<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>HeoBrain</title>
    <link>https://onethingflow.tistory.com/</link>
    <description>빠르게 변화하는 세상에서, 변화에 도움이 되는 지식을 전하기 위해 매일 배운 것들을 진심으로 기록하고 있습니다.
함께 성장해 나가요.</description>
    <language>ko</language>
    <pubDate>Thu, 30 Jul 2026 20:59:32 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>거대웅 TitanBear</managingEditor>
    <image>
      <title>HeoBrain</title>
      <url>https://tistory1.daumcdn.net/tistory/6687043/attach/182773c6090d4a02b384594efcbe8882</url>
      <link>https://onethingflow.tistory.com</link>
    </image>
    <item>
      <title>Day19)programmers-문자열 분리, 반복 추가, 빈 배열 추가&amp;middot;삭제, 스택, K개 수 뽑기</title>
      <link>https://onethingflow.tistory.com/entry/Day19programmers-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%B6%84%EB%A6%AC-%EB%B0%98%EB%B3%B5-%EC%B6%94%EA%B0%80-%EB%B9%88-%EB%B0%B0%EC%97%B4-%EC%B6%94%EA%B0%80%C2%B7%EC%82%AD%EC%A0%9C-%EC%8A%A4%ED%83%9D-K%EA%B0%9C-%EC%88%98-%EB%BD%91%EA%B8%B0</link>
      <description>&lt;!--
Title: 프로그래머스 파이썬 - 문자열 분리와 리스트·스택 조작 5문제 정리
Meta description: 세 개의 구분자, 배열 반복 추가, 빈 배열 추가·삭제, 배열 만들기 6, 무작위 K개 뽑기를 사용자 코드의 실수와 함께 초보자 눈높이로 정리합니다.
Suggested tags: 파이썬, Python, 프로그래머스, 문자열분리, 리스트, 스택, 코딩테스트
--&gt;
&lt;style&gt;&lt;/style&gt;
&lt;article class=&quot;hb-post hb-string-list-stack hb-paste-safe&quot; style=&quot;box-sizing:border-box;max-width:760px;margin:0 auto;padding:24px 18px;color:#1f2937;background:#ffffff;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;line-height:1.78;word-break:keep-all;overflow-wrap:anywhere;&quot;&gt;
  &lt;header style=&quot;margin:0 0 32px;padding:0 0 22px;border-bottom:1px solid #e5e7eb;&quot;&gt;
    &lt;p style=&quot;margin:0 0 8px;color:#2563eb;font-size:14px;font-weight:700;&quot;&gt;Programmers | Python study note&lt;/p&gt;
    &lt;h1 style=&quot;margin:0 0 14px;color:#111827;font-size:30px;line-height:1.35;letter-spacing:0;&quot;&gt;문자열 분리와 리스트·스택 조작 5문제 정리&lt;/h1&gt;
    &lt;p style=&quot;margin:0;color:#4b5563;font-size:16px;&quot;&gt;문자열을 여러 기준으로 나누는 방법부터 리스트에 여러 값을 넣고 빼는 방법, 스택으로 인접한 같은 값을 처리하는 방법까지. 처음 작성한 코드에서 왜 오류가 났는지와 Python답게 다듬는 흐름을 함께 기록했다.&lt;/p&gt;
  &lt;/header&gt;

  &lt;section style=&quot;margin:0 0 32px;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 12px;font-size:23px;line-height:1.4;color:#111827;&quot;&gt;오늘의 문제와 핵심 개념&lt;/h2&gt;
    &lt;div style=&quot;overflow-x:auto;&quot;&gt;
      &lt;table style=&quot;width:100%;min-width:600px;border-collapse:collapse;font-size:14px;&quot;&gt;
        &lt;caption style=&quot;caption-side:top;text-align:left;padding:0 0 8px;color:#374151;font-weight:700;&quot;&gt;공식 문제 링크&lt;/caption&gt;
        &lt;thead&gt;&lt;tr&gt;&lt;th scope=&quot;col&quot; style=&quot;padding:10px;border:1px solid #d1d5db;background:#f9fafb;text-align:left;&quot;&gt;문제&lt;/th&gt;&lt;th scope=&quot;col&quot; style=&quot;padding:10px;border:1px solid #d1d5db;background:#f9fafb;text-align:left;&quot;&gt;핵심&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
        &lt;tbody&gt;
          &lt;tr&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181862&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2563eb;font-weight:700;&quot;&gt;세 개의 구분자&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;replace, split, extend, 빈 리스트 처리&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181861&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2563eb;font-weight:700;&quot;&gt;배열의 원소만큼 추가하기&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;반복 횟수 초기화, 리스트 곱셈, 이중 컴프리헨션&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181860&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2563eb;font-weight:700;&quot;&gt;빈 배열에 추가, 삭제하기&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;zip, +=, extend, del, 슬라이싱&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181859&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2563eb;font-weight:700;&quot;&gt;배열 만들기 6&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;스택, pop, 빈 리스트 안전 확인&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181858&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2563eb;font-weight:700;&quot;&gt;무작위로 K개의 수 뽑기&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;중복 제거, break, 부족한 값 채우기&lt;/td&gt;&lt;/tr&gt;
        &lt;/tbody&gt;
      &lt;/table&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section style=&quot;margin:0 0 36px;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 14px;font-size:24px;line-height:1.4;color:#111827;&quot;&gt;1. 세 개의 구분자: 여러 번 나누려다 데이터가 꼬일 때&lt;/h2&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;문자열에서 a, b, c를 모두 구분자로 삼아 나누는 문제다. 처음에는 a로 나누고, 나온 조각을 다시 b와 c로 나누는 방식으로 접근할 수 있다. 방향은 맞지만 리스트를 다루는 방식이 중요하다.&lt;/p&gt;
    &lt;h3 style=&quot;margin:0 0 8px;font-size:18px;color:#111827;&quot;&gt;처음 시도에서 생긴 문제&lt;/h3&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(myStr):
    answer = []
    for char in myStr.split(&quot;a&quot;):
        answer = &quot;&quot;.join(char)
    ...&lt;/code&gt;&lt;/pre&gt;
    &lt;div style=&quot;margin:0 0 12px;padding:14px;border-left:4px solid #f59e0b;background:#fffbeb;&quot;&gt;
      &lt;p style=&quot;margin:0 0 8px;&quot;&gt;&lt;strong&gt;= 는 덮어쓰기다.&lt;/strong&gt; 반복할 때마다 새 값을 대입하면 앞에서 얻은 조각은 사라지고 마지막 조각만 남는다.&lt;/p&gt;
      &lt;p style=&quot;margin:0 0 8px;&quot;&gt;&lt;strong&gt;split()의 결과는 리스트다.&lt;/strong&gt; &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;append(char.split(&quot;b&quot;))&lt;/code&gt;는 리스트 안에 또 리스트를 넣는다. 다음 단계에서 꺼낸 값은 문자열이 아니라 리스트가 되어 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;split()&lt;/code&gt;을 쓸 수 없다.&lt;/p&gt;
      &lt;p style=&quot;margin:0 0 8px;&quot;&gt;&lt;strong&gt;순회 중인 리스트에 append하지 않는다.&lt;/strong&gt; &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;for item in answer&lt;/code&gt; 안에서 같은 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;answer&lt;/code&gt;에 계속 추가하면 반복 대상이 끝없이 늘어날 수 있다.&lt;/p&gt;
      &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;리스트와 문자열은 다르다.&lt;/strong&gt; &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;answer == &quot;&quot;&lt;/code&gt;이 아니라 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;not answer&lt;/code&gt; 또는 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;answer == []&lt;/code&gt;로 빈 리스트를 확인한다.&lt;/p&gt;
    &lt;/div&gt;
    &lt;h3 style=&quot;margin:0 0 8px;font-size:18px;color:#111827;&quot;&gt;내 생각을 그대로 살린 단계별 풀이&lt;/h3&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(myStr):
    step1 = myStr.split(&quot;a&quot;)

    step2 = []
    for text in step1:
        step2.extend(text.split(&quot;b&quot;))

    step3 = []
    for text in step2:
        step3.extend(text.split(&quot;c&quot;))

    answer = []
    for text in step3:
        if text != &quot;&quot;:
            answer.append(text)

    return answer if answer else [&quot;EMPTY&quot;]&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;&lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;append()&lt;/code&gt;는 값을 하나의 원소로 넣고, &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;extend()&lt;/code&gt;는 리스트의 원소를 풀어서 넣는다. 그래서 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;split()&lt;/code&gt; 결과를 이어 붙일 때는 extend가 알맞다.&lt;/p&gt;
    &lt;h3 style=&quot;margin:0 0 8px;font-size:18px;color:#111827;&quot;&gt;더 간단한 기본 풀이: 구분자를 공백으로 통일하기&lt;/h3&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(myStr):
    answer = myStr.replace(&quot;a&quot;, &quot; &quot;).replace(&quot;b&quot;, &quot; &quot;).replace(&quot;c&quot;, &quot; &quot;).split()
    return answer if answer else [&quot;EMPTY&quot;]&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;여기서 공백 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;&quot; &quot;&lt;/code&gt;과 빈 문자열 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;&quot;&quot;&lt;/code&gt;을 구분해야 한다. 빈 문자열로 바꾸면 구분자가 삭제되어 양옆 글자가 붙고, 공백으로 바꾸면 split이 나눌 경계가 남는다. 또한 인수 없이 쓰는 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;split()&lt;/code&gt;은 연속된 공백과 빈 조각을 자동으로 무시하므로 별도의 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;if x&lt;/code&gt; 필터가 필요 없다.&lt;/p&gt;
    &lt;h3 style=&quot;margin:0 0 8px;font-size:18px;color:#111827;&quot;&gt;선택 풀이: 정규표현식&lt;/h3&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;import re

def solution(myStr):
    answer = re.findall(r&quot;[^abc]+&quot;, myStr)
    return answer if answer else [&quot;EMPTY&quot;]&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;정규표현식 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;[^abc]+&lt;/code&gt;는 a, b, c가 아닌 문자가 한 글자 이상 이어진 덩어리를 찾는다. 고정된 구분자 세 개만 처리하는 이 문제에서는 replace와 split이 더 쉽게 읽히며, 정규표현식은 구분 규칙이 복잡해질 때 유용하다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;section style=&quot;margin:0 0 36px;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 14px;font-size:24px;line-height:1.4;color:#111827;&quot;&gt;2. 배열의 원소만큼 추가하기: 횟수 변수는 매번 새로 시작한다&lt;/h2&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(arr):
    answer = []
    cnt = 0

    for char in arr:
        while char &amp;gt; cnt:
            answer.append(char)
            cnt += 1
    return answer&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;첫 번째 원소를 처리한 뒤에도 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;cnt&lt;/code&gt; 값이 남아 있는 것이 문제다. 예를 들어 [3, 1]에서 3을 처리하면 cnt는 3이 되고, 다음 1은 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;1 &amp;gt; 3&lt;/code&gt;이 거짓이라 추가되지 않는다. 원소 하나마다 횟수는 0부터 다시 세야 한다.&lt;/p&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(arr):
    answer = []
    for num in arr:
        cnt = 0
        while cnt &amp;lt; num:
            answer.append(num)
            cnt += 1
    return answer&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;같은 값을 여러 번 넣는 일은 리스트 곱셈으로 더 직접적으로 표현할 수 있다. &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;[num] * num&lt;/code&gt;은 num이 들어 있는 리스트를 num번 반복한 새 리스트다.&lt;/p&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(arr):
    answer = []
    for num in arr:
        answer.extend([num] * num)
    return answer&lt;/code&gt;&lt;/pre&gt;
    &lt;pre style=&quot;margin:0;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(arr):
    return [num for num in arr for _ in range(num)]&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:12px 0 0;&quot;&gt;마지막 코드는 이중 for문을 한 줄로 쓴 것이다. 바깥쪽에서 num을 꺼내고, 안쪽에서 num번 반복해 맨 앞의 num을 결과에 넣는다. 반복 횟수만 필요하고 그 값은 쓰지 않을 때는 관례적으로 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;_&lt;/code&gt;를 쓴다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;section style=&quot;margin:0 0 36px;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 14px;font-size:24px;line-height:1.4;color:#111827;&quot;&gt;3. 빈 배열에 추가, 삭제하기: pop은 개수가 아니라 위치를 받는다&lt;/h2&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(arr, flag):
    answer = []
    for i, value in enumerate(flag):
        if value:
            answer.extend([arr[i]] * arr[i] * 2)
        else:
            answer.pop(arr[i])
    return answer&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;참일 때 여러 값을 넣는 부분은 맞다. 하지만 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;pop(n)&lt;/code&gt;은 “뒤에서 n개를 삭제”가 아니라 “인덱스 n의 원소 하나를 꺼내기”다. 마지막에서 여러 개를 지우려면 슬라이싱이나 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;del&lt;/code&gt;을 사용한다.&lt;/p&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(arr, flag):
    answer = []

    for num, is_true in zip(arr, flag):
        if is_true:
            answer += [num] * (num * 2)
        else:
            del answer[-num:]

    return answer&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;&lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;zip(arr, flag)&lt;/code&gt;은 두 배열에서 같은 위치의 값을 함께 꺼낸다. 그래서 인덱스를 얻고 다시 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;arr[i]&lt;/code&gt;를 찾을 필요가 없다. &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;del answer[-num:]&lt;/code&gt;은 기존 리스트의 뒤 num개를 제자리에서 지운다.&lt;/p&gt;
    &lt;div style=&quot;overflow-x:auto;&quot;&gt;
      &lt;table style=&quot;width:100%;min-width:580px;border-collapse:collapse;font-size:14px;&quot;&gt;
        &lt;caption style=&quot;caption-side:top;text-align:left;padding:0 0 8px;color:#374151;font-weight:700;&quot;&gt;리스트에 값을 더할 때의 차이&lt;/caption&gt;
        &lt;thead&gt;&lt;tr&gt;&lt;th scope=&quot;col&quot; style=&quot;padding:10px;border:1px solid #d1d5db;background:#f9fafb;text-align:left;&quot;&gt;코드&lt;/th&gt;&lt;th scope=&quot;col&quot; style=&quot;padding:10px;border:1px solid #d1d5db;background:#f9fafb;text-align:left;&quot;&gt;결과&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
        &lt;tbody&gt;
          &lt;tr&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;[1, 2] + [3, 4]&lt;/code&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;[1, 2, 3, 4]&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;answer += [3, 4]&lt;/code&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;리스트 원소를 뒤에 이어 붙임&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;answer.extend([3, 4])&lt;/code&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;+=와 같은 모양으로 원소를 이어 붙임&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;answer.append([3, 4])&lt;/code&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;[1, 2, [3, 4]]처럼 리스트 하나를 원소로 넣음&lt;/td&gt;&lt;/tr&gt;
        &lt;/tbody&gt;
      &lt;/table&gt;
    &lt;/div&gt;
    &lt;p style=&quot;margin:12px 0 0;&quot;&gt;더하기 기호는 같은 종류끼리 사용한다. 리스트와 리스트, 문자열과 문자열, 숫자와 숫자는 가능하지만 리스트와 문자열 또는 문자열과 숫자를 더하면 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;TypeError&lt;/code&gt;가 난다. 따라서 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;answer += [num] * ...&lt;/code&gt;은 리스트에 리스트를 더하는 형태라 정상 동작한다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;section style=&quot;margin:0 0 36px;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 14px;font-size:24px;line-height:1.4;color:#111827;&quot;&gt;4. 배열 만들기 6: 스택의 마지막 값과 현재 값을 비교하기&lt;/h2&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;이 문제는 현재 값이 스택의 마지막 값과 같으면 마지막 값을 제거하고, 다르면 현재 값을 넣는다. 비어 있으면 당연히 넣는다.&lt;/p&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;for i in arr:
    if arr[i] != stk[-1]:
        ...&lt;/code&gt;&lt;/pre&gt;
    &lt;div style=&quot;margin:0 0 12px;padding:14px;border-left:4px solid #f59e0b;background:#fffbeb;&quot;&gt;
      &lt;p style=&quot;margin:0 0 8px;&quot;&gt;&lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;for i in arr&lt;/code&gt;에서 i는 인덱스가 아니라 실제 값이다. i를 그대로 사용하거나, 인덱스가 필요할 때만 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;enumerate()&lt;/code&gt;를 쓴다.&lt;/p&gt;
      &lt;p style=&quot;margin:0 0 8px;&quot;&gt;빈 리스트에서 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;stk[-1]&lt;/code&gt;을 읽으면 오류가 난다. 먼저 스택이 비었는지 확인해야 한다.&lt;/p&gt;
      &lt;p style=&quot;margin:0 0 8px;&quot;&gt;&lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;pop()&lt;/code&gt;은 괄호를 비우면 마지막 원소 하나를 제거한다. &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;pop(value)&lt;/code&gt;는 값을 지우는 문법이 아니다.&lt;/p&gt;
      &lt;p style=&quot;margin:0;&quot;&gt;for문은 다음 원소로 자동 이동하므로, 문제 지문의 “i에 1을 더한다”를 그대로 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;i += 1&lt;/code&gt;로 옮길 필요가 없다.&lt;/p&gt;
    &lt;/div&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(arr):
    stk = []

    for value in arr:
        if not stk:
            stk.append(value)
        elif stk[-1] != value:
            stk.append(value)
        else:
            stk.pop()

    return stk if stk else [-1]&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;첫 조건에서 값을 넣었다면 그 반복에서는 다른 조건을 실행하면 안 된다. 그래서 서로 하나만 실행할 조건은 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;if&lt;/code&gt; 다음에 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;elif&lt;/code&gt;, &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;else&lt;/code&gt;로 묶는다.&lt;/p&gt;
    &lt;pre style=&quot;margin:0;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(arr):
    stk = []

    for value in arr:
        if stk and stk[-1] == value:
            stk.pop()
        else:
            stk.append(value)

    return stk or [-1]&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:12px 0 0;&quot;&gt;&lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;if stk and ...&lt;/code&gt;는 왼쪽부터 확인한다. 스택이 비어 있으면 뒤의 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;stk[-1]&lt;/code&gt;을 읽지 않으므로 안전하다. 빈 리스트는 거짓으로 취급되므로 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;stk or [-1]&lt;/code&gt;은 스택이 비면 [-1], 아니면 stk를 반환한다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;section style=&quot;margin:0 0 36px;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 14px;font-size:24px;line-height:1.4;color:#111827;&quot;&gt;5. 무작위로 K개의 수 뽑기: 채우는 작업은 반복문 뒤에서&lt;/h2&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(arr, k):
    answer = []
    for value in arr:
        if value not in answer:
            answer.append(value)
        elif not answer[:k]:
            while len(answer) &amp;gt; k:
                answer.append(-1)
    return answer&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;-1은 중복을 만났을 때 채우는 값이 아니다. arr를 끝까지 확인하거나 k개를 이미 모은 뒤, 결과가 부족할 때만 채워야 한다. 또 원소를 추가하는 while문은 길이가 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;k보다 작을 때&lt;/code&gt; 돌아야 한다. 길이가 k보다 큰데 계속 추가하면 멈출 수 없다.&lt;/p&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(arr, k):
    answer = []

    for value in arr:
        if value not in answer:
            answer.append(value)

        if len(answer) == k:
            break

    while len(answer) &amp;lt; k:
        answer.append(-1)

    return answer&lt;/code&gt;&lt;/pre&gt;
    &lt;pre style=&quot;margin:0;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(arr, k):
    answer = []

    for value in arr:
        if value not in answer:
            answer.append(value)
        if len(answer) == k:
            break

    answer.extend([-1] * (k - len(answer)))
    return answer&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:12px 0 0;&quot;&gt;두 번째 풀이는 부족한 개수만큼 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;[-1]&lt;/code&gt;을 반복해 한 번에 이어 붙인다. &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;break&lt;/code&gt;를 넣으면 필요한 k개를 다 모은 뒤에는 뒤의 입력을 더 볼 필요가 없다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;section style=&quot;margin:0 0 28px;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 14px;font-size:23px;line-height:1.4;color:#111827;&quot;&gt;이번 기록에서 챙길 실수 방지 포인트&lt;/h2&gt;
    &lt;div style=&quot;display:grid;gap:10px;&quot;&gt;
      &lt;div style=&quot;display:grid;grid-template-columns:28px 1fr;gap:10px;align-items:start;padding:12px;border:1px solid #e5e7eb;border-radius:6px;&quot;&gt;&lt;span style=&quot;display:inline-flex;width:26px;height:26px;border-radius:50%;background:#111827;color:#fff;align-items:center;justify-content:center;font-size:12px;font-weight:700;&quot;&gt;1&lt;/span&gt;&lt;p style=&quot;margin:0;&quot;&gt;split() 결과는 리스트다. 리스트를 문자열과 비교하지 않는다.&lt;/p&gt;&lt;/div&gt;
      &lt;div style=&quot;display:grid;grid-template-columns:28px 1fr;gap:10px;align-items:start;padding:12px;border:1px solid #e5e7eb;border-radius:6px;&quot;&gt;&lt;span style=&quot;display:inline-flex;width:26px;height:26px;border-radius:50%;background:#111827;color:#fff;align-items:center;justify-content:center;font-size:12px;font-weight:700;&quot;&gt;2&lt;/span&gt;&lt;p style=&quot;margin:0;&quot;&gt;리스트를 순회하면서 같은 리스트에 계속 추가하지 않는다. 필요하면 새 리스트를 만든다.&lt;/p&gt;&lt;/div&gt;
      &lt;div style=&quot;display:grid;grid-template-columns:28px 1fr;gap:10px;align-items:start;padding:12px;border:1px solid #e5e7eb;border-radius:6px;&quot;&gt;&lt;span style=&quot;display:inline-flex;width:26px;height:26px;border-radius:50%;background:#111827;color:#fff;align-items:center;justify-content:center;font-size:12px;font-weight:700;&quot;&gt;3&lt;/span&gt;&lt;p style=&quot;margin:0;&quot;&gt;append는 원소 하나, extend와 +=는 다른 리스트의 원소를 이어 붙인다.&lt;/p&gt;&lt;/div&gt;
      &lt;div style=&quot;display:grid;grid-template-columns:28px 1fr;gap:10px;align-items:start;padding:12px;border:1px solid #e5e7eb;border-radius:6px;&quot;&gt;&lt;span style=&quot;display:inline-flex;width:26px;height:26px;border-radius:50%;background:#111827;color:#fff;align-items:center;justify-content:center;font-size:12px;font-weight:700;&quot;&gt;4&lt;/span&gt;&lt;p style=&quot;margin:0;&quot;&gt;pop()은 마지막 하나를 뺀다. 여러 개 삭제에는 슬라이싱이나 del을 쓴다.&lt;/p&gt;&lt;/div&gt;
      &lt;div style=&quot;display:grid;grid-template-columns:28px 1fr;gap:10px;align-items:start;padding:12px;border:1px solid #e5e7eb;border-radius:6px;&quot;&gt;&lt;span style=&quot;display:inline-flex;width:26px;height:26px;border-radius:50%;background:#111827;color:#fff;align-items:center;justify-content:center;font-size:12px;font-weight:700;&quot;&gt;5&lt;/span&gt;&lt;p style=&quot;margin:0;&quot;&gt;for value in arr에서 value는 원소다. arr[value]처럼 인덱스로 다시 쓰지 않는다.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;footer style=&quot;padding-top:18px;border-top:1px solid #e5e7eb;&quot;&gt;&lt;p style=&quot;margin:0;color:#4b5563;&quot;&gt;문자열과 리스트 문제는 한 번에 짧게 쓰는 것보다, 자료형과 데이터 흐름이 바뀌는 지점을 분명히 보는 편이 먼저다. 기본 풀이가 이해되면 replace, split, extend, zip, del 같은 도구가 왜 코드를 줄여 주는지도 자연스럽게 보인다.&lt;/p&gt;&lt;/footer&gt;
&lt;/article&gt;</description>
      <category>AI/Coding_Test</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/133</guid>
      <comments>https://onethingflow.tistory.com/entry/Day19programmers-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%B6%84%EB%A6%AC-%EB%B0%98%EB%B3%B5-%EC%B6%94%EA%B0%80-%EB%B9%88-%EB%B0%B0%EC%97%B4-%EC%B6%94%EA%B0%80%C2%B7%EC%82%AD%EC%A0%9C-%EC%8A%A4%ED%83%9D-K%EA%B0%9C-%EC%88%98-%EB%BD%91%EA%B8%B0#entry133comment</comments>
      <pubDate>Thu, 30 Jul 2026 08:29:59 +0900</pubDate>
    </item>
    <item>
      <title>Day13)정처기 1과목 요구사항 확인&amp;middot;화면 설계 정리 | p.1-2~p.1-55</title>
      <link>https://onethingflow.tistory.com/entry/Day13%EC%A0%95%EC%B2%98%EA%B8%B0-1%EA%B3%BC%EB%AA%A9-%EC%9A%94%EA%B5%AC%EC%82%AC%ED%95%AD-%ED%99%95%EC%9D%B8%C2%B7%ED%99%94%EB%A9%B4-%EC%84%A4%EA%B3%84-%EC%A0%95%EB%A6%AC-p1-2p1-55</link>
      <description>&lt;!-- 티스토리 제목: 정처기 1과목 요구사항 확인·화면 설계 정리 | p.1-2~p.1-55 --&gt;
&lt;!-- 메타 설명: 정보처리기사 실기 1과목 요구사항 확인과 화면 설계를 초보자용으로 정리합니다. 현행 시스템 분석, 기능·비기능 요구사항, UML 분석 모델, UI 설계 원칙을 한 번에 복습합니다. --&gt;
&lt;style&gt;&lt;/style&gt;
&lt;article class=&quot;hb-post hb-jeongcheogi-requirements-ui&quot; style=&quot;max-width:780px;margin:0 auto;color:#1f2937;font-size:17px;line-height:1.82;word-break:keep-all;overflow-wrap:break-word;&quot;&gt;
  &lt;p style=&quot;margin:0 0 10px;color:#52606d;font-size:14px;&quot;&gt;정처기 공부 기록 · 7월 29일 · 실기 1과목&lt;/p&gt;
  &lt;h1 style=&quot;margin:0 0 18px;color:#111827;font-size:32px;line-height:1.32;letter-spacing:-0.04em;&quot;&gt;요구사항 확인 · 화면 설계&lt;br&gt;p.1-2~p.1-55&lt;/h1&gt;
  &lt;div style=&quot;margin:0 0 28px;padding:19px 20px;border:1px solid #dbe7ff;border-radius:14px;background:#f5f8ff;&quot;&gt;
    &lt;p style=&quot;margin:0 0 8px;color:#2458bc;font-weight:700;&quot;&gt;오늘의 한 줄 목표&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;좋은 프로그램은 코딩부터 시작하지 않는다. &lt;strong&gt;무엇을 만들어야 하는지 정확히 확인하고, 사용자가 이해할 화면으로 설계하는 것&lt;/strong&gt;부터 시작한다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:36px 0 14px;color:#111827;font-size:24px;&quot;&gt;1. 오늘 공부한 내용&lt;/h2&gt;
  &lt;p style=&quot;margin:0 0 15px;&quot;&gt;오늘 범위는 1과목의 &lt;strong&gt;01. 요구사항 확인&lt;/strong&gt;과 &lt;strong&gt;02. 화면 설계&lt;/strong&gt;입니다. 현행 시스템을 파악한 뒤 이해관계자의 요구를 수집·분석·검증하고, 그 결과를 사용하기 쉬운 화면(UI)으로 표현하는 흐름을 다룹니다.&lt;/p&gt;

  &lt;div style=&quot;margin:16px 0 26px;border:1px solid #d9e2ef;border-radius:14px;overflow:hidden;background:#fff;&quot;&gt;
    &lt;div style=&quot;padding:15px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;display:inline-block;width:28px;height:28px;margin-right:10px;border-radius:8px;background:#315efb;color:#fff;text-align:center;line-height:28px;&quot;&gt;1&lt;/strong&gt;&lt;strong&gt;현행 시스템 분석&lt;/strong&gt;&lt;br&gt;&lt;span style=&quot;display:block;margin-left:40px;color:#52606d;font-size:15px;&quot;&gt;현재 업무·사용자·장비·소프트웨어·데이터·연계 시스템과 문제점을 조사&lt;/span&gt;&lt;/div&gt;
    &lt;div style=&quot;padding:15px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;display:inline-block;width:28px;height:28px;margin-right:10px;border-radius:8px;background:#315efb;color:#fff;text-align:center;line-height:28px;&quot;&gt;2&lt;/strong&gt;&lt;strong&gt;요구사항 확인&lt;/strong&gt;&lt;br&gt;&lt;span style=&quot;display:block;margin-left:40px;color:#52606d;font-size:15px;&quot;&gt;기능·비기능 요구사항을 수집하고 우선순위·완전성·일관성을 검증&lt;/span&gt;&lt;/div&gt;
    &lt;div style=&quot;padding:15px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;display:inline-block;width:28px;height:28px;margin-right:10px;border-radius:8px;background:#315efb;color:#fff;text-align:center;line-height:28px;&quot;&gt;3&lt;/strong&gt;&lt;strong&gt;분석 모델 확인&lt;/strong&gt;&lt;br&gt;&lt;span style=&quot;display:block;margin-left:40px;color:#52606d;font-size:15px;&quot;&gt;유스케이스·클래스·시퀀스·상태 다이어그램으로 요구사항을 구조화&lt;/span&gt;&lt;/div&gt;
    &lt;div style=&quot;padding:15px 16px;&quot;&gt;&lt;strong style=&quot;display:inline-block;width:28px;height:28px;margin-right:10px;border-radius:8px;background:#315efb;color:#fff;text-align:center;line-height:28px;&quot;&gt;4&lt;/strong&gt;&lt;strong&gt;UI 요구사항·화면 설계&lt;/strong&gt;&lt;br&gt;&lt;span style=&quot;display:block;margin-left:40px;color:#52606d;font-size:15px;&quot;&gt;사용자·업무·환경을 고려해 직관적이고 일관된 화면과 흐름을 설계&lt;/span&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;현행 시스템 분석: 새로 만들기 전에 현재를 안다&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 15px;&quot;&gt;현행 시스템 분석은 ‘지금 무엇을 쓰고 있는가’를 파악하는 일입니다. 단순한 장비 목록이 아니라, 업무가 어떻게 흐르고 어디에서 불편·오류·중복이 생기는지까지 확인해야 새 시스템의 요구사항을 제대로 정할 수 있습니다.&lt;/p&gt;
  &lt;div style=&quot;margin:0 0 22px;padding:18px;border:1px solid #d9e2ef;border-radius:14px;background:#fff;&quot;&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;업무·사용자&lt;/strong&gt; — 누가 어떤 업무를 어떤 순서로 하는지, 수작업·중복 입력·승인 지연 같은 문제는 무엇인지 확인합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;기술 환경&lt;/strong&gt; — 서버·PC·모바일, 운영체제, DBMS, 네트워크, 보안 장비, 기존 소프트웨어와 버전을 조사합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;데이터&lt;/strong&gt; — 어떤 데이터가 어디에 저장되는지, 데이터의 양·품질·중복·개인정보 여부와 이행 필요성을 확인합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;연계 시스템&lt;/strong&gt; — 외부 기관·결제·인증·사내 시스템 등과 어떤 방식으로 데이터를 주고받는지, 인터페이스 제약은 무엇인지 파악합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;제약사항&lt;/strong&gt; — 예산, 일정, 법·규정, 보안 기준, 기존 장비 활용 여부, 운영 인력과 같은 현실적인 제한도 요구사항의 일부입니다.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div style=&quot;margin:0 0 22px;padding:17px 18px;border-radius:12px;background:#fff8e7;border:1px solid #f2d490;&quot;&gt;
    &lt;p style=&quot;margin:0 0 7px;color:#805100;font-weight:700;&quot;&gt;초보자식으로 말하면&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;카페 주문 앱을 새로 만든다고 할 때, 현행 시스템 분석은 ‘현재 주문을 종이로 받는지·POS는 무엇인지·누가 재고를 수정하는지·배달 앱과 연동하는지·피크 시간에 주문이 얼마나 몰리는지’를 알아보는 단계입니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;요구사항: 사용자가 원하는 것과 시스템이 지켜야 할 것&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 15px;&quot;&gt;&lt;strong&gt;요구사항&lt;/strong&gt;은 시스템이 제공해야 할 기능과 만족해야 할 조건을 문서로 명확히 한 것입니다. “좋은 앱으로 만들어 주세요”는 요구사항이 아닙니다. 누가, 어떤 상황에서, 무엇을, 어느 수준으로 할 수 있어야 하는지 구체적으로 표현해야 합니다.&lt;/p&gt;
  &lt;div style=&quot;margin:0 0 20px;border:1px solid #d9e2ef;border-radius:14px;overflow-x:auto;background:#fff;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:660px;border-collapse:collapse;font-size:15px;line-height:1.65;&quot;&gt;
      &lt;thead&gt;&lt;tr style=&quot;background:#f1f5ff;color:#223f7a;&quot;&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;구분&lt;/th&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;무엇을 말하나?&lt;/th&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;예시&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;기능 요구사항&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;시스템이 &lt;strong&gt;무엇을 해야 하는지&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;사용자는 주문을 등록·취소할 수 있어야 한다.&lt;/td&gt;&lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfe;&quot;&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;성능 요구사항&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;처리 시간·동시 사용자·처리량&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;동시 1,000명 접속 시 주문 조회는 3초 이내여야 한다.&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;보안 요구사항&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;인증, 권한, 개인정보, 감사 기록&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;관리자 기능은 승인된 계정만 사용할 수 있어야 한다.&lt;/td&gt;&lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfe;&quot;&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;품질·운영 요구사항&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;가용성, 유지보수성, 호환성, 법·규정&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;장애 발생 후 2시간 안에 서비스를 복구할 수 있어야 한다.&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;요구사항을 얻고, 분석하고, 검증하는 과정&lt;/h3&gt;
  &lt;div style=&quot;margin:0 0 22px;padding:18px;border-left:4px solid #315efb;background:#f6f8ff;&quot;&gt;
    &lt;p style=&quot;margin:0 0 8px;&quot;&gt;&lt;strong&gt;1) 도출(Elicitation)&lt;/strong&gt; — 인터뷰, 설문, 워크숍, 관찰, 기존 문서 분석, 프로토타입 등을 통해 이해관계자의 요구를 수집합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 8px;&quot;&gt;&lt;strong&gt;2) 분석(Analysis)&lt;/strong&gt; — 모호한 표현을 구체화하고, 서로 충돌하는 요구를 조정하며, 우선순위·범위·실현 가능성을 판단합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 8px;&quot;&gt;&lt;strong&gt;3) 명세(Specification)&lt;/strong&gt; — 합의한 요구를 문서·모델·화면 정의서 등으로 기록해 개발자와 사용자가 같은 내용을 보게 합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;4) 검증(Validation)&lt;/strong&gt; — 빠진 것은 없는지, 모순은 없는지, 시험 가능한지, 실제 업무 목적에 맞는지 검토합니다.&lt;/p&gt;
  &lt;/div&gt;
  &lt;p style=&quot;margin:0 0 20px;&quot;&gt;IIBA의 요구사항 분석 체계도 이해관계자 정보 수집과 결과 확인, 그리고 요구사항의 분석·설계·검증을 분리된 중요한 활동으로 봅니다. 즉, 인터뷰로 들은 말을 그대로 적는 것만으로는 충분하지 않습니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;좋은 요구사항의 조건&lt;/h3&gt;
  &lt;div style=&quot;margin:0 0 22px;border:1px solid #d9e2ef;border-radius:14px;overflow:hidden;background:#fff;&quot;&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;완전성&lt;/strong&gt; — 필요한 기능·예외 상황·제약이 빠지지 않아야 합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;border-bottom:1px solid #e7edf5;background:#fbfcfe;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;일관성&lt;/strong&gt; — 서로 모순되는 문장이 없어야 합니다. 예를 들어 ‘누구나 수정 가능’과 ‘관리자만 수정 가능’이 함께 있으면 안 됩니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;명확성&lt;/strong&gt; — ‘빠르게’, ‘편리하게’ 같은 말 대신 숫자·조건·대상을 넣어 해석이 하나로 되게 합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;border-bottom:1px solid #e7edf5;background:#fbfcfe;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;검증 가능성&lt;/strong&gt; — 개발 후 시험으로 충족 여부를 판단할 수 있어야 합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;추적 가능성&lt;/strong&gt; — 요구사항이 설계·코드·테스트 케이스의 어디에 반영됐는지 연결해서 확인할 수 있어야 합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;background:#fbfcfe;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;변경 가능성&lt;/strong&gt; — 요구가 바뀌었을 때 영향 범위를 찾고 이력을 관리할 수 있어야 합니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;분석 모델: 말로만 설명하지 않고 그림으로 확인하기&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 15px;&quot;&gt;분석 모델은 복잡한 요구사항을 표준화된 그림으로 표현하는 방법입니다. 정처기에서는 UML 다이어그램의 역할을 구분하는 문제가 자주 나옵니다.&lt;/p&gt;
  &lt;div style=&quot;margin:0 0 20px;border:1px solid #d9e2ef;border-radius:14px;overflow-x:auto;background:#fff;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:650px;border-collapse:collapse;font-size:15px;line-height:1.65;&quot;&gt;
      &lt;thead&gt;&lt;tr style=&quot;background:#eef7f4;color:#17624f;&quot;&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;모델&lt;/th&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;무엇을 보여 주나?&lt;/th&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;문제 단서&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;유스케이스 다이어그램&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;외부 사용자(액터)와 시스템 기능의 관계&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;누가 어떤 기능을 사용하는가&lt;/td&gt;&lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfe;&quot;&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;클래스 다이어그램&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;클래스의 속성·연산과 클래스 사이 구조&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;객체의 정적인 구조&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;시퀀스 다이어그램&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;객체들이 시간 순서에 따라 주고받는 메시지&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;세로축 시간, 메시지 흐름&lt;/td&gt;&lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfe;&quot;&gt;&lt;td style=&quot;padding:10px;&quot;&gt;&lt;strong&gt;상태 다이어그램&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;&quot;&gt;객체가 사건에 따라 바뀌는 상태와 전이&lt;/td&gt;&lt;td style=&quot;padding:10px;&quot;&gt;대기·승인·취소 같은 상태 변화&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;UI 요구사항과 화면 설계&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 15px;&quot;&gt;UI(User Interface)는 사용자가 시스템과 만나는 접점입니다. 화면을 예쁘게 꾸미는 것만이 아니라, 사용자가 실수 없이 목적을 달성하도록 입력·출력·선택·오류 안내·화면 이동을 설계하는 일입니다. 사람 중심 설계는 사용성·접근성을 개발 과정 전반에서 고려하는 접근입니다.&lt;/p&gt;
  &lt;div style=&quot;margin:0 0 22px;padding:18px;border:1px solid #d9e2ef;border-radius:14px;background:#fff;&quot;&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;사용자 요구&lt;/strong&gt; — 초보자·숙련자·관리자 등 사용자 유형, 자주 하는 업무, 접근성·언어·기기 환경을 확인합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;기능·정보 요구&lt;/strong&gt; — 화면마다 보여 줄 정보, 입력 항목, 필수값, 계산·검증 규칙, 오류 메시지와 버튼 동작을 정의합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;화면 흐름&lt;/strong&gt; — 로그인 후 어디로 가는지, 목록에서 상세로 어떻게 들어가는지, 저장·취소 뒤 어디로 돌아가는지를 설계합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;프로토타입&lt;/strong&gt; — 실제 코딩 전 와이어프레임이나 시안을 보여 주고 피드백을 받으면, 요구사항 오해를 빨리 줄일 수 있습니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;UI 설계 원칙: ‘직유학연’&lt;/h3&gt;
  &lt;div style=&quot;margin:0 0 22px;border:1px solid #d9e2ef;border-radius:14px;overflow:hidden;background:#fff;&quot;&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;직관성&lt;/strong&gt; — 처음 보는 사람도 의미와 사용 방법을 쉽게 이해해야 합니다. 익숙한 아이콘·용어·배치를 사용합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;border-bottom:1px solid #e7edf5;background:#fbfcfe;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;유효성&lt;/strong&gt; — 사용자의 목적을 정확하고 빠르게 달성하게 해야 합니다. 불필요한 입력·클릭을 줄입니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;학습성&lt;/strong&gt; — 초보자도 쉽게 배우고, 숙련자는 빠르게 사용할 수 있어야 합니다. 일관된 동작과 도움말이 필요합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;background:#fbfcfe;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;유연성&lt;/strong&gt; — 다양한 사용자·상황·기기에서 사용 가능하고, 사용자의 선택과 요구를 적절히 수용해야 합니다.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div style=&quot;margin:0 0 22px;padding:17px 18px;border-radius:12px;background:#fff8e7;border:1px solid #f2d490;&quot;&gt;
    &lt;p style=&quot;margin:0 0 7px;color:#805100;font-weight:700;&quot;&gt;화면 설계 체크&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;같은 기능의 버튼은 같은 위치·색·이름으로 쓰고, 필수 입력값은 분명히 표시하며, 저장 전·후의 결과와 오류 원인을 사용자가 이해할 말로 알려 주는지 확인합니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:36px 0 14px;color:#111827;font-size:24px;&quot;&gt;2. 공부하면서 개인적으로 중요하다고 생각하는 용어&lt;/h2&gt;
  &lt;div style=&quot;margin:15px 0 22px;padding:18px;border-radius:14px;background:#f5f8ff;border:1px solid #dbe7ff;&quot;&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;&lt;strong&gt;① 기능 요구사항과 비기능 요구사항&lt;/strong&gt;&lt;br&gt;기능은 ‘무엇을 하는가’, 비기능은 ‘어느 수준과 조건으로 하는가’라는 차이를 확실히 구분해야 한다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;&lt;strong&gt;② 요구사항 검증 가능성&lt;/strong&gt;&lt;br&gt;개발이 끝난 뒤 통과·실패를 판단할 수 없는 요구는 좋은 요구사항이 아니다. 숫자와 조건으로 써야 한다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;&lt;strong&gt;③ 추적 가능성&lt;/strong&gt;&lt;br&gt;요구사항 하나가 설계·코드·테스트에 어떻게 이어졌는지 추적할 수 있어야 변경 때 누락을 막을 수 있다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;④ 직관성·유효성·학습성·유연성&lt;/strong&gt;&lt;br&gt;UI 설계 원칙은 약어 ‘직유학연’으로 묶어 두면 화면 설계 문제에서 바로 떠올릴 수 있다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:36px 0 14px;color:#111827;font-size:24px;&quot;&gt;3. 공부하면서 이해하지 못한 용어&lt;/h2&gt;
  &lt;div style=&quot;margin:15px 0 22px;padding:18px;border-radius:14px;background:#fffaf0;border:1px solid #f3d99c;&quot;&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;&lt;strong&gt;① 요구사항 도출과 검증의 차이&lt;/strong&gt;&lt;br&gt;도출은 이해관계자에게서 필요한 내용을 끌어내는 일이고, 검증은 그 내용이 빠짐·모순·모호함 없이 실제 목적에 맞는지 확인하는 일이다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;&lt;strong&gt;② 유스케이스와 시퀀스 다이어그램의 차이&lt;/strong&gt;&lt;br&gt;유스케이스는 사용자와 기능의 큰 관계, 시퀀스는 객체들이 시간 순서대로 주고받는 메시지를 보여 준다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;③ UI와 UX의 차이&lt;/strong&gt;&lt;br&gt;UI는 화면·버튼·입력창처럼 사용자가 직접 만나는 접점이고, UX는 그 접점을 쓰는 전체 경험과 만족을 포함하는 더 넓은 개념이다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:36px 0 14px;color:#111827;font-size:24px;&quot;&gt;4. 오늘 공부한것 소회&lt;/h2&gt;
  &lt;div style=&quot;margin:15px 0 26px;padding:19px 20px;border-left:4px solid #315efb;background:#f6f8ff;&quot;&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;요구사항 확인은 개발 전의 행정 절차라고만 생각했는데, 실제로는 프로젝트의 방향을 정하는 가장 중요한 단계였다. 특히 “빠르게”, “편하게” 같은 말은 사람마다 다르게 해석될 수 있다는 점이 기억에 남았다. 화면 설계도 예쁜 디자인보다 사용자가 실수 없이 목적을 달성하게 하는 일이 먼저라는 것을 알았다. 다음에는 UML 다이어그램의 역할을 그림 없이도 말할 수 있게 복습해야겠다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:36px 0 12px;color:#111827;font-size:21px;&quot;&gt;범위 확인·추가 복습 자료&lt;/h2&gt;
  &lt;p style=&quot;margin:0 0 8px;font-size:14px;color:#52606d;&quot;&gt;학습 일정의 p.1-2~p.1-55, 요구사항 확인과 화면 설계 범위를 기준으로 정리했습니다. 판본에 따라 세부 페이지·용어 배열은 달라질 수 있습니다.&lt;/p&gt;
  &lt;p style=&quot;margin:0;font-size:14px;line-height:1.75;&quot;&gt;&lt;a href=&quot;https://www.iiba.org/knowledgehub/business-analysis-body-of-knowledge-babok-guide/7-requirements-analysis-and-design-definition/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2458bc;text-decoration:underline;&quot;&gt;IIBA 요구사항 분석·설계 정의&lt;/a&gt; · &lt;a href=&quot;https://www.iso.org/cms/%20render/live/en/sites/isoorg/contents/data/standard/07/75/77520.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2458bc;text-decoration:underline;&quot;&gt;ISO 9241-210 사람 중심 설계&lt;/a&gt;&lt;/p&gt;
&lt;/article&gt;</description>
      <category>AI/정보처리기사_스터디</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/132</guid>
      <comments>https://onethingflow.tistory.com/entry/Day13%EC%A0%95%EC%B2%98%EA%B8%B0-1%EA%B3%BC%EB%AA%A9-%EC%9A%94%EA%B5%AC%EC%82%AC%ED%95%AD-%ED%99%95%EC%9D%B8%C2%B7%ED%99%94%EB%A9%B4-%EC%84%A4%EA%B3%84-%EC%A0%95%EB%A6%AC-p1-2p1-55#entry132comment</comments>
      <pubDate>Wed, 29 Jul 2026 22:56:48 +0900</pubDate>
    </item>
    <item>
      <title>에이수스(ASUS) 노트북 AS 후기...!(3~4일 간의 여정)</title>
      <link>https://onethingflow.tistory.com/entry/%EC%97%90%EC%9D%B4%EC%88%98%EC%8A%A4ASUS-%EB%85%B8%ED%8A%B8%EB%B6%81-AS-%ED%9B%84%EA%B8%B034%EC%9D%BC-%EA%B0%84%EC%9D%98-%EC%97%AC%EC%A0%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;최근 ASUS 젠북 듀오(모델명: UX8406MA-QL149W) 노트북에 큰 문제가 발생했다. 취준을 하기 위해 AI 서비스를 한창 Claude를 통해 열심히 만들고 있었는데 중요한 시기에 갑자기 7월 25일 토요일에 공부를 하려고 도서관에 와서 노트북을 꺼내는 순간에 파손이 된 걸 확인할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 이전에 전조 증상이 있었다. 어느 날부터인가 내가 화면을 만지지도 않았는데 하단 작업 표시줄 영역에 원형 터치 이펙트가 무수히 생기며 무한대로 제멋대로 클릭되는 증상이 나타났다. 그래서 터치 스크린을 끈 상태로 노트북을 사용하였다. 이렇게 취업 하기 전까지 무리없이 쓸 수 있을 거라 생각했다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3060&quot; data-origin-height=&quot;4080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgK3Jz/dJMcahrPYo6/NC5R4lBD7V2DIkXD7Q2jKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgK3Jz/dJMcahrPYo6/NC5R4lBD7V2DIkXD7Q2jKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgK3Jz/dJMcahrPYo6/NC5R4lBD7V2DIkXD7Q2jKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgK3Jz%2FdJMcahrPYo6%2FNC5R4lBD7V2DIkXD7Q2jKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3060&quot; height=&quot;4080&quot; data-origin-width=&quot;3060&quot; data-origin-height=&quot;4080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 설상가상으로 이번에 힌지(경첩) 부분마저 파손되었다. 오른쪽 화면이 제대로 고정되지 못해 덜렁거리고, 하단 가운데 부품이 밖으로 튀어나와 버렸다. 살짝만 힘을 주어도 베젤 틈이 벌어지며 노트북 내부 기판이 훤히 드러나는 상태였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RwNCe/dJMcafHyAcs/nmbkrHpPpQsYwDkbOCXkQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RwNCe/dJMcafHyAcs/nmbkrHpPpQsYwDkbOCXkQk/img.png&quot; data-alt=&quot;노트북 가운데 보면 부품이 빠져나온 것을 확인할 수 있다. 그리고 오른쪽 화면이 덜렁거렸다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RwNCe/dJMcafHyAcs/nmbkrHpPpQsYwDkbOCXkQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRwNCe%2FdJMcafHyAcs%2FnmbkrHpPpQsYwDkbOCXkQk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1080&quot; height=&quot;1080&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;노트북 가운데 보면 부품이 빠져나온 것을 확인할 수 있다. 그리고 오른쪽 화면이 덜렁거렸다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이날 정보처리기사 공부를 빨리 끝내고, 본격적으로 수리를 위해 알아보기 시작했다. 먼저 구글링을 통해 내 지역에서 괜찮은 노트북을 수리할 수 있는 곳을 알아봤다. 전화를 통해 수리 가능 여부를 여쭤봤는데 내 노트북 모델은 희귀한 모델이라서 부품이 없어서 수리할 수 없다고 했다. 우선 형하고 밥을 저녁에 먹기로 해서 일요일에 좀 더 자세히 알아보기로 결정했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일요일에 네이버 map을 통해 여러 노트북 사설 수리 업체에 전화를 했다. 대부분 협조적이지 않았다. 그런 와중에 내 노트북을 가져오면 고쳐보겠다고 한 업체에 직접 가져갔더니 자신이 할 수 없는 영역이라고 했다. 그래서 그날도 점심 이후에 찾아갔다가 1군데 더 알아봤지만 마찬가지로 수리를 할 수 없다고 했다. 그래서 ASUS 공식 서비스센터 분당점에 방문했다.&lt;/p&gt;
&lt;h2 data-path-to-node=&quot;6&quot; data-ke-size=&quot;size26&quot;&gt;ASUS 공식 서비스센터 정자점 방문&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;729&quot; data-origin-height=&quot;558&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1EqA9/dJMcadpjxwH/brt8a7rvvlwTlfesNxKVE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1EqA9/dJMcadpjxwH/brt8a7rvvlwTlfesNxKVE1/img.png&quot; data-alt=&quot;한적한 곳에 위치해 있는 정자 롯데하이마트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1EqA9/dJMcadpjxwH/brt8a7rvvlwTlfesNxKVE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1EqA9%2FdJMcadpjxwH%2Fbrt8a7rvvlwTlfesNxKVE1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;729&quot; height=&quot;558&quot; data-origin-width=&quot;729&quot; data-origin-height=&quot;558&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;한적한 곳에 위치해 있는 정자 롯데하이마트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-path-to-node=&quot;7&quot; data-ke-size=&quot;size16&quot;&gt;당장 개발 일정과 시험 계획이 밀려 있었기에 수리가 시급했다. ASUS 공식 서비스센터 정자점을 방문하기로 했다. 방문하기 이전에 4~5일 정도면 수리할 수 있다고 해서 비싸지만 시간도 중요했기 때문에 빠르게 맡기고, 정처기 시험을 준비하기로 결심했다. 여러 절차를 완료하고, 내 노트북을 배송을 하려고 하는 순간에 서비스 직원분께서 한 달까지도 걸릴 수 있다고 말씀하셨다.(ASUS 공식&amp;nbsp; 지점에서 수리를 해야하기 때문에 배송을 하고, 점검을 하고, 만약 부품이 없다면 해외에서 배송을 해야하기 때문에 그런 거 같다.) 나는 당장 취업을 준비하기 위해 노트북이 필요했기 때문에 그러면 다른 방법을 찾아봐야되겠다고 하였다.&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;7&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;7&quot; data-ke-size=&quot;size16&quot;&gt;서비스 직원분께서 그러면 수리를 빨리 할 수 있는 곳을 알려주겠다고 하시면서 포스트잇에 내 지역 인근 ASUS 마포센터하고, ASUS 강남청담점을 소개해주셨다. 주말에는 안 열기 때문에 월요일에 찾아갔다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;374&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bP5jJC/dJMcacqwQ3F/VJeJDKXkdKYJ98KKUYp7x0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bP5jJC/dJMcacqwQ3F/VJeJDKXkdKYJ98KKUYp7x0/img.png&quot; data-alt=&quot;강남 청담동에 위치한 asus 강남청담 공식 서비스센터&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bP5jJC/dJMcacqwQ3F/VJeJDKXkdKYJ98KKUYp7x0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbP5jJC%2FdJMcacqwQ3F%2FVJeJDKXkdKYJ98KKUYp7x0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;374&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;374&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;강남 청담동에 위치한 asus 강남청담 공식 서비스센터&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot; data-path-to-node=&quot;6&quot;&gt;ASUS 공식 서비스센터 강남청담점 방문&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(ASUS 서비스센터에 방문할 때 네이버 맵으로 오후 2시에 한자리 남아서 예약하고 방문했다. 하지만 도착하고 나서 보니 예약을 할 필요가 없었다. 대부분 예약을 안하고 방문하는 것 같다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론부터 말하자면 &lt;span&gt;수리비는 총 61만 원&lt;/span&gt;이 나왔다. 내 노트북 수리 비용이 그렇게 많이 나올 거라고는 생각하지 못했다. 인터넷을 통해 알아봤을 때는 보통 최소 5만원에서 최대 30만원이라고 GPT가 말해줬기 때문에 더 충격적이였다. 듀얼 OLED 터치 패널에 힌지와 상판 케이스 부품까지 통째로 교체하는 비용이라 수리비가 많이 나온 거 같다. 이때는 내 노트북 수리 비용을 과도하게 일부로 많이 받는 건가 싶어서 다른 사설 업체를 알아보기로 하고 수리를 하지 않고 떠났다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PVHBx/dJMcagTXsqL/HbQPfhw7DLpxvpPPNqn1kk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PVHBx/dJMcagTXsqL/HbQPfhw7DLpxvpPPNqn1kk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PVHBx/dJMcagTXsqL/HbQPfhw7DLpxvpPPNqn1kk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPVHBx%2FdJMcagTXsqL%2FHbQPfhw7DLpxvpPPNqn1kk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1080&quot; height=&quot;1080&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-path-to-node=&quot;6&quot; data-ke-size=&quot;size26&quot;&gt;당근마켓의 후기 좋은 사설 수리업체 방문&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네이버 맵으로 사설 수리업체를 알아보면 후기가 거의 없고, 쓸데없이 방문 서비스 업체들만 많이 나왔다. 다 전화했을 때 너무 노트북 수리를 어떻게든 하기 위해 마케팅적인 광고를 하는 느낌이 들어서 정말 괜찮은 수리업체에 내 노트북을 맡기고 싶어서 우연히 당근마켓에서 알아보기로 결심했다.&amp;nbsp; 여러 사설업체가 있었고, 연락해서 우선 가져오면 상황을 보고 수리를 해보겠다고 말씀하신 동네 사설업체에 갔다. 평점은 4.8이였고, 후기도 굉장히 많았다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방문하는 도중에 핸드폰이 꺼져서 할 수 없이 편의점에 가서 보조배터리를 구매를 해서 겨우 밤에 도착했다. 사설 수리 업체 사장님께서 굉장히 친절하셨다. 그래서 고칠 수 있을 거라 생각했는데... 하지만 내 모델 같은 경우는 희귀한 모델이고, 다른 노트북이랑 달리 일체형으로 되어있기 때문에 잘못 수리하면 액정이 다 박살날 수도 있어 수리를 하기 무섭다고 하셨다. 그래도 내가 여기까지 오는데 고생하셨다고, 이것저것 알아봐주셨다. 내 노트북 부품의 가격을 알아봐주셨는데 해외에서 직구로 39만 4000원 정도 했다. 여기서 수리 서비스 비용까지 합하면 최소 30%를 받기 때문에 50만원 정도 가까이 된다고 말씀해주셨다. 그냥 이런 경우는 공식 ASUS 업체에 맡기는 것이 좋다고 하셨다. 혹시 몰라서 온라인에서 검색한 ASUS 사설 업체에 전화를 해서 물어봤지만 너무 마케팅 느낌이 많이 들었다.(내 노트북이 무엇이 고장났고, 어떤 부품이 필요한지 다 말해줬지만, 정확히 어느정도 소요되는지 얼마인지 알려주지 않았기 때문에 신뢰도가 많이 떨어졌다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1780&quot; data-origin-height=&quot;835&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vVBSC/dJMcafnfVFs/8dS6MYGa7pgxz10LAYKMgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vVBSC/dJMcafnfVFs/8dS6MYGa7pgxz10LAYKMgk/img.png&quot; data-alt=&quot;zenbook duo 상단 메인 디스플레이 가격은 조금씩 다른 거 같다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vVBSC/dJMcafnfVFs/8dS6MYGa7pgxz10LAYKMgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvVBSC%2FdJMcafnfVFs%2F8dS6MYGa7pgxz10LAYKMgk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1780&quot; height=&quot;835&quot; data-origin-width=&quot;1780&quot; data-origin-height=&quot;835&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;zenbook duo 상단 메인 디스플레이 가격은 조금씩 다른 거 같다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-path-to-node=&quot;6&quot; data-ke-size=&quot;size26&quot;&gt;다시 ASUS 공식 서비스센터 강남청담점 방문&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화요일에 다시 ASUS 방문을 했다. 내 노트북 2024년형 젠북 듀오(UX8406MA)는 위아래 OLED 화면과 중앙 힌지가 유기적으로 연결된 특수 설계 모델이다. 따라서 공식 서비스센터에서는 힌지나 베젤, 터치 패널 중 일부만 고장 나도 이를 개별적으로 분해하지 않고, &lt;span&gt;상&amp;middot;하단 디스플레이와 힌지, 전면 베젤이 모두 하나로 결합된 '일체형 어셈블리(Assy)' 단위로 통째로 교체를 진행했다. (서비스를 받아주시는 젊은 엔지니어 분께서 굉장히 친절하셨다. 하지만 나이가 좀 있으신 기술자 분께서는 좀 덜 친절하셨다. 그래도 서비스 전체적으로는 만족했다.)&amp;nbsp; &lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;노트북 수리는 30분 정도 걸렸고, 접수는 5분 정도 소요됬다. 4일 간의 여정을 통해 겨우 내 노트북을 수리했고, 여러 교훈을 얻을 수 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot; data-path-to-node=&quot;6&quot;&gt;결론&amp;nbsp;&lt;/h2&gt;
&lt;p data-path-to-node=&quot;2&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;2&quot;&gt;첫째, 평소 철저한 노트북 발열 및 컨디션 관리는 필수다.&lt;/b&gt; 인공지능 모델을 학습시키거나 무거운 시스템 아키텍처 환경을 돌리다 보면 기기에 가해지는 부하가 매우 크다. 특히 위아래로 디스플레이가 탑재된 듀얼 OLED 폼팩터 특성상 내부 발열이 힌지 주변의 내구성이나 디스플레이 패널 자체에 영향을 줄 수 있다. 쿨링 패드를 사용하거나 주기적으로 열을 식혀주는 등, 작업 성능을 유지하기 위해서라도 하드웨어 컨디션을 세심하게 관리해주어야 한다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3&quot;&gt;둘째, 희귀 모델이나 일체형 노트북은 고민 없이 공식 서비스센터로 직행하자.&lt;/b&gt; 국내 대기업 모델이거나 비교적 수요가 많은 보급형 노트북이라면 부품을 쉽게 구해 사설 업체에서 저렴하게 수리하는 것도 좋은 방법이 될 수 있다.(사설 업체는 당근마켓에서 후기 보고 가는 것을 추천!!) 하지만 젠북 듀오처럼 특수한 설계(일체형 디스플레이 어셈블리)가 적용된 하이엔드 기종은 사설에서 정품 부품을 구하기도 하늘의 별 따기일 뿐만 아니라, 억지로 수리를 시도하다 메인보드 등 다른 부품까지 완전히 망칠 위험이 크다. 초기 진단대로 비싼 수리비가 예상되더라도 헛걸음하지 말고 공식 센터에 빨리 맡기는 것이 결국 소중한 시간과 멘탈을 지키는 가장 확실한 지름길이다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4&quot;&gt;셋째, 언제 닥칠지 모르는 고장에 대비한 상시 백업은 생명줄이다. &lt;/b&gt;기기가 한순간에 먹통이 되었을 때 가장 먼저 떠오른 것은 그 안에 담긴 내 자료들이었다. 다행히 나는 문제가 생기지 않았지만 다른 분들이 문제가 생기는 경우를 많이 봤기 때문에 클라우드 백업이나 외장하드에 백업을 해놓는 것을 추천한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비록 예상치 못한 지출로 61만 원이라는 큰 비용을 내긴 했지만, 다시 새것처럼 짱짱해진 노트북을 보니 마음이 한결 편안해진다. 새로워진 노트북을 이용해 남은 프로젝트들까지 무사히 완주하고, 취업을 해서 새 노트북으로 갈아타야되겠다!!&amp;nbsp;&lt;/p&gt;</description>
      <category>IT</category>
      <category>ASUS #에이수스 #젠북듀오 #ZenbookDuo #UX8406M #UX8406MA #ASUS노트북 #듀얼스크린노트북 #하이엔드노트북 #개발자노트북</category>
      <category>ASUS서비스센터 #ASUS공식센터 #ASUS분당센터 #오리역 #수리비용 #수리후기 #ASUS수리비</category>
      <category>노트북수리 #노트북AS #힌지파손 #경첩수리 #고스트터치 #터치스크린오작동 #디스플레이교체 #화면고장 #액정수리 #일체형디스플레이</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/131</guid>
      <comments>https://onethingflow.tistory.com/entry/%EC%97%90%EC%9D%B4%EC%88%98%EC%8A%A4ASUS-%EB%85%B8%ED%8A%B8%EB%B6%81-AS-%ED%9B%84%EA%B8%B034%EC%9D%BC-%EA%B0%84%EC%9D%98-%EC%97%AC%EC%A0%95#entry131comment</comments>
      <pubDate>Wed, 29 Jul 2026 15:07:37 +0900</pubDate>
    </item>
    <item>
      <title>Day18)파이썬 if와 for의 순서: 필터링, 변환, 분기까지 초보자 정리</title>
      <link>https://onethingflow.tistory.com/entry/Day18%ED%8C%8C%EC%9D%B4%EC%8D%AC-if%EC%99%80-for%EC%9D%98-%EC%88%9C%EC%84%9C-%ED%95%84%ED%84%B0%EB%A7%81-%EB%B3%80%ED%99%98-%EB%B6%84%EA%B8%B0%EA%B9%8C%EC%A7%80-%EC%B4%88%EB%B3%B4%EC%9E%90-%EC%A0%95%EB%A6%AC</link>
      <description>&lt;!--
Title: 파이썬 if와 for의 순서: 필터링, 변환, 분기까지 초보자 정리
Meta description: 파이썬에서 if와 for의 순서가 헷갈릴 때, 여러 줄 코드와 리스트 컴프리헨션을 나란히 비교합니다. 필터링, 변환, 반복 대상 선택, 문자열 처리 예제를 초보자 눈높이로 정리합니다.
Suggested tags: 파이썬, Python, 코딩테스트, 리스트컴프리헨션, for문, if문, 프로그래머스
--&gt;
&lt;style&gt;&lt;/style&gt;
&lt;article class=&quot;hb-post hb-if-for-beginner hb-paste-safe&quot; style=&quot;box-sizing:border-box;max-width:760px;margin:0 auto;padding:24px 18px;color:#1f2937;background:#ffffff;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;line-height:1.78;word-break:keep-all;overflow-wrap:anywhere;&quot;&gt;
  &lt;header style=&quot;margin-bottom:32px;padding-bottom:22px;border-bottom:1px solid #e5e7eb;&quot;&gt;
    &lt;p style=&quot;margin:0 0 8px;color:#2563eb;font-size:14px;font-weight:700;&quot;&gt;Python basics | 조건문과 반복문&lt;/p&gt;
    &lt;h1 style=&quot;margin:0 0 14px;font-size:30px;line-height:1.35;color:#111827;letter-spacing:0;&quot;&gt;파이썬 if와 for의 순서: 필터링, 변환, 분기까지 초보자 정리&lt;/h1&gt;
    &lt;p style=&quot;margin:0;color:#4b5563;font-size:16px;&quot;&gt;한 줄 리스트 컴프리헨션에서 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;if&lt;/code&gt;가 앞이나 뒤에 놓이는 이유, 그리고 실제 여러 줄 코드에서는 왜 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;for&lt;/code&gt;가 먼저 실행되는지 예제로 정리했다.&lt;/p&gt;
  &lt;/header&gt;

  &lt;section style=&quot;margin:0 0 32px;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 12px;font-size:23px;line-height:1.4;color:#111827;&quot;&gt;먼저 결론: 조건이 무엇을 검사하는지부터 본다&lt;/h2&gt;
    &lt;p style=&quot;margin:0 0 14px;&quot;&gt;코드의 모양만 보고 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;if&lt;/code&gt;와 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;for&lt;/code&gt;의 순서를 외우면 금방 헷갈린다. 중요한 것은 &lt;strong&gt;조건이 지금 검사하려는 대상&lt;/strong&gt;이다.&lt;/p&gt;
    &lt;div style=&quot;overflow-x:auto;margin:0 0 16px;&quot;&gt;
      &lt;table style=&quot;width:100%;min-width:580px;border-collapse:collapse;font-size:14px;&quot;&gt;
        &lt;caption style=&quot;caption-side:top;text-align:left;padding:0 0 8px;font-weight:700;color:#374151;&quot;&gt;조건이 검사하는 대상에 따른 코드 위치&lt;/caption&gt;
        &lt;thead&gt;&lt;tr&gt;&lt;th scope=&quot;col&quot; style=&quot;padding:10px;border:1px solid #d1d5db;background:#f9fafb;text-align:left;&quot;&gt;검사 대상&lt;/th&gt;&lt;th scope=&quot;col&quot; style=&quot;padding:10px;border:1px solid #d1d5db;background:#f9fafb;text-align:left;&quot;&gt;자연스러운 구조&lt;/th&gt;&lt;th scope=&quot;col&quot; style=&quot;padding:10px;border:1px solid #d1d5db;background:#f9fafb;text-align:left;&quot;&gt;예시&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
        &lt;tbody&gt;
          &lt;tr&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;반복 중인 원소 하나&lt;/td&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;for&lt;/code&gt; 안에서 &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;if&lt;/code&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;짝수인지, 글자가 p인지&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;리스트 전체의 상태&lt;/td&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;if&lt;/code&gt;로 먼저 판단한 뒤 &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;for&lt;/code&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;목록이 비어 있는지&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;반복할 목록 자체&lt;/td&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;조건으로 목록을 고른 뒤 &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;for&lt;/code&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border:1px solid #d1d5db;&quot;&gt;VIP 목록 또는 일반 목록&lt;/td&gt;&lt;/tr&gt;
        &lt;/tbody&gt;
      &lt;/table&gt;
    &lt;/div&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;일반적인 여러 줄 코드에서 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;i&lt;/code&gt;는 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;for i in ...&lt;/code&gt;가 실행될 때 처음 만들어진다. 그래서 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;i&lt;/code&gt;를 검사하는 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;if i == ...&lt;/code&gt;를 그 위에 둘 수는 없다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;section style=&quot;margin:0 0 32px;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 14px;font-size:23px;line-height:1.4;color:#111827;&quot;&gt;한 줄 문법 네 가지를 여러 줄 코드로 풀어 보기&lt;/h2&gt;

    &lt;div style=&quot;margin:0 0 18px;padding:16px;border:1px solid #dbeafe;border-radius:8px;background:#f8fbff;&quot;&gt;&lt;div style=&quot;display:grid;grid-template-columns:28px 1fr;gap:10px;align-items:start;&quot;&gt;&lt;span style=&quot;display:inline-flex;width:26px;height:26px;border-radius:50%;background:#2563eb;color:#fff;align-items:center;justify-content:center;font-size:13px;font-weight:700;&quot;&gt;1&lt;/span&gt;&lt;div&gt;
      &lt;h3 style=&quot;margin:0 0 8px;font-size:18px;color:#111827;&quot;&gt;if가 맨 뒤: 필요한 원소만 남기는 필터링&lt;/h3&gt;
      &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;result = [char for char in &quot;apple&quot; if char == &quot;p&quot;]
# ['p', 'p']&lt;/code&gt;&lt;/pre&gt;
      &lt;p style=&quot;margin:0 0 10px;&quot;&gt;이 문장은 &lt;strong&gt;p인 글자만 결과에 넣는다&lt;/strong&gt;는 뜻이다. 조건에 맞지 않는 a, l, e는 결과에 들어가지 않으므로 길이가 줄어들 수 있다.&lt;/p&gt;
      &lt;pre style=&quot;margin:0;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;result = []

for char in &quot;apple&quot;:
    if char == &quot;p&quot;:
        result.append(char)&lt;/code&gt;&lt;/pre&gt;
    &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

    &lt;div style=&quot;margin:0 0 18px;padding:16px;border:1px solid #dbeafe;border-radius:8px;background:#f8fbff;&quot;&gt;&lt;div style=&quot;display:grid;grid-template-columns:28px 1fr;gap:10px;align-items:start;&quot;&gt;&lt;span style=&quot;display:inline-flex;width:26px;height:26px;border-radius:50%;background:#2563eb;color:#fff;align-items:center;justify-content:center;font-size:13px;font-weight:700;&quot;&gt;2&lt;/span&gt;&lt;div&gt;
      &lt;h3 style=&quot;margin:0 0 8px;font-size:18px;color:#111827;&quot;&gt;if-else가 맨 앞: 모든 원소를 넣되 값만 바꾸는 변환&lt;/h3&gt;
      &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;result = [&quot;P&quot; if char == &quot;p&quot; else char for char in &quot;apple&quot;]
# ['a', 'P', 'P', 'l', 'e']&lt;/code&gt;&lt;/pre&gt;
      &lt;p style=&quot;margin:0 0 10px;&quot;&gt;이번에는 어느 글자도 버리지 않는다. p는 P로 바꾸고, 나머지는 원래 글자를 넣는다. &lt;strong&gt;모든 반복에서 append가 한 번씩 실행되므로 결과 길이는 원본과 같다.&lt;/strong&gt;&lt;/p&gt;
      &lt;pre style=&quot;margin:0;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;result = []

for char in &quot;apple&quot;:
    if char == &quot;p&quot;:
        result.append(&quot;P&quot;)
    else:
        result.append(char)&lt;/code&gt;&lt;/pre&gt;
    &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

    &lt;div style=&quot;margin:0 0 18px;padding:16px;border:1px solid #dbeafe;border-radius:8px;background:#f8fbff;&quot;&gt;&lt;div style=&quot;display:grid;grid-template-columns:28px 1fr;gap:10px;align-items:start;&quot;&gt;&lt;span style=&quot;display:inline-flex;width:26px;height:26px;border-radius:50%;background:#2563eb;color:#fff;align-items:center;justify-content:center;font-size:13px;font-weight:700;&quot;&gt;3&lt;/span&gt;&lt;div&gt;
      &lt;h3 style=&quot;margin:0 0 8px;font-size:18px;color:#111827;&quot;&gt;in 뒤의 if-else: 반복할 대상 자체를 먼저 고르는 분기&lt;/h3&gt;
      &lt;p style=&quot;margin:0 0 10px;&quot;&gt;이 경우의 조건은 item 하나가 아니라 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#eef2ff;overflow-wrap:anywhere;&quot;&gt;customer_type&lt;/code&gt;이라는 전체 상태를 검사한다. 처음에는 아래처럼 두 줄로 쓰는 편이 가장 읽기 쉽다.&lt;/p&gt;
      &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;items = vip_items if customer_type == &quot;VIP&quot; else normal_items

for item in items:
    print(item)&lt;/code&gt;&lt;/pre&gt;
      &lt;p style=&quot;margin:0 0 10px;&quot;&gt;한 줄로 표현하면 다음과 같다. 괄호 안에서 먼저 목록 하나를 고르고, 그 다음에 선택된 목록을 순회한다.&lt;/p&gt;
      &lt;pre style=&quot;margin:0;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;result = [item for item in (vip_items if customer_type == &quot;VIP&quot; else normal_items)]&lt;/code&gt;&lt;/pre&gt;
    &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

    &lt;div style=&quot;margin:0;padding:16px;border:1px solid #dbeafe;border-radius:8px;background:#f8fbff;&quot;&gt;&lt;div style=&quot;display:grid;grid-template-columns:28px 1fr;gap:10px;align-items:start;&quot;&gt;&lt;span style=&quot;display:inline-flex;width:26px;height:26px;border-radius:50%;background:#2563eb;color:#fff;align-items:center;justify-content:center;font-size:13px;font-weight:700;&quot;&gt;4&lt;/span&gt;&lt;div&gt;
      &lt;h3 style=&quot;margin:0 0 8px;font-size:18px;color:#111827;&quot;&gt;표현식 전체 바깥의 if-else: 작업을 시작할지 결정하는 가드&lt;/h3&gt;
      &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;result = [user + &quot;님&quot; for user in users] if users else [&quot;접속자 없음&quot;]&lt;/code&gt;&lt;/pre&gt;
      &lt;p style=&quot;margin:0 0 10px;&quot;&gt;여기서 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#eef2ff;overflow-wrap:anywhere;&quot;&gt;if users&lt;/code&gt;는 목록 전체가 비어 있는지를 먼저 확인한다. 실제 서비스 코드나 초보자 풀이에서는 아래처럼 풀어 쓰는 편이 더 분명하다.&lt;/p&gt;
      &lt;pre style=&quot;margin:0;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;if users:
    result = []
    for user in users:
        result.append(user + &quot;님&quot;)
else:
    result = [&quot;접속자 없음&quot;]&lt;/code&gt;&lt;/pre&gt;
    &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
  &lt;/section&gt;

  &lt;section style=&quot;margin:0 0 32px;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 12px;font-size:23px;line-height:1.4;color:#111827;&quot;&gt;필터링한 뒤 for문을 따로 돌리는 경우&lt;/h2&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;질문처럼 &lt;strong&gt;먼저 필요한 값만 골라 두고, 그 결과를 다시 for문으로 처리&lt;/strong&gt;하는 방식도 당연히 쓴다. 고른 결과를 여러 번 사용하거나, 중간 결과에 이름을 붙이는 것이 읽기 쉬울 때 좋다.&lt;/p&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;numbers = [1, 2, 3, 4, 5, 6]
even_numbers = [number for number in numbers if number % 2 == 0]

for number in even_numbers:
    print(number * 10)

# 20
# 40
# 60&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;다만 결과를 한 번만 쓸 때는 중간 리스트를 만들지 않고 아래처럼 한 번에 처리해도 된다. 둘 중 무엇이 더 좋은지는 “중간 결과를 다시 쓸까?”와 “이름을 붙이면 이해가 쉬워질까?”로 결정하면 된다.&lt;/p&gt;
    &lt;pre style=&quot;margin:14px 0 0;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;for number in numbers:
    if number % 2 == 0:
        print(number * 10)&lt;/code&gt;&lt;/pre&gt;
  &lt;/section&gt;

  &lt;section style=&quot;margin:0 0 32px;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 14px;font-size:23px;line-height:1.4;color:#111827;&quot;&gt;예제 1. 문자열 식을 분리해 계산하기&lt;/h2&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;문제: &lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181865&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2563eb;font-weight:700;&quot;&gt;프로그래머스 - 간단한 식 계산하기&lt;/a&gt;&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;입력이 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;&quot;43 + 12&quot;&lt;/code&gt;처럼 숫자, 연산자, 숫자의 순서로 주어진다. 처음 떠올릴 수 있는 방식은 공백으로 나누고 연산자에 따라 계산하는 것이다.&lt;/p&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(binomial):
    box = list(binomial.split(&quot; &quot;))

    for char in box:
        if box[1] == &quot;+&quot;:
            answer = int(box[0]) + int(box[2])
        elif box[1] == &quot;-&quot;:
            answer = int(box[0]) - int(box[2])
        else:
            answer = int(box[0]) * int(box[2])

    return answer&lt;/code&gt;&lt;/pre&gt;
    &lt;div style=&quot;margin:0 0 12px;padding:14px;border-left:4px solid #f59e0b;background:#fffbeb;&quot;&gt;&lt;p style=&quot;margin:0 0 8px;font-weight:700;color:#92400e;&quot;&gt;여기서 정리할 점&lt;/p&gt;&lt;p style=&quot;margin:0 0 8px;&quot;&gt;&lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;split()&lt;/code&gt;의 결과는 이미 리스트다. 따라서 바깥의 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;list()&lt;/code&gt;는 필요 없다.&lt;/p&gt;&lt;p style=&quot;margin:0 0 8px;&quot;&gt;&lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;for char in box&lt;/code&gt;에서 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;char&lt;/code&gt;를 전혀 사용하지 않는다. 같은 계산을 세 번 반복할 이유가 없으므로 for문도 필요 없다.&lt;/p&gt;&lt;p style=&quot;margin:0;&quot;&gt;현재 제한에서는 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;&quot;-&quot; in box&lt;/code&gt;도 동작한다. 하지만 “리스트 어딘가에 -가 있는가”보다 “연산자 자리인 1번 칸이 -인가”를 확인하는 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;box[1] == &quot;-&quot;&lt;/code&gt;가 더 정확하다. 음수처럼 -가 다른 의미로 등장하는 입력까지 생각하면 특히 차이가 난다.&lt;/p&gt;&lt;/div&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(binomial):
    a, op, b = binomial.split()
    a = int(a)
    b = int(b)

    if op == &quot;+&quot;:
        return a + b
    if op == &quot;-&quot;:
        return a - b
    return a * b&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;여기서 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;a, op, b = binomial.split()&lt;/code&gt;은 세 조각을 각각 이름 있는 변수에 담는 언패킹이다. &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;split()&lt;/code&gt;은 공백이 여러 개이거나 탭이 있어도 여백을 기준으로 나누므로 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;split(&quot; &quot;)&lt;/code&gt;보다 보통 안전하다. 문자열을 그대로 실행하는 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;eval()&lt;/code&gt;은 외부 입력에서 위험할 수 있으므로 이 글에서는 사용하지 않는다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;section style=&quot;margin:0 0 32px;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 14px;font-size:23px;line-height:1.4;color:#111827;&quot;&gt;예제 2. A와 B를 바꾸고 패턴 찾기&lt;/h2&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;문제: &lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181864&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2563eb;font-weight:700;&quot;&gt;프로그래머스 - 문자열 바꿔서 찾기&lt;/a&gt;&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;처음에는 문자열을 나누고 바꾼 글자를 리스트에 담은 뒤 다시 합치는 흐름으로 생각할 수 있다. 이 흐름 자체는 좋다. 다만 문자열에 공백이 없다는 점을 놓치면 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;split()&lt;/code&gt; 때문에 한 글자씩 처리되지 않는다.&lt;/p&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;# 잘못되기 쉬운 부분
for char in myString.split():
    ...

ans = &quot;,&quot;.join(answer)&lt;/code&gt;&lt;/pre&gt;
    &lt;div style=&quot;margin:0 0 12px;padding:14px;border-left:4px solid #f59e0b;background:#fffbeb;&quot;&gt;&lt;p style=&quot;margin:0 0 8px;&quot;&gt;&lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;&quot;ABBA&quot;.split()&lt;/code&gt;의 결과는 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;[&quot;ABBA&quot;]&lt;/code&gt;다. 공백이 없으므로 통째로 한 조각이 된다. 한 글자씩 꺼내려면 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;for char in myString&lt;/code&gt;처럼 문자열 자체를 순회하면 된다.&lt;/p&gt;&lt;p style=&quot;margin:0;&quot;&gt;&lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;&quot;,&quot;.join([&quot;B&quot;, &quot;A&quot;, &quot;A&quot;, &quot;B&quot;])&lt;/code&gt;의 결과는 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;&quot;B,A,A,B&quot;&lt;/code&gt;다. 글자 사이에 쉼표가 끼면 찾으려는 연속 문자열과 달라진다. 빈 문자열로 붙이는 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#fef3c7;overflow-wrap:anywhere;&quot;&gt;&quot;&quot;.join(...)&lt;/code&gt;을 사용해야 한다.&lt;/p&gt;&lt;/div&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(myString, pat):
    answer = []

    for char in myString:
        if char == &quot;A&quot;:
            answer.append(&quot;B&quot;)
        else:
            answer.append(&quot;A&quot;)

    changed = &quot;&quot;.join(answer)
    return 1 if pat in changed else 0&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;A와 B만 입력된다는 조건이 있으므로 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;else&lt;/code&gt;에서는 B를 A로 바꿔도 된다. &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;pat in changed&lt;/code&gt;는 포함되면 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;True&lt;/code&gt;, 아니면 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;False&lt;/code&gt;를 만든다. 숫자 1 또는 0이 필요하면 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;int(True)&lt;/code&gt;는 1, &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;int(False)&lt;/code&gt;는 0이라는 점을 이용할 수 있다.&lt;/p&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(myString, pat):
    changed = &quot;&quot;.join(&quot;B&quot; if char == &quot;A&quot; else &quot;A&quot; for char in myString)
    return int(pat in changed)&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;또 하나의 관점은 긴 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;myString&lt;/code&gt; 대신 짧은 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;pat&lt;/code&gt;을 반대로 바꿔 원래 문자열에서 찾는 것이다. A와 B만 있다는 이 문제의 조건에서만 성립하는 변환이다.&lt;/p&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(myString, pat):
    flipped_pat = &quot;&quot;.join(&quot;A&quot; if char == &quot;B&quot; else &quot;B&quot; for char in pat)
    return int(flipped_pat in myString)&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;A와 B를 동시에 뒤집는 일이 자주 나온다면 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;translate()&lt;/code&gt;도 쓸 수 있다.&lt;/p&gt;
    &lt;pre style=&quot;margin:14px 0 0;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(myString, pat):
    changed = myString.translate(str.maketrans(&quot;AB&quot;, &quot;BA&quot;))
    return int(pat in changed)&lt;/code&gt;&lt;/pre&gt;
  &lt;/section&gt;

  &lt;section style=&quot;margin:0 0 32px;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 14px;font-size:23px;line-height:1.4;color:#111827;&quot;&gt;예제 3. 단순 치환에는 replace()가 가장 직접적이다&lt;/h2&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;문제: &lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181863&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2563eb;font-weight:700;&quot;&gt;프로그래머스 - rny_string&lt;/a&gt;&lt;/p&gt;
    &lt;pre style=&quot;margin:0 0 12px;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(rny_string):
    return rny_string.replace(&quot;m&quot;, &quot;rn&quot;)

# &quot;masterpiece&quot; -&amp;gt; &quot;rnasterpiece&quot;&lt;/code&gt;&lt;/pre&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;글자 하나를 특정 문자열로 바꾸는 일이라면 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;replace()&lt;/code&gt;가 의도를 가장 바로 보여 준다. 원리를 확인하는 용도로는 아래처럼 컴프리헨션과 &lt;code style=&quot;padding:2px 5px;border-radius:4px;background:#f3f4f6;overflow-wrap:anywhere;&quot;&gt;join()&lt;/code&gt;으로도 쓸 수 있지만, 이 문제에서는 첫 번째 풀이가 더 간단하다.&lt;/p&gt;
    &lt;pre style=&quot;margin:0;padding:14px;overflow:auto;border-radius:6px;background:#111827;color:#f9fafb;line-height:1.55;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;def solution(rny_string):
    return &quot;&quot;.join(&quot;rn&quot; if char == &quot;m&quot; else char for char in rny_string)&lt;/code&gt;&lt;/pre&gt;
  &lt;/section&gt;

  &lt;section style=&quot;margin:0 0 32px;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 14px;font-size:23px;line-height:1.4;color:#111827;&quot;&gt;실수 방지 체크리스트&lt;/h2&gt;
    &lt;div style=&quot;display:grid;gap:10px;&quot;&gt;
      &lt;div style=&quot;display:grid;grid-template-columns:28px 1fr;gap:10px;align-items:start;padding:12px;border:1px solid #e5e7eb;border-radius:6px;&quot;&gt;&lt;span style=&quot;display:inline-flex;width:26px;height:26px;border-radius:50%;background:#111827;color:#fff;align-items:center;justify-content:center;font-size:12px;font-weight:700;&quot;&gt;1&lt;/span&gt;&lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;원소 하나를 검사하는가?&lt;/strong&gt; 그렇다면 보통 &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;for&lt;/code&gt; 안에 &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;if&lt;/code&gt;를 둔다.&lt;/p&gt;&lt;/div&gt;
      &lt;div style=&quot;display:grid;grid-template-columns:28px 1fr;gap:10px;align-items:start;padding:12px;border:1px solid #e5e7eb;border-radius:6px;&quot;&gt;&lt;span style=&quot;display:inline-flex;width:26px;height:26px;border-radius:50%;background:#111827;color:#fff;align-items:center;justify-content:center;font-size:12px;font-weight:700;&quot;&gt;2&lt;/span&gt;&lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;목록 전체 상태나 선택할 목록을 검사하는가?&lt;/strong&gt; 그렇다면 &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;if&lt;/code&gt;로 먼저 결정한 뒤 &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;for&lt;/code&gt;를 돌릴 수 있다.&lt;/p&gt;&lt;/div&gt;
      &lt;div style=&quot;display:grid;grid-template-columns:28px 1fr;gap:10px;align-items:start;padding:12px;border:1px solid #e5e7eb;border-radius:6px;&quot;&gt;&lt;span style=&quot;display:inline-flex;width:26px;height:26px;border-radius:50%;background:#111827;color:#fff;align-items:center;justify-content:center;font-size:12px;font-weight:700;&quot;&gt;3&lt;/span&gt;&lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;컴프리헨션의 if 위치를 확인한다.&lt;/strong&gt; 뒤의 if는 필터링, 앞의 if-else는 변환, &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;in&lt;/code&gt; 뒤의 if-else는 반복 대상 선택이다.&lt;/p&gt;&lt;/div&gt;
      &lt;div style=&quot;display:grid;grid-template-columns:28px 1fr;gap:10px;align-items:start;padding:12px;border:1px solid #e5e7eb;border-radius:6px;&quot;&gt;&lt;span style=&quot;display:inline-flex;width:26px;height:26px;border-radius:50%;background:#111827;color:#fff;align-items:center;justify-content:center;font-size:12px;font-weight:700;&quot;&gt;4&lt;/span&gt;&lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;문자열을 한 글자씩 볼 때는 split()이 필요 없다.&lt;/strong&gt; &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;for char in text&lt;/code&gt;로 바로 순회한다.&lt;/p&gt;&lt;/div&gt;
      &lt;div style=&quot;display:grid;grid-template-columns:28px 1fr;gap:10px;align-items:start;padding:12px;border:1px solid #e5e7eb;border-radius:6px;&quot;&gt;&lt;span style=&quot;display:inline-flex;width:26px;height:26px;border-radius:50%;background:#111827;color:#fff;align-items:center;justify-content:center;font-size:12px;font-weight:700;&quot;&gt;5&lt;/span&gt;&lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;연속된 문자열을 만들 때는 &quot;&quot;.join()을 쓴다.&lt;/strong&gt; 쉼표나 공백을 넣은 join은 그 기호도 결과에 포함한다.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section style=&quot;margin:0 0 28px;padding:16px;border-radius:8px;background:#f3f4f6;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 10px;font-size:20px;line-height:1.4;color:#111827;&quot;&gt;같이 보면 좋은 문제&lt;/h2&gt;
    &lt;p style=&quot;margin:0 0 8px;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181865&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2563eb;font-weight:700;&quot;&gt;간단한 식 계산하기&lt;/a&gt;: split, 언패킹, 정확한 연산자 비교를 연습하기 좋다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 8px;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181864&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2563eb;font-weight:700;&quot;&gt;문자열 바꿔서 찾기&lt;/a&gt;: 문자열 순회, join, 조건식, in 연산자를 한 번에 복습할 수 있다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181863&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2563eb;font-weight:700;&quot;&gt;rny_string&lt;/a&gt;: replace와 직접 순회의 차이를 비교하기 좋다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;footer style=&quot;padding-top:18px;border-top:1px solid #e5e7eb;&quot;&gt;&lt;p style=&quot;margin:0;color:#4b5563;&quot;&gt;한 줄 코드가 낯설 때는 먼저 여러 줄 코드로 풀어 보자. 반복할 원소를 꺼내는 일은 for가 하고, 그 원소를 남길지 바꿀지는 if가 결정한다. 반대로 전체 상태나 반복할 목록을 고르는 조건은 for보다 앞에 둘 수 있다.&lt;/p&gt;&lt;/footer&gt;
&lt;/article&gt;</description>
      <category>AI/Coding_Test</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/130</guid>
      <comments>https://onethingflow.tistory.com/entry/Day18%ED%8C%8C%EC%9D%B4%EC%8D%AC-if%EC%99%80-for%EC%9D%98-%EC%88%9C%EC%84%9C-%ED%95%84%ED%84%B0%EB%A7%81-%EB%B3%80%ED%99%98-%EB%B6%84%EA%B8%B0%EA%B9%8C%EC%A7%80-%EC%B4%88%EB%B3%B4%EC%9E%90-%EC%A0%95%EB%A6%AC#entry130comment</comments>
      <pubDate>Tue, 28 Jul 2026 22:53:10 +0900</pubDate>
    </item>
    <item>
      <title>Day12)정처기 5과목 소프트웨어 개발 보안 구축 정리 | p.5-76~p.5-141</title>
      <link>https://onethingflow.tistory.com/entry/Day12%EC%A0%95%EC%B2%98%EA%B8%B0-5%EA%B3%BC%EB%AA%A9-%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-%EC%A0%95%EB%A6%AC-p5-76p5-141</link>
      <description>&lt;!-- 티스토리 제목: 정처기 5과목 소프트웨어 개발 보안 구축 정리 | p.5-76~p.5-141 --&gt;
&lt;!-- 메타 설명: 정보처리기사 실기 5과목 소프트웨어 개발 보안 구축을 초보자용으로 정리합니다. 보안 설계·구현, 시큐어 코딩, 접근제어, 암호화, 시스템 보안 설계를 한 번에 복습합니다. --&gt;
&lt;style&gt;&lt;/style&gt;
&lt;article class=&quot;hb-post hb-jeongcheogi-security&quot; style=&quot;max-width:780px;margin:0 auto;color:#1f2937;font-size:17px;line-height:1.82;word-break:keep-all;overflow-wrap:break-word;&quot;&gt;
  &lt;p style=&quot;margin:0 0 10px;color:#52606d;font-size:14px;&quot;&gt;정처기 공부 기록 · 7월 28일 · 실기 5과목&lt;/p&gt;
  &lt;h1 style=&quot;margin:0 0 18px;color:#111827;font-size:32px;line-height:1.32;letter-spacing:-0.04em;&quot;&gt;소프트웨어 개발 보안 구축&lt;br&gt;p.5-76~p.5-141&lt;/h1&gt;
  &lt;div style=&quot;margin:0 0 28px;padding:19px 20px;border:1px solid #dbe7ff;border-radius:14px;background:#f5f8ff;&quot;&gt;
    &lt;p style=&quot;margin:0 0 8px;color:#2458bc;font-weight:700;&quot;&gt;오늘의 한 줄 목표&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;보안을 ‘마지막에 붙이는 기능’이 아니라, &lt;strong&gt;요구사항부터 설계·코딩·테스트·운영까지 이어지는 개발 기준&lt;/strong&gt;으로 이해하기.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:36px 0 14px;color:#111827;font-size:24px;&quot;&gt;1. 오늘 공부한 내용&lt;/h2&gt;
  &lt;p style=&quot;margin:0 0 15px;&quot;&gt;이번 범위는 5과목 &lt;strong&gt;03. 소프트웨어 개발 보안 구축&lt;/strong&gt;과 이어지는 &lt;strong&gt;시스템 보안 설계&lt;/strong&gt;입니다. 핵심은 “해킹 사고가 난 뒤 막는 것”이 아니라, 만들기 전부터 위험을 찾고 안전한 구조·코드·운영 환경을 설계하는 것입니다.&lt;/p&gt;

  &lt;div style=&quot;margin:16px 0 26px;border:1px solid #d9e2ef;border-radius:14px;overflow:hidden;background:#fff;&quot;&gt;
    &lt;div style=&quot;padding:15px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;display:inline-block;width:28px;height:28px;margin-right:10px;border-radius:8px;background:#315efb;color:#fff;text-align:center;line-height:28px;&quot;&gt;1&lt;/strong&gt;&lt;strong&gt;소프트웨어 개발 보안 설계&lt;/strong&gt;&lt;br&gt;&lt;span style=&quot;display:block;margin-left:40px;color:#52606d;font-size:15px;&quot;&gt;보안 요구사항, 자산·위협 분석, 보안 원칙, 접근 통제와 암호화 설계&lt;/span&gt;&lt;/div&gt;
    &lt;div style=&quot;padding:15px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;display:inline-block;width:28px;height:28px;margin-right:10px;border-radius:8px;background:#315efb;color:#fff;text-align:center;line-height:28px;&quot;&gt;2&lt;/strong&gt;&lt;strong&gt;소프트웨어 개발 보안 구현&lt;/strong&gt;&lt;br&gt;&lt;span style=&quot;display:block;margin-left:40px;color:#52606d;font-size:15px;&quot;&gt;입력값 검증, 인증·세션, 인가, 오류 처리, 로그, 시큐어 코딩&lt;/span&gt;&lt;/div&gt;
    &lt;div style=&quot;padding:15px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;display:inline-block;width:28px;height:28px;margin-right:10px;border-radius:8px;background:#315efb;color:#fff;text-align:center;line-height:28px;&quot;&gt;3&lt;/strong&gt;&lt;strong&gt;시스템 보안 설계&lt;/strong&gt;&lt;br&gt;&lt;span style=&quot;display:block;margin-left:40px;color:#52606d;font-size:15px;&quot;&gt;접근제어 모델, 암호화, 방화벽·IDS/IPS·VPN·DMZ·Secure OS&lt;/span&gt;&lt;/div&gt;
    &lt;div style=&quot;padding:15px 16px;&quot;&gt;&lt;strong style=&quot;display:inline-block;width:28px;height:28px;margin-right:10px;border-radius:8px;background:#315efb;color:#fff;text-align:center;line-height:28px;&quot;&gt;4&lt;/strong&gt;&lt;strong&gt;운영까지의 보안&lt;/strong&gt;&lt;br&gt;&lt;span style=&quot;display:block;margin-left:40px;color:#52606d;font-size:15px;&quot;&gt;배포 설정, 권한 관리, 로그·모니터링, 백업과 장애 대응&lt;/span&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;개발 보안은 언제 시작할까?&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 15px;&quot;&gt;보안은 구현 단계에서만 하는 검사가 아닙니다. 개발 생명주기 전체에서 반복해야 합니다. 처음 설계가 안전하지 않으면, 나중에 코드를 고쳐도 근본 위험이 남을 수 있습니다.&lt;/p&gt;
  &lt;div style=&quot;margin:0 0 22px;padding:18px;border-left:4px solid #315efb;background:#f6f8ff;&quot;&gt;
    &lt;p style=&quot;margin:0 0 8px;&quot;&gt;&lt;strong&gt;요구사항&lt;/strong&gt; — 어떤 정보가 민감한지, 누가 어떤 기능을 써야 하는지, 법·규정·보안 요구가 무엇인지 정의합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 8px;&quot;&gt;&lt;strong&gt;설계&lt;/strong&gt; — 자산·위협·취약점을 분석하고, 인증·권한·암호화·로그·네트워크 구간을 설계합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 8px;&quot;&gt;&lt;strong&gt;구현&lt;/strong&gt; — 입력값 검증, 안전한 API 사용, 비밀번호·세션 처리, 예외 처리와 로그 기준을 코드에 반영합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 8px;&quot;&gt;&lt;strong&gt;테스트&lt;/strong&gt; — 기능 시험뿐 아니라 권한 우회, 입력값 공격, 설정 오류, 취약점 여부를 점검합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;배포·운영&lt;/strong&gt; — 기본 계정 제거, 최소 권한, 패치, 백업, 모니터링과 사고 대응 절차를 관리합니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;보안의 기본 목표: CIA와 추가 속성&lt;/h3&gt;
  &lt;div style=&quot;margin:0 0 22px;border:1px solid #d9e2ef;border-radius:14px;overflow-x:auto;background:#fff;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:650px;border-collapse:collapse;font-size:15px;line-height:1.65;&quot;&gt;
      &lt;thead&gt;&lt;tr style=&quot;background:#f1f5ff;color:#223f7a;&quot;&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;목표&lt;/th&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;의미&lt;/th&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;예시&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;기밀성&lt;br&gt;Confidentiality&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;허가된 사람만 정보를 볼 수 있음&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;접근 권한, 암호화, 마스킹&lt;/td&gt;&lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfe;&quot;&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;무결성&lt;br&gt;Integrity&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;정보가 허가 없이 바뀌거나 훼손되지 않음&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;해시, 전자서명, 변경 이력&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;가용성&lt;br&gt;Availability&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;필요할 때 서비스를 사용할 수 있음&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;이중화, 백업, 장애 복구&lt;/td&gt;&lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfe;&quot;&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;인증&lt;br&gt;Authentication&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;접속자가 주장하는 본인이 맞는지 확인&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;비밀번호, OTP, 생체 인증&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;인가&lt;br&gt;Authorization&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;인증된 사람이 무엇을 할 수 있는지 결정&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;관리자·일반 사용자 권한 분리&lt;/td&gt;&lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfe;&quot;&gt;&lt;td style=&quot;padding:10px;&quot;&gt;&lt;strong&gt;부인 방지&lt;br&gt;Non-repudiation&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;&quot;&gt;행위를 한 사람이 나중에 부인하지 못하게 함&lt;/td&gt;&lt;td style=&quot;padding:10px;&quot;&gt;전자서명, 감사 로그&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;보안 설계의 원칙&lt;/h3&gt;
  &lt;div style=&quot;margin:0 0 22px;padding:18px;border:1px solid #d9e2ef;border-radius:14px;background:#fff;&quot;&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;최소 권한&lt;/strong&gt; — 사용자·프로그램에는 업무에 꼭 필요한 권한만 줍니다. “일단 모두 허용”이 아니라 필요한 경우에만 허용합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;안전한 기본값&lt;/strong&gt; — 설정하지 않은 기능·접근은 기본적으로 차단하고, 허용이 필요할 때만 명시합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;직무 분리&lt;/strong&gt; — 한 사람이 요청·승인·실행·검증을 모두 하지 않도록 역할을 나누어 실수와 악용을 줄입니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;완전한 검증&lt;/strong&gt; — 화면에서 버튼을 숨기는 것으로 끝내지 않고, 서버와 API에서도 매 요청마다 인증·권한을 확인합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;장애도 안전하게&lt;/strong&gt; — 오류가 나더라도 민감 정보가 노출되거나 권한이 열리지 않게 하고, 사용자에게는 필요한 범위의 안내만 보여 줍니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;시큐어 코딩: 자주 나오는 취약점과 예방 방향&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 15px;&quot;&gt;시큐어 코딩은 공격을 막는 코드를 처음부터 작성하는 것입니다. 아래는 시험에서 자주 비교하는 공격 유형과 방어 방향입니다. 실제 서비스에서는 프레임워크·언어별 보안 가이드를 함께 적용해야 합니다.&lt;/p&gt;
  &lt;div style=&quot;margin:0 0 22px;border:1px solid #d9e2ef;border-radius:14px;overflow-x:auto;background:#fff;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:710px;border-collapse:collapse;font-size:15px;line-height:1.65;&quot;&gt;
      &lt;thead&gt;&lt;tr style=&quot;background:#fff6ee;color:#8a4a10;&quot;&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;취약점&lt;/th&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;무엇이 문제인가?&lt;/th&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;예방 방향&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;SQL 삽입&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;입력값이 SQL 문장의 일부로 해석되어 의도하지 않은 조회·변경이 일어남&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;준비된 쿼리·파라미터 바인딩, 입력값 검증, DB 최소 권한&lt;/td&gt;&lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfe;&quot;&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;XSS&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;공격자가 넣은 스크립트가 다른 사용자의 브라우저에서 실행됨&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;출력 인코딩, 입력 검증, 안전한 콘텐츠 정책 적용&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;명령어 삽입&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;외부 입력이 운영체제 명령처럼 실행됨&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;셸 호출 최소화, 허용 목록 검증, 안전한 API 사용&lt;/td&gt;&lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfe;&quot;&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;경로 조작&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;파일 경로를 바꿔 허용되지 않은 파일에 접근&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;경로 정규화, 상위 경로 이동 차단, 허용된 저장소만 사용&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;버퍼 오류&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;허용 범위를 넘는 데이터 처리로 메모리 훼손·오작동 발생&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;길이 검사, 안전한 함수·자료형, 경계값 시험&lt;/td&gt;&lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfe;&quot;&gt;&lt;td style=&quot;padding:10px;&quot;&gt;&lt;strong&gt;권한 우회&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;&quot;&gt;URL·ID·API 요청을 바꿔 다른 사람의 정보·기능에 접근&lt;/td&gt;&lt;td style=&quot;padding:10px;&quot;&gt;서버 측 인가 검사, 기본 거부, 객체별 소유권 확인&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
  &lt;div style=&quot;margin:0 0 22px;padding:17px 18px;border-radius:12px;background:#fff8e7;border:1px solid #f2d490;&quot;&gt;
    &lt;p style=&quot;margin:0 0 7px;color:#805100;font-weight:700;&quot;&gt;암기 연결&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;입력값을 믿어 발생하는 문제는 &lt;strong&gt;삽입·경로 조작·버퍼 오류&lt;/strong&gt;로, 로그인 뒤 권한 검사를 빼서 생기는 문제는 &lt;strong&gt;권한 우회&lt;/strong&gt;로 구분합니다. 현재 OWASP도 접근제어 실패, 설정 오류, 암호화 실패, 삽입 등을 주요 웹 애플리케이션 위험으로 제시합니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;인증·세션·로그에서 놓치기 쉬운 부분&lt;/h3&gt;
  &lt;div style=&quot;margin:0 0 22px;padding:18px;border:1px solid #d9e2ef;border-radius:14px;background:#fff;&quot;&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;비밀번호&lt;/strong&gt; — 평문으로 저장하지 않고, 검증된 비밀번호 해싱 방식을 사용합니다. 소스 코드·설정 파일에 비밀값을 하드코딩하지 않습니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;세션&lt;/strong&gt; — 로그인 전후로 세션을 적절히 관리하고, 세션 식별자를 안전하게 전송·보관하며 로그아웃·만료 처리를 명확히 합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;오류 처리&lt;/strong&gt; — 사용자 화면에는 DB 구조·파일 경로·내부 오류 정보가 그대로 보이지 않게 하고, 분석에 필요한 상세 정보는 접근 통제된 로그로 남깁니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;로그·모니터링&lt;/strong&gt; — 로그인 실패, 권한 변경, 중요 데이터 접근, 오류와 배포 이력을 남기고 이상 징후를 확인합니다. 단, 로그에 비밀번호·주민번호 등 민감값을 그대로 기록하면 안 됩니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;시스템 보안 설계: 접근제어와 암호화&lt;/h3&gt;
  &lt;div style=&quot;margin:0 0 20px;border:1px solid #d9e2ef;border-radius:14px;overflow-x:auto;background:#fff;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:680px;border-collapse:collapse;font-size:15px;line-height:1.65;&quot;&gt;
      &lt;thead&gt;&lt;tr style=&quot;background:#eef7f4;color:#17624f;&quot;&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;구분&lt;/th&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;권한을 정하는 기준&lt;/th&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;핵심 단서&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;DAC&lt;br&gt;임의적 접근제어&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;자원 소유자가 권한을 부여·변경&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;소유자 재량, 유연하지만 통제 약화 가능&lt;/td&gt;&lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfe;&quot;&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;MAC&lt;br&gt;강제적 접근제어&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;시스템이 보안 등급·규칙에 따라 강제&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;등급, 중앙 통제, 군사·고보안 환경&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;RBAC&lt;br&gt;역할 기반 접근제어&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;개인에게 직접 주기보다 역할에 권한을 부여&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;관리자·인사·일반 사용자 같은 역할&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
  &lt;div style=&quot;margin:0 0 22px;padding:18px;border:1px solid #d9e2ef;border-radius:14px;background:#fff;&quot;&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;대칭키 암호화&lt;/strong&gt; — 암호화와 복호화에 같은 비밀키를 사용합니다. 빠르지만 키를 안전하게 전달·관리해야 합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;비대칭키 암호화&lt;/strong&gt; — 공개키와 개인키 한 쌍을 사용합니다. 키 분배·전자서명에 유용하지만 대칭키보다 연산 부담이 큽니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;해시&lt;/strong&gt; — 원문을 일정한 길이의 값으로 변환해 무결성 확인에 씁니다. 일반적으로 원문을 되돌리는 복호화를 목적으로 하지 않습니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;전자서명&lt;/strong&gt; — 개인키로 서명하고 공개키로 검증해, 무결성과 송신자 확인·부인 방지에 활용합니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;시스템·네트워크 보안 장비 한 번에 구분하기&lt;/h3&gt;
  &lt;div style=&quot;margin:0 0 22px;border:1px solid #d9e2ef;border-radius:14px;overflow:hidden;background:#fff;&quot;&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;방화벽(Firewall)&lt;/strong&gt; — 정책에 따라 네트워크 통신을 허용·차단합니다. ‘문 앞에서 출입 규칙을 적용하는 장치’로 기억합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;border-bottom:1px solid #e7edf5;background:#fbfcfe;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;IDS&lt;/strong&gt; — 침입 징후를 탐지하고 알려 줍니다. 직접 차단보다 ‘발견·경보’가 핵심입니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;IPS&lt;/strong&gt; — 침입 징후를 탐지한 뒤 차단까지 수행합니다. IDS와 달리 ‘차단’이 핵심입니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;border-bottom:1px solid #e7edf5;background:#fbfcfe;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;VPN&lt;/strong&gt; — 공용 네트워크에서도 암호화된 가상 사설 통신 경로를 만듭니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;DMZ&lt;/strong&gt; — 외부에 공개해야 하는 웹·메일 서버 등을 내부망과 분리해 두는 중간 구역입니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;Secure OS&lt;/strong&gt; — 기존 운영체제에 보안 기능을 강화해 사용자·프로세스·파일·장치에 대한 접근 통제를 지원하는 운영체제입니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:36px 0 14px;color:#111827;font-size:24px;&quot;&gt;2. 공부하면서 개인적으로 중요하다고 생각하는 용어&lt;/h2&gt;
  &lt;div style=&quot;margin:15px 0 22px;padding:18px;border-radius:14px;background:#f5f8ff;border:1px solid #dbe7ff;&quot;&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;&lt;strong&gt;① 최소 권한 원칙&lt;/strong&gt;&lt;br&gt;권한을 많이 줄수록 편해 보여도 사고 범위가 커진다. ‘필요한 것만 허용’이 접근제어 문제의 출발점이다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;&lt;strong&gt;② 입력값 검증&lt;/strong&gt;&lt;br&gt;SQL 삽입, 명령어 삽입, 경로 조작처럼 외부 입력을 믿어서 생기는 취약점의 공통 방어선이다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;&lt;strong&gt;③ 인증과 인가&lt;/strong&gt;&lt;br&gt;인증은 ‘너 누구야?’, 인가는 ‘너는 무엇을 해도 돼?’라는 질문으로 구분하면 가장 명확하다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;④ RBAC&lt;/strong&gt;&lt;br&gt;사람 한 명씩 권한을 부여하는 대신 역할에 권한을 묶어 관리하므로, 실제 조직에서 권한 변경을 관리하기 쉽다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:36px 0 14px;color:#111827;font-size:24px;&quot;&gt;3. 공부하면서 이해하지 못한 용어&lt;/h2&gt;
  &lt;div style=&quot;margin:15px 0 22px;padding:18px;border-radius:14px;background:#fffaf0;border:1px solid #f3d99c;&quot;&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;&lt;strong&gt;① 해시와 암호화의 차이&lt;/strong&gt;&lt;br&gt;암호화는 키로 원문을 다시 복호화할 수 있지만, 해시는 원문 복원을 목적으로 하지 않고 값이 바뀌었는지 확인하는 데 쓴다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;&lt;strong&gt;② IDS와 IPS의 차이&lt;/strong&gt;&lt;br&gt;IDS는 침입을 찾아 알려 주는 탐지 중심, IPS는 탐지 뒤 실제 통신을 차단하는 방어 중심이다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;③ DAC·MAC·RBAC의 차이&lt;/strong&gt;&lt;br&gt;DAC는 소유자 재량, MAC는 보안 등급을 시스템이 강제, RBAC는 역할에 따라 권한을 주는 방식이다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:36px 0 14px;color:#111827;font-size:24px;&quot;&gt;4. 오늘 공부한것 소회&lt;/h2&gt;
  &lt;div style=&quot;margin:15px 0 26px;padding:19px 20px;border-left:4px solid #315efb;background:#f6f8ff;&quot;&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;보안은 어려운 암호 알고리즘만 외우는 과목이라고 생각했는데, 실제로는 개발 과정의 기본 습관에 가까웠다. 입력값을 의심하고, 권한을 최소화하고, 오류가 나도 정보를 덜 보여 주는 작은 원칙들이 모여 시스템을 지킨다는 점이 인상적이었다. 다음 복습에서는 SQL 삽입·XSS·권한 우회를 각각 어떤 방어 방식과 연결해야 하는지 다시 확인해야겠다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:36px 0 12px;color:#111827;font-size:21px;&quot;&gt;범위 확인·추가 복습 자료&lt;/h2&gt;
  &lt;p style=&quot;margin:0 0 8px;font-size:14px;color:#52606d;&quot;&gt;학습 일정의 p.5-76~p.5-141, 소프트웨어 개발 보안 설계·구현과 시스템 보안 설계 범위를 기준으로 정리했습니다. 판본에 따라 세부 페이지·용어 배열은 달라질 수 있습니다.&lt;/p&gt;
  &lt;p style=&quot;margin:0;font-size:14px;line-height:1.75;&quot;&gt;&lt;a href=&quot;https://owasp.org/Top10/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2458bc;text-decoration:underline;&quot;&gt;OWASP Top 10:2025&lt;/a&gt; · &lt;a href=&quot;https://owasp.org/Top10/2025/A01_2025-Broken_Access_Control/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2458bc;text-decoration:underline;&quot;&gt;OWASP 접근제어 실패 예방 자료&lt;/a&gt;&lt;/p&gt;
&lt;/article&gt;</description>
      <category>AI/정보처리기사_스터디</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/129</guid>
      <comments>https://onethingflow.tistory.com/entry/Day12%EC%A0%95%EC%B2%98%EA%B8%B0-5%EA%B3%BC%EB%AA%A9-%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-%EC%A0%95%EB%A6%AC-p5-76p5-141#entry129comment</comments>
      <pubDate>Tue, 28 Jul 2026 22:14:24 +0900</pubDate>
    </item>
    <item>
      <title>Day11)IT 프로젝트 정보시스템 구축관리p.5-38~p.5-72</title>
      <link>https://onethingflow.tistory.com/entry/Day11IT-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%A0%95%EB%B3%B4%EC%8B%9C%EC%8A%A4%ED%85%9C-%EA%B5%AC%EC%B6%95%EA%B4%80%EB%A6%ACp5-38p5-72</link>
      <description>&lt;!-- 티스토리 제목: 정처기 5과목 IT 프로젝트 정보시스템 구축관리 정리 | p.5-38~p.5-72 --&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;!-- 메타 설명: 정보처리기사 실기 5과목 IT 프로젝트 정보시스템 구축관리 범위를 초보자용으로 정리합니다. 네트워크·SW·HW·DB 구축관리의 핵심 개념과 선택 기준을 복습합니다. --&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;article class=&quot;hb-post hb-jeongcheogi-it-project&quot; style=&quot;max-width: 780px; margin: 0 auto; color: #1f2937; font-size: 17px; line-height: 1.82; word-break: keep-all; overflow-wrap: break-word;&quot;&gt;
&lt;p style=&quot;margin: 0 0 10px; color: #52606d; font-size: 14px;&quot; data-ke-size=&quot;size16&quot;&gt;정처기 공부 기록 &amp;middot; 실기 5과목&lt;/p&gt;
&lt;h1 style=&quot;margin: 0 0 18px; color: #111827; font-size: 32px; line-height: 1.32; letter-spacing: -0.04em;&quot;&gt;IT 프로젝트 정보시스템 구축관리&lt;br /&gt;p.5-38~p.5-72&lt;/h1&gt;
&lt;div style=&quot;margin: 0 0 28px; padding: 19px 20px; border: 1px solid #dbe7ff; border-radius: 14px; background: #f5f8ff;&quot;&gt;
&lt;p style=&quot;margin: 0 0 8px; color: #2458bc; font-weight: bold;&quot; data-ke-size=&quot;size16&quot;&gt;오늘의 한 줄 목표&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;정보시스템을 만들 때 필요한 &lt;b&gt;네트워크 &amp;middot; 소프트웨어 &amp;middot; 하드웨어 &amp;middot; 데이터베이스&lt;/b&gt;를 따로 외우지 않고, &amp;lsquo;무엇을 확인하고 어떻게 안정적으로 운영할지&amp;rsquo; 흐름으로 이해하기.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin: 36px 0 14px; color: #111827; font-size: 24px;&quot; data-ke-size=&quot;size26&quot;&gt;1. 오늘 공부한 내용&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 15px;&quot; data-ke-size=&quot;size16&quot;&gt;이번 범위는 5과목 &lt;b&gt;02. IT 프로젝트 정보시스템 구축관리&lt;/b&gt;입니다. 시스템을 실제로 운영 가능한 상태로 만들기 위해 네트워크, SW, HW, DB를 각각 설치하는 데서 끝내지 않고, &lt;b&gt;환경 파악 &amp;rarr; 제약 확인 &amp;rarr; 구축 &amp;rarr; 시험 &amp;rarr; 문서화&amp;middot;운영 인계&lt;/b&gt;까지 관리하는 내용을 다룹니다.&lt;/p&gt;
&lt;div style=&quot;margin: 16px 0 26px; border: 1px solid #d9e2ef; border-radius: 14px; overflow: hidden; background: #fff;&quot;&gt;
&lt;div style=&quot;padding: 15px 16px; border-bottom: 1px solid #e7edf5;&quot;&gt;&lt;b&gt;1&lt;/b&gt;&lt;b&gt;네트워크 구축 관리&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;display: block; margin-left: 40px; color: #52606d; font-size: 15px;&quot;&gt;통신 구조&amp;middot;주소&amp;middot;장비&amp;middot;보안&amp;middot;이중화&amp;middot;성능을 설계하고 검증&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 15px 16px; border-bottom: 1px solid #e7edf5;&quot;&gt;&lt;b&gt;2&lt;/b&gt;&lt;b&gt;SW 구축 관리&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;display: block; margin-left: 40px; color: #52606d; font-size: 15px;&quot;&gt;운영체제&amp;middot;미들웨어&amp;middot;응용SW의 호환성, 보안, 배포와 운영 기준 확인&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 15px 16px; border-bottom: 1px solid #e7edf5;&quot;&gt;&lt;b&gt;3&lt;/b&gt;&lt;b&gt;HW 구축 관리&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;display: block; margin-left: 40px; color: #52606d; font-size: 15px;&quot;&gt;서버&amp;middot;저장장치&amp;middot;가상화 자원의 성능, 용량, 가용성, 비용을 관리&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 15px 16px;&quot;&gt;&lt;b&gt;4&lt;/b&gt;&lt;b&gt;DB 구축 관리&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;display: block; margin-left: 40px; color: #52606d; font-size: 15px;&quot;&gt;DBMS 선정, 데이터 이행, 백업&amp;middot;복구, 권한과 성능을 관리&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 style=&quot;margin: 30px 0 12px; color: #172033; font-size: 21px;&quot; data-ke-size=&quot;size23&quot;&gt;정보시스템 구축관리의 큰 흐름&lt;/h3&gt;
&lt;div style=&quot;margin: 0 0 22px; padding: 18px; border-left: 4px solid #315efb; background: #f6f8ff;&quot;&gt;
&lt;p style=&quot;margin: 0 0 8px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 현황&amp;middot;요구사항 파악&lt;/b&gt; &amp;mdash; 현재 장비, 사용자 수, 연계 시스템, 보안&amp;middot;성능 요구를 조사합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 8px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) 제약사항 식별&lt;/b&gt; &amp;mdash; 예산, 납기, 공간&amp;middot;전력, 기존 기술, 법&amp;middot;보안 규정, 운영 인력의 한계를 확인합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 8px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) 구축&amp;middot;연동&amp;middot;시험&lt;/b&gt; &amp;mdash; 장비와 프로그램을 설치하고, 다른 시스템과 연결한 뒤 기능&amp;middot;성능&amp;middot;장애 상황을 시험합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4) 문서화&amp;middot;운영 인계&lt;/b&gt; &amp;mdash; 구성도, 계정&amp;middot;권한, 설정값, 장애 대응&amp;middot;백업 절차를 남겨 실제 운영팀에 넘깁니다.&lt;/p&gt;
&lt;/div&gt;
&lt;p style=&quot;margin: 0 0 20px;&quot; data-ke-size=&quot;size16&quot;&gt;시험에서는 특정 장비 이름만 묻기보다, &amp;lsquo;가용성&amp;middot;성능&amp;middot;기술 지원&amp;middot;보안&amp;middot;구축 비용&amp;rsquo;처럼 &lt;b&gt;구축 시 고려할 기준&lt;/b&gt;을 묻는 형태가 많습니다. 네 가지 인프라를 같은 기준으로 비교해 두면 기억하기 편합니다.&lt;/p&gt;
&lt;h3 style=&quot;margin: 30px 0 12px; color: #172033; font-size: 21px;&quot; data-ke-size=&quot;size23&quot;&gt;네트워크 구축 관리&lt;/h3&gt;
&lt;p style=&quot;margin: 0 0 15px;&quot; data-ke-size=&quot;size16&quot;&gt;네트워크는 사용자&amp;middot;서버&amp;middot;외부 서비스를 연결하는 길입니다. 길을 만든다는 것은 케이블이나 스위치를 설치하는 것만 뜻하지 않습니다. 트래픽이 몰렸을 때도 서비스가 끊기지 않고, 허가되지 않은 접근을 막으며, 장애 원인을 찾을 수 있게 설계하는 일까지 포함합니다.&lt;/p&gt;
&lt;div style=&quot;margin: 0 0 22px; border: 1px solid #d9e2ef; border-radius: 14px; overflow: hidden; background: #fff;&quot;&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; border-bottom: 1px solid #e7edf5;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;구조와 용량&lt;/b&gt; &amp;mdash; 사용자 수, 서버 위치, LAN&amp;middot;WAN 구성, 예상 트래픽, 대역폭, IP 주소 체계와 서브넷을 확인합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; border-bottom: 1px solid #e7edf5; background: #fbfcfe;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장비와 역할&lt;/b&gt; &amp;mdash; 스위치는 같은 네트워크 안의 장비 연결, 라우터는 서로 다른 네트워크 사이 경로 선택, 방화벽은 정책에 따라 통신을 허용&amp;middot;차단합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; border-bottom: 1px solid #e7edf5;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;가용성과 이중화&lt;/b&gt; &amp;mdash; 핵심 회선&amp;middot;장비를 하나만 두지 않고 이중화해, 한쪽 장애 시 다른 경로로 서비스를 이어갑니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; border-bottom: 1px solid #e7edf5; background: #fbfcfe;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;보안과 모니터링&lt;/b&gt; &amp;mdash; 접근 통제, 망 분리, 로그 수집, 침입 탐지&amp;middot;차단, 장애 알림과 복구 절차를 함께 설계합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;검증&lt;/b&gt; &amp;mdash; 연결 여부만이 아니라 응답 시간, 처리량, 장애 전환, 보안 정책 적용 여부까지 시험합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&quot;margin: 0 0 22px; padding: 17px 18px; border-radius: 12px; background: #fff8e7; border: 1px solid #f2d490;&quot;&gt;
&lt;p style=&quot;margin: 0 0 7px; color: #805100; font-weight: bold;&quot; data-ke-size=&quot;size16&quot;&gt;네트워크 신기술 한 줄 정리&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SDN&lt;/b&gt;은 제어 기능과 데이터 전달 기능을 분리해 네트워크를 소프트웨어적으로 관리하는 방식이고, &lt;b&gt;NFV&lt;/b&gt;는 방화벽&amp;middot;로드밸런서 같은 네트워크 기능을 전용 장비 대신 가상화 환경에서 제공하는 방식입니다. 둘 다 유연한 운영&amp;middot;확장과 연결합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 style=&quot;margin: 30px 0 12px; color: #172033; font-size: 21px;&quot; data-ke-size=&quot;size23&quot;&gt;SW 구축 관리&lt;/h3&gt;
&lt;p style=&quot;margin: 0 0 15px;&quot; data-ke-size=&quot;size16&quot;&gt;SW 구축 관리는 응용 프로그램만 설치하는 일이 아닙니다. 운영체제(OS), 웹&amp;middot;애플리케이션 서버 같은 미들웨어, DBMS, 프레임워크, 보안 솔루션까지 서로 충돌 없이 동작하도록 구성하고 운영 기준을 만드는 일입니다.&lt;/p&gt;
&lt;div style=&quot;margin: 0 0 22px; padding: 18px; border: 1px solid #d9e2ef; border-radius: 14px; background: #fff;&quot;&gt;
&lt;p style=&quot;margin: 0 0 11px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;호환성&lt;/b&gt; &amp;mdash; 운영체제, CPU 구조, 미들웨어, DBMS, 기존 연계 시스템과 버전이 맞는지 확인합니다. &amp;lsquo;좋은 제품&amp;rsquo;보다 &amp;lsquo;우리 환경에서 함께 동작하는 제품&amp;rsquo;이 중요합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 11px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;성능&amp;middot;확장성&lt;/b&gt; &amp;mdash; 동시 접속자와 처리량, 향후 기능&amp;middot;사용자 증가에 따라 서버 증설 또는 수평 확장이 가능한지 봅니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 11px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;보안&amp;middot;패치&lt;/b&gt; &amp;mdash; 계정 권한, 취약점 패치, 로그 관리, 암호화, 보안 설정 기준을 포함합니다. 보안 기능을 커널 수준에 적용해 시스템 자원을 보호하는 &lt;b&gt;Secure OS&lt;/b&gt;도 관련 키워드입니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 11px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;배포&amp;middot;형상 관리&lt;/b&gt; &amp;mdash; 개발&amp;middot;시험&amp;middot;운영 환경을 구분하고, 배포 버전과 설정 변경 이력을 남겨 문제가 생기면 되돌릴 수 있게 합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;유지보수성&lt;/b&gt; &amp;mdash; 제품 지원 기간, 기술 지원, 라이선스, 운영 문서, 장애 대응 체계까지 확인합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 style=&quot;margin: 30px 0 12px; color: #172033; font-size: 21px;&quot; data-ke-size=&quot;size23&quot;&gt;HW 구축 관리&lt;/h3&gt;
&lt;p style=&quot;margin: 0 0 15px;&quot; data-ke-size=&quot;size16&quot;&gt;HW 구축 관리는 서버&amp;middot;스토리지&amp;middot;백업 장치 같은 물리 자원을 필요한 성능과 안정성으로 확보하는 일입니다. 초기 구매 가격만 보면 안 되고, 운영&amp;middot;전력&amp;middot;유지보수&amp;middot;교체까지 포함한 비용을 봐야 합니다.&lt;/p&gt;
&lt;div style=&quot;margin: 0 0 20px; border: 1px solid #d9e2ef; border-radius: 14px; overflow-x: auto; background: #fff;&quot;&gt;
&lt;table style=&quot;width: 100%; min-width: 650px; border-collapse: collapse; font-size: 15px; line-height: 1.65;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background: #f1f5ff; color: #223f7a;&quot;&gt;
&lt;th style=&quot;padding: 11px; text-align: left; border-bottom: 1px solid #d9e2ef;&quot;&gt;확인 항목&lt;/th&gt;
&lt;th style=&quot;padding: 11px; text-align: left; border-bottom: 1px solid #d9e2ef;&quot;&gt;무엇을 보는가?&lt;/th&gt;
&lt;th style=&quot;padding: 11px; text-align: left; border-bottom: 1px solid #d9e2ef;&quot;&gt;초보자식 질문&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;성능&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;CPU, 메모리, 디스크 I/O, 네트워크 처리 능력&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;사용자가 몰려도 느리지 않은가?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background: #fbfcfe;&quot;&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;용량&amp;middot;확장성&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;저장 공간, 슬롯, 증설 가능성&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;데이터와 사용자가 늘면 키울 수 있는가?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;가용성&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;이중 전원, RAID, 클러스터, 예비 장비&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;한 부품이 고장 나도 멈추지 않는가?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background: #fbfcfe;&quot;&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;운영 환경&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;전력, 발열, 공간, 랙, 장애 대응&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;실제 설치&amp;middot;운영할 장소와 인력이 준비됐는가?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px;&quot;&gt;&lt;b&gt;TCO&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px;&quot;&gt;구매&amp;middot;설치&amp;middot;운영&amp;middot;전력&amp;middot;유지보수&amp;middot;교체의 총비용&lt;/td&gt;
&lt;td style=&quot;padding: 10px;&quot;&gt;싼 가격이 정말 싼 선택인가?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p style=&quot;margin: 0 0 22px;&quot; data-ke-size=&quot;size16&quot;&gt;가상화는 하나의 물리 서버 자원을 여러 가상 서버처럼 나누어 쓰는 기술입니다. 자원 활용률을 높이고 증설을 빠르게 할 수 있지만, 자원 경쟁&amp;middot;장애 영향 범위와 백업&amp;middot;복구 정책도 함께 관리해야 합니다.&lt;/p&gt;
&lt;h3 style=&quot;margin: 30px 0 12px; color: #172033; font-size: 21px;&quot; data-ke-size=&quot;size23&quot;&gt;DB 구축 관리&lt;/h3&gt;
&lt;p style=&quot;margin: 0 0 15px;&quot; data-ke-size=&quot;size16&quot;&gt;DB 구축 관리는 데이터를 저장할 DBMS를 고르고 설치하는 것에서 끝나지 않습니다. 기존 데이터를 안전하게 옮기고, 성능을 확인하며, 권한&amp;middot;백업&amp;middot;복구 기준을 운영 단계까지 이어가는 과정입니다.&lt;/p&gt;
&lt;div style=&quot;margin: 0 0 22px; border: 1px solid #d9e2ef; border-radius: 14px; overflow: hidden; background: #fff;&quot;&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; border-bottom: 1px solid #e7edf5;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DBMS 선정&lt;/b&gt; &amp;mdash; 데이터 규모, 동시 사용자, 트랜잭션 처리, 기존 시스템 호환성, 보안, 기술 지원, 라이선스와 비용을 비교합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; border-bottom: 1px solid #e7edf5; background: #fbfcfe;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;데이터 이행&lt;/b&gt; &amp;mdash; 기존 데이터의 형식&amp;middot;코드&amp;middot;누락&amp;middot;중복을 확인하고 변환한 뒤, 이행 전후 데이터가 맞는지 검증합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; border-bottom: 1px solid #e7edf5;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;성능&lt;/b&gt; &amp;mdash; 인덱스, 실행 계획, 저장 구조, 동시 처리량을 점검해 조회&amp;middot;등록이 느려지지 않게 합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; border-bottom: 1px solid #e7edf5; background: #fbfcfe;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;보안&amp;middot;권한&lt;/b&gt; &amp;mdash; 사용자별 접근 권한을 최소 권한 원칙으로 부여하고, 중요 데이터 접근&amp;middot;변경 로그를 남깁니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;백업&amp;middot;복구&amp;middot;장애 대응&lt;/b&gt; &amp;mdash; 백업을 &amp;lsquo;해두는 것&amp;rsquo;만으로 충분하지 않습니다. 실제 복구 시험을 해 보고, 장애 시 복구 목표 시간과 절차를 문서화해야 합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&quot;margin: 0 0 23px; padding: 18px; border-radius: 14px; background: #fff8e7; border: 1px solid #f2d490;&quot;&gt;
&lt;p style=&quot;margin: 0 0 8px; color: #805100; font-weight: bold;&quot; data-ke-size=&quot;size16&quot;&gt;네 가지를 한 번에 구분하는 법&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;네트워크&lt;/b&gt;는 &amp;lsquo;어떻게 연결할까?&amp;rsquo;, &lt;b&gt;SW&lt;/b&gt;는 &amp;lsquo;어떤 프로그램 조합으로 실행할까?&amp;rsquo;, &lt;b&gt;HW&lt;/b&gt;는 &amp;lsquo;어떤 물리 자원으로 버틸까?&amp;rsquo;, &lt;b&gt;DB&lt;/b&gt;는 &amp;lsquo;데이터를 어떻게 안전하게 저장&amp;middot;복구할까?&amp;rsquo;에 답합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin: 36px 0 14px; color: #111827; font-size: 24px;&quot; data-ke-size=&quot;size26&quot;&gt;2. 공부하면서 개인적으로 중요하다고 생각하는 용어&lt;/h2&gt;
&lt;div style=&quot;margin: 15px 0 22px; padding: 18px; border-radius: 14px; background: #f5f8ff; border: 1px solid #dbe7ff;&quot;&gt;
&lt;p style=&quot;margin: 0 0 12px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;① 가용성(Availability)&lt;/b&gt;&lt;br /&gt;서비스가 필요할 때 계속 사용할 수 있는 정도다. 이중화, 장애 전환, 백업&amp;middot;복구와 함께 기억한다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 12px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;② TCO(Total Cost of Ownership)&lt;/b&gt;&lt;br /&gt;장비의 구매가만이 아니라 설치&amp;middot;운영&amp;middot;전력&amp;middot;유지보수&amp;middot;교체까지 포함한 총소유비용이다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 12px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;③ 이중화(Redundancy)&lt;/b&gt;&lt;br /&gt;하나가 고장 나도 전체 서비스가 멈추지 않도록 회선&amp;middot;장비&amp;middot;전원&amp;middot;데이터를 여분으로 구성하는 방식이다.&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;④ 데이터 이행(Data Migration)&lt;/b&gt;&lt;br /&gt;기존 데이터를 새 시스템으로 옮기는 과정이며, 변환 자체보다 이행 전후 데이터 검증이 중요하다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin: 36px 0 14px; color: #111827; font-size: 24px;&quot; data-ke-size=&quot;size26&quot;&gt;3. 공부하면서 이해하지 못한 용어&lt;/h2&gt;
&lt;div style=&quot;margin: 15px 0 22px; padding: 18px; border-radius: 14px; background: #fffaf0; border: 1px solid #f3d99c;&quot;&gt;
&lt;p style=&quot;margin: 0 0 12px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;① SDN과 NFV의 차이&lt;/b&gt;&lt;br /&gt;SDN은 네트워크를 제어하는 방식을 소프트웨어 중심으로 바꾸는 개념이고, NFV는 방화벽&amp;middot;로드밸런서 같은 네트워크 기능을 가상화하는 개념이다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 12px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;② 백업과 복구의 차이&lt;/b&gt;&lt;br /&gt;백업은 데이터를 보관하는 행위, 복구는 장애 뒤 백업본으로 서비스를 다시 살리는 행위다. 따라서 복구 시험까지 해야 한다.&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;③ 성능과 가용성의 차이&lt;/b&gt;&lt;br /&gt;성능은 빠르게 처리하는 능력, 가용성은 장애가 나도 계속 이용할 수 있는 능력이다. 빠르지만 자주 멈추면 가용성이 낮다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin: 36px 0 14px; color: #111827; font-size: 24px;&quot; data-ke-size=&quot;size26&quot;&gt;4. 오늘 공부한것 소회&lt;/h2&gt;
&lt;div style=&quot;margin: 15px 0 26px; padding: 19px 20px; border-left: 4px solid #315efb; background: #f6f8ff;&quot;&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;처음에는 네트워크&amp;middot;SW&amp;middot;HW&amp;middot;DB 구축관리가 각각 완전히 다른 단원처럼 보였다. 하지만 네 가지 모두 &lt;b&gt;성능, 가용성, 보안, 확장성, 비용, 운영 가능성&lt;/b&gt;을 확인한다는 공통점이 있었다. 앞으로는 기술 이름만 암기하기보다 &amp;ldquo;장애가 나면 어떻게 되는가, 사용자가 늘면 어떻게 되는가, 운영팀이 관리할 수 있는가&amp;rdquo;를 먼저 생각하며 복습해야겠다.&lt;/p&gt;
&lt;/div&gt;
&lt;p style=&quot;margin: 0; font-size: 14px; line-height: 1.75;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/article&gt;</description>
      <category>AI/정보처리기사_스터디</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/127</guid>
      <comments>https://onethingflow.tistory.com/entry/Day11IT-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%A0%95%EB%B3%B4%EC%8B%9C%EC%8A%A4%ED%85%9C-%EA%B5%AC%EC%B6%95%EA%B4%80%EB%A6%ACp5-38p5-72#entry127comment</comments>
      <pubDate>Sat, 25 Jul 2026 16:45:26 +0900</pubDate>
    </item>
    <item>
      <title>Day 15) 프로그래머스 파이썬 조건 변환과 반복문 5문제 풀</title>
      <link>https://onethingflow.tistory.com/entry/Day-15-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%A1%B0%EA%B1%B4-%EB%B3%80%ED%99%98%EA%B3%BC-%EB%B0%98%EB%B3%B5%EB%AC%B8-5%EB%AC%B8%EC%A0%9C-%ED%92%80</link>
      <description>&lt;!--
Title: Day 15) 프로그래머스 파이썬 조건 변환과 반복문 5문제 풀이
Meta description: 프로그래머스 코딩 기초 트레이닝 Day 15의 조건에 맞게 수열 변환하기 1·2, 1로 만들기, 길이에 따른 연산, 원하는 문자열 찾기를 직접 작성한 코드와 오류 수정 과정 중심으로 정리했습니다.
Tags: 프로그래머스, 코딩테스트, 파이썬, Day15, 조건문, 반복문, while, 정수나눗셈, math.prod, 문자열, lower
--&gt;

&lt;article class=&quot;hb-post hb-day15-transform hb-paste-safe&quot; style=&quot;max-width:860px;margin:0 auto;color:#17211d;font-size:17px;line-height:1.8;word-break:keep-all;overflow-wrap:anywhere;&quot;&gt;
  &lt;style&gt;&lt;/style&gt;

  &lt;header style=&quot;margin:0 0 34px;padding:30px 26px;color:#ffffff;background:#145c4b;border-radius:8px;&quot;&gt;
    &lt;p style=&quot;margin:0 0 8px;color:#d7f5e9;font-size:14px;font-weight:800;&quot;&gt;Programmers Coding Test · Day 15 · Python&lt;/p&gt;
    &lt;h1 style=&quot;margin:0;color:#ffffff;font-size:31px;line-height:1.35;letter-spacing:0;&quot;&gt;Day 15&lt;br&gt;조건 변환과 반복문 5문제 풀이&lt;/h1&gt;
    &lt;p style=&quot;margin:14px 0 0;color:#e8fff6;font-size:18px;&quot;&gt;정수 나눗셈, 이전 상태와 다음 상태 비교, 중첩 반복문, 문자열 대소문자 통일까지 직접 작성한 코드의 흐름을 따라 정리했습니다.&lt;/p&gt;
  &lt;/header&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;이번 문제들은 조건식 자체보다 &lt;strong&gt;값의 자료형&lt;/strong&gt;, &lt;strong&gt;반복문 안팎의 들여쓰기&lt;/strong&gt;, &lt;strong&gt;현재 상태와 다음 상태의 비교&lt;/strong&gt;를 정확하게 다루는 연습이었다. 특히 배열이 더 이상 변하지 않을 때까지 반복하는 문제는 한 번의 변환을 만드는 코드와 멈추는 시점을 나누어 생각하는 것이 핵심이었다.&lt;/p&gt;

  &lt;div style=&quot;margin:20px 0;padding:17px 19px;background:#edf8f3;border-left:4px solid #176b57;border-radius:8px;&quot;&gt;
    &lt;strong style=&quot;display:block;margin-bottom:4px;&quot;&gt;오늘의 핵심&lt;/strong&gt;
    &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;/&lt;/code&gt;는 실수를 만들고 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;//&lt;/code&gt;는 몫을 만든다. 배열 변환을 반복할 때는 기존 배열과 새 배열을 비교하고, 값이 아니라 인덱스가 필요한 반복인지도 먼저 판단한다.
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:50px 0 16px;padding-bottom:10px;color:#17211d;font-size:27px;line-height:1.4;letter-spacing:0;border-bottom:2px solid #d8e1dc;&quot;&gt;문제 및 공식 링크&lt;/h2&gt;

  &lt;div style=&quot;width:100%;margin:16px 0 24px;overflow-x:auto;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:700px;border-collapse:collapse;font-size:15px;&quot;&gt;
      &lt;caption style=&quot;padding:12px 14px;color:#33433c;background:#f5f8f6;font-weight:800;text-align:left;&quot;&gt;프로그래머스 코딩 기초 트레이닝 Day 15&lt;/caption&gt;
      &lt;thead&gt;&lt;tr&gt;&lt;th scope=&quot;col&quot; style=&quot;padding:12px 14px;text-align:left;background:#f8faf9;border-bottom:1px solid #d8e1dc;&quot;&gt;순서&lt;/th&gt;&lt;th scope=&quot;col&quot; style=&quot;padding:12px 14px;text-align:left;background:#f8faf9;border-bottom:1px solid #d8e1dc;&quot;&gt;문제&lt;/th&gt;&lt;th scope=&quot;col&quot; style=&quot;padding:12px 14px;text-align:left;background:#f8faf9;border-bottom:1px solid #d8e1dc;&quot;&gt;핵심 개념&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;1&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181882&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#086f5b;text-underline-offset:3px;&quot;&gt;조건에 맞게 수열 변환하기 1&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;조건 분기, &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;//&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;2&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181881&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#086f5b;text-underline-offset:3px;&quot;&gt;조건에 맞게 수열 변환하기 2&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;상태 비교, &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;while&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;3&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181880&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#086f5b;text-underline-offset:3px;&quot;&gt;1로 만들기&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;중첩 반복문, 몫 나눗셈&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;4&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181879&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#086f5b;text-underline-offset:3px;&quot;&gt;길이에 따른 연산&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;합, 곱, 조건부 표현식&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:12px 14px;&quot;&gt;5&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181878&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#086f5b;text-underline-offset:3px;&quot;&gt;원하는 문자열 찾기&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;&quot;&gt;문자열 메서드, &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;in&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:50px 0 16px;padding-bottom:10px;color:#17211d;font-size:27px;line-height:1.4;letter-spacing:0;border-bottom:2px solid #d8e1dc;&quot;&gt;1. 조건에 맞게 수열 변환하기 1&lt;/h2&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;각 원소가 50 이상인 짝수라면 2로 나누고, 50 미만인 홀수라면 2를 곱하는 문제다. 나머지 원소는 그대로 둔다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;처음 작성한 코드&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(arr):
    answer = []

    for num in arr:
        if num &amp;gt;= 50 and num % 2 == 0:
            answer.append(num / 2)
        elif num &amp;lt;= 50 and num % 2 != 0:
            answer.append(num * 2)
        else:
            answer.append(num)

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;세 갈래로 나누어 결과를 새 리스트에 넣는 전체 흐름은 정확했다. 다만 첫 번째 조건의 나눗셈 기호 하나 때문에 반환값의 자료형이 달라진다.&lt;/p&gt;

  &lt;div style=&quot;display:grid;gap:12px;margin:17px 0 24px;&quot;&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;1&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;/&lt;/code&gt;는 일반 나눗셈이다&lt;/strong&gt;&lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;50 / 2&lt;/code&gt;의 결과는 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;25.0&lt;/code&gt;이다. 문제는 정수 배열을 요구하므로 실수가 섞이지 않도록 해야 한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;2&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;지문대로 &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;num &amp;lt; 50&lt;/code&gt;이라고 적는다&lt;/strong&gt;50은 짝수라 두 번째 조건에서 실제 결과는 같지만, 문제의 조건이 50보다 작은 홀수이므로 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;&amp;lt; 50&lt;/code&gt;이 더 정확하고 읽기 쉽다.&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;수정한 기본 풀이&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(arr):
    answer = []

    for num in arr:
        if num &amp;gt;= 50 and num % 2 == 0:
            answer.append(num // 2)
        elif num &amp;lt; 50 and num % 2 != 0:
            answer.append(num * 2)
        else:
            answer.append(num)

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;리스트 컴프리헨션 풀이&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(arr):
    return [num // 2 if num &amp;gt;= 50 and num % 2 == 0
            else num * 2 if num &amp;lt; 50 and num % 2 != 0
            else num
            for num in arr]&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;한 줄로 줄일 수는 있지만 조건이 세 갈래라면 처음에는 일반 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;for&lt;/code&gt;문 풀이가 더 읽기 쉽다. 공식 예제 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;[1, 2, 3, 100, 99, 98]&lt;/code&gt;은 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;[2, 2, 6, 50, 99, 49]&lt;/code&gt;가 된다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:50px 0 16px;padding-bottom:10px;color:#17211d;font-size:27px;line-height:1.4;letter-spacing:0;border-bottom:2px solid #d8e1dc;&quot;&gt;2. 조건에 맞게 수열 변환하기 2&lt;/h2&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;첫 번째 문제의 조건과 비슷하지만, 50 미만인 홀수는 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;2를 곱한 뒤 1을 더하고&lt;/code&gt;, 배열이 더 이상 변하지 않을 때까지 이 작업을 반복한다. 문제의 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;arr(x)&lt;/code&gt;는 함수 호출 문법이 아니라 “x번 변환한 배열”을 뜻하는 수학 표기다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;처음 떠올린 흐름과 막힌 지점&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(arr):
    arr(x)

    while arr(x) = arr(x + 1):
        for num in arr:
            if num &amp;gt;= 50 and num % 2 == 0:
                arr = num // 2
            elif num &amp;lt;= 50 and num != 2:
                arr = num * 2 + 1

    return arr&lt;/code&gt;&lt;/pre&gt;

  &lt;div style=&quot;display:grid;gap:12px;margin:17px 0 24px;&quot;&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;1&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;수학 표기와 코드 문법은 다르다&lt;/strong&gt;&lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;arr(x)&lt;/code&gt;는 문제 설명의 표기다. 파이썬에서 리스트 뒤에 괄호를 붙이면 함수를 호출하려는 것으로 해석된다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;2&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;배열 전체를 숫자로 덮어쓰면 안 된다&lt;/strong&gt;변환한 원소는 새 리스트에 하나씩 모아야 한다. &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;arr = num // 2&lt;/code&gt;는 리스트를 숫자 하나로 바꿔 버린다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;3&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;홀수는 &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;num % 2 != 0&lt;/code&gt;으로 확인한다&lt;/strong&gt;&lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;num % 2 != 2&lt;/code&gt;는 나머지가 0 또는 1인 모든 정수에 대해 참이 된다. 50 미만의 짝수까지 잘못 변환하는 원인이다.&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;시간 초과가 난 이유: 들여쓰기&lt;/h3&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;새 배열을 만든 뒤의 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;if old == new&lt;/code&gt;, 배열 교체, 카운트 증가가 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;while&lt;/code&gt;문 바깥에 있으면 반복문은 탈출 조건을 절대 만나지 못한다. 파이썬에서는 들여쓰기가 코드 블록의 소속을 결정하므로 이 세 줄도 반드시 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;while&lt;/code&gt; 안에 있어야 한다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;내가 완성한 풀이&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(arr):
    answer = 0
    old = arr

    while True:
        new = []

        for i in old:
            if i &amp;gt;= 50 and i % 2 == 0:
                new.append(i // 2)
            elif i &amp;lt; 50 and i % 2 == 1:
                new.append(i * 2 + 1)
            else:
                new.append(i)

        if old == new:
            break

        old = new
        answer += 1

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;이 풀이는 정답이다. 처음에는 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;i / 2&lt;/code&gt; 뒤에 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;int(i)&lt;/code&gt;를 씌워 정수로 바꾸는 방식도 가능했지만, 조건상 나누는 수는 짝수이므로 처음부터 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;i // 2&lt;/code&gt;를 쓰는 편이 더 직접적이다.&lt;/p&gt;

  &lt;div style=&quot;margin:20px 0;padding:17px 19px;background:#edf8f3;border-left:4px solid #176b57;border-radius:8px;&quot;&gt;
    &lt;strong style=&quot;display:block;margin-bottom:4px;&quot;&gt;break를 만나면 answer가 0인 것 아닌가?&lt;/strong&gt;
    아니다. &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;answer += 1&lt;/code&gt;은 배열이 실제로 바뀌었을 때만 실행된다. 처음부터 변하지 않으면 0에서 바로 멈추는 것이 맞고, 예를 들어 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;[100]&lt;/code&gt;은 [100] → [50] → [25] → [51]로 세 번 바뀐 뒤 [51]에서 멈추므로 3을 반환한다.
  &lt;/div&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;&lt;strong&gt;검산:&lt;/strong&gt; 공식 예제 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;[1, 2, 3, 100, 99, 98]&lt;/code&gt;은 다섯 번 변환한 배열과 여섯 번 변환한 배열이 같아지므로 5를 반환한다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:50px 0 16px;padding-bottom:10px;color:#17211d;font-size:27px;line-height:1.4;letter-spacing:0;border-bottom:2px solid #d8e1dc;&quot;&gt;3. 1로 만들기&lt;/h2&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;리스트의 각 정수를 1이 될 때까지 반으로 줄이고, 필요한 나누기 연산 횟수의 총합을 구하는 문제다. 짝수는 반으로 나누고, 홀수는 1을 뺀 뒤 반으로 나눈다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;처음 시도에서 보완할 점&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(num_list):
    answer = 0

    while True:
        num = 0
        for i in num_list:
            if i % 2 == 0:
                num = i // 2
            else:
                num = (i - 1) // 2

        if num == 1:
            return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;&lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;num&lt;/code&gt; 하나에 계산 결과를 넣으면 반복할 때마다 앞의 값이 덮어써져 마지막 원소만 남는다. 이 문제는 배열 전체를 한꺼번에 새 배열로 바꾸기보다, 원소 하나를 꺼내서 1이 될 때까지 처리하는 구조가 자연스럽다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;내 풀이&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(num_list):
    answer = 0

    for n in num_list:
        while n != 1:
            n //= 2
            answer += 1

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;이 코드는 양의 정수라는 문제 조건에서 정확하다. 홀수 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;n&lt;/code&gt;에 대해 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;n // 2&lt;/code&gt;는 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;(n - 1) // 2&lt;/code&gt;와 같으므로 짝수와 홀수를 따로 나눌 필요가 없다.&lt;/p&gt;

  &lt;div style=&quot;margin:20px 0;padding:17px 19px;background:#fff5ed;border-left:4px solid #a84412;border-radius:8px;&quot;&gt;
    &lt;strong style=&quot;display:block;margin-bottom:4px;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;/&lt;/code&gt;와 &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;//&lt;/code&gt;의 차이&lt;/strong&gt;
    소수점까지 정확한 나눗셈이 필요하면 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;/&lt;/code&gt;를 쓴다. 예를 들어 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;5 / 2&lt;/code&gt;는 2.5다. 반대로 이번 문제처럼 소수점 아래를 버리고 정수 몫만 필요하면 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;//&lt;/code&gt;를 사용한다. &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;5 // 2&lt;/code&gt;는 2다.
  &lt;/div&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;&lt;strong&gt;검산:&lt;/strong&gt; &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;[12, 4, 15, 1, 14]&lt;/code&gt;에서는 각각 3, 2, 3, 0, 3번이 필요해 총 11을 반환한다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:50px 0 16px;padding-bottom:10px;color:#17211d;font-size:27px;line-height:1.4;letter-spacing:0;border-bottom:2px solid #d8e1dc;&quot;&gt;4. 길이에 따른 연산&lt;/h2&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;리스트 길이가 11 이상이면 모든 원소의 합을, 10 이하이면 모든 원소의 곱을 반환하는 문제다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;내 풀이&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(num_list):
    answer = 1

    if len(num_list) &amp;gt; 10:
        answer = sum(num_list)
    else:
        for i in num_list:
            answer *= i

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;이 풀이는 정답이다. 곱셈의 초기값을 1로 둔 점이 중요하다. 0으로 시작하면 어떤 수를 곱해도 0이 된다. &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;len(num_list) &amp;gt; 10&lt;/code&gt;은 “길이가 11 이상”과 같은 뜻이다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;math.prod()와 조건부 표현식&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;from math import prod


def solution(num_list):
    return sum(num_list) if len(num_list) &amp;gt;= 11 else prod(num_list)&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;작성한 한 줄 풀이도 정답이다. 다만 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;from math import prod&lt;/code&gt;와 함수 정의는 서로 다른 문장이므로 반드시 줄을 나누어 적는다. 조건부 표현식은 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;참일 때 값 if 조건 else 거짓일 때 값&lt;/code&gt; 순서로 읽으면 된다.&lt;/p&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;&lt;strong&gt;검산:&lt;/strong&gt; 길이가 13인 공식 예제는 합계 51을, &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;[2, 3, 4, 5]&lt;/code&gt;는 곱 120을 반환한다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:50px 0 16px;padding-bottom:10px;color:#17211d;font-size:27px;line-height:1.4;letter-spacing:0;border-bottom:2px solid #d8e1dc;&quot;&gt;5. 원하는 문자열 찾기&lt;/h2&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;대소문자를 구분하지 않고 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;myString&lt;/code&gt; 안에 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;pat&lt;/code&gt;이 연속된 부분 문자열로 존재하는지 확인하는 문제다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;처음 시도&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(myString, pat):
    my_string = super(myString)
    pat = super(pat)

    if pat in my_string:
        return 1
    else:
        return 0&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;&lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;pat in my_string&lt;/code&gt;이라는 포함 여부 검사 방향은 정확했다. 다만 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;super()&lt;/code&gt;는 부모 클래스 관련 기능이고, 문자열을 통일하는 메서드가 아니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;수정한 기본 풀이&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(myString, pat):
    my_string = myString.lower()
    pat = pat.lower()

    if pat in my_string:
        return 1

    return 0&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;&lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;lower()&lt;/code&gt;는 문자열 뒤에 점을 붙여 호출하는 메서드다. 두 문자열을 모두 소문자로 통일한 뒤 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;in&lt;/code&gt;으로 검사하면 대소문자를 구분하지 않는 비교가 된다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;내가 줄인 한 줄 풀이&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(myString, pat):
    return int(pat.lower() in myString.lower())&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;이 코드도 정답이다. &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;in&lt;/code&gt;의 결과는 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;True&lt;/code&gt; 또는 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;False&lt;/code&gt;이고, 파이썬에서 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;int(True)&lt;/code&gt;는 1, &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;int(False)&lt;/code&gt;는 0이다.&lt;/p&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;&lt;strong&gt;검산:&lt;/strong&gt; &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;&quot;AbCdEfG&quot;&lt;/code&gt;와 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;&quot;aBc&quot;&lt;/code&gt;은 1을, &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;&quot;aaAA&quot;&lt;/code&gt;와 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;&quot;aaaaa&quot;&lt;/code&gt;는 0을 반환한다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:50px 0 16px;padding-bottom:10px;color:#17211d;font-size:27px;line-height:1.4;letter-spacing:0;border-bottom:2px solid #d8e1dc;&quot;&gt;실수 방지 체크리스트&lt;/h2&gt;

  &lt;div style=&quot;display:grid;gap:10px;margin:15px 0;&quot;&gt;
    &lt;div style=&quot;display:grid;grid-template-columns:25px minmax(0,1fr);gap:8px;align-items:start;&quot;&gt;&lt;span style=&quot;color:#176b57;font-weight:900;text-align:center;&quot;&gt;✓&lt;/span&gt;&lt;div&gt;정수 결과가 필요한 나눗셈에는 &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;//&lt;/code&gt;를 사용한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div style=&quot;display:grid;grid-template-columns:25px minmax(0,1fr);gap:8px;align-items:start;&quot;&gt;&lt;span style=&quot;color:#176b57;font-weight:900;text-align:center;&quot;&gt;✓&lt;/span&gt;&lt;div&gt;홀수 조건은 &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;num % 2 != 0&lt;/code&gt; 또는 &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;num % 2 == 1&lt;/code&gt;로 쓴다.&lt;/div&gt;&lt;/div&gt;
    &lt;div style=&quot;display:grid;grid-template-columns:25px minmax(0,1fr);gap:8px;align-items:start;&quot;&gt;&lt;span style=&quot;color:#176b57;font-weight:900;text-align:center;&quot;&gt;✓&lt;/span&gt;&lt;div&gt;반복 종료 조건, 상태 갱신, 카운트 증가가 모두 &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;while&lt;/code&gt; 블록 안에 있는지 확인한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div style=&quot;display:grid;grid-template-columns:25px minmax(0,1fr);gap:8px;align-items:start;&quot;&gt;&lt;span style=&quot;color:#176b57;font-weight:900;text-align:center;&quot;&gt;✓&lt;/span&gt;&lt;div&gt;리스트 전체를 숫자 하나로 덮어쓰지 않고, 필요하면 새 리스트에 값을 모은다.&lt;/div&gt;&lt;/div&gt;
    &lt;div style=&quot;display:grid;grid-template-columns:25px minmax(0,1fr);gap:8px;align-items:start;&quot;&gt;&lt;span style=&quot;color:#176b57;font-weight:900;text-align:center;&quot;&gt;✓&lt;/span&gt;&lt;div&gt;곱셈 누적 변수의 시작값은 1이다.&lt;/div&gt;&lt;/div&gt;
    &lt;div style=&quot;display:grid;grid-template-columns:25px minmax(0,1fr);gap:8px;align-items:start;&quot;&gt;&lt;span style=&quot;color:#176b57;font-weight:900;text-align:center;&quot;&gt;✓&lt;/span&gt;&lt;div&gt;문자열 전용 기능은 &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;myString.lower()&lt;/code&gt;처럼 점 표기법으로 호출한다.&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:50px 0 16px;padding-bottom:10px;color:#17211d;font-size:27px;line-height:1.4;letter-spacing:0;border-bottom:2px solid #d8e1dc;&quot;&gt;같이 보면 좋은 자료&lt;/h2&gt;

  &lt;div style=&quot;display:grid;gap:12px;margin:17px 0 24px;&quot;&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;1&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;&lt;a href=&quot;https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#086f5b;text-underline-offset:3px;&quot;&gt;파이썬 공식 문서: 숫자형과 연산&lt;/a&gt;&lt;/strong&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;/&lt;/code&gt;, &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;//&lt;/code&gt;, 나머지 연산의 의미를 확인할 수 있다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;2&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;&lt;a href=&quot;https://docs.python.org/3/library/math.html#math.prod&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#086f5b;text-underline-offset:3px;&quot;&gt;파이썬 공식 문서: math.prod()&lt;/a&gt;&lt;/strong&gt;반복 가능한 객체의 모든 원소를 곱하는 표준 함수다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;3&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;&lt;a href=&quot;https://docs.python.org/3/library/stdtypes.html#str.lower&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#086f5b;text-underline-offset:3px;&quot;&gt;파이썬 공식 문서: str.lower()&lt;/a&gt;&lt;/strong&gt;문자열을 소문자로 통일하는 메서드와 문자열 검색을 복습할 수 있다.&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;div style=&quot;margin-top:48px;padding:23px;background:#f5f8f6;border-top:3px solid #176b57;border-radius:8px;&quot;&gt;
    &lt;strong style=&quot;display:block;margin-bottom:4px;&quot;&gt;마무리&lt;/strong&gt;
    &lt;p style=&quot;margin:8px 0 0;&quot;&gt;이번 문제에서 가장 크게 남은 포인트는 “반복할 때 무엇을 비교하고, 언제 카운트를 올릴 것인가”였다. 수열 변환 문제는 새 배열을 만든 뒤 이전 배열과 다를 때만 횟수를 증가시키면 되고, 1로 만들기는 각 숫자 하나를 끝까지 처리하면 된다. 문제의 수학적 설명을 그대로 코드에 옮기기보다, 현재 값과 다음 값이라는 프로그램의 흐름으로 바꾸어 생각하면 복잡한 반복문도 훨씬 선명해진다.&lt;/p&gt;
  &lt;/div&gt;
&lt;/article&gt;</description>
      <category>AI/Coding_Test</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/126</guid>
      <comments>https://onethingflow.tistory.com/entry/Day-15-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%A1%B0%EA%B1%B4-%EB%B3%80%ED%99%98%EA%B3%BC-%EB%B0%98%EB%B3%B5%EB%AC%B8-5%EB%AC%B8%EC%A0%9C-%ED%92%80#entry126comment</comments>
      <pubDate>Thu, 23 Jul 2026 22:41:24 +0900</pubDate>
    </item>
    <item>
      <title>정처기 5과목 소프트웨어 개발방법론 활용 정리 | p.5-2~p.5-37</title>
      <link>https://onethingflow.tistory.com/entry/%EC%A0%95%EC%B2%98%EA%B8%B0-5%EA%B3%BC%EB%AA%A9-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B0%9C%EB%B0%9C%EB%B0%A9%EB%B2%95%EB%A1%A0-%ED%99%9C%EC%9A%A9-%EC%A0%95%EB%A6%AC-p5-2p5-37</link>
      <description>&lt;!-- 티스토리 제목: 정처기 5과목 소프트웨어 개발방법론 활용 정리 | p.5-2~p.5-37 --&gt;
&lt;!-- 메타 설명: 정보처리기사 실기 5과목 소프트웨어 개발방법론 활용을 초보자용으로 정리합니다. 생명주기 모델, 개발 방법론, CMMI·SPICE, 방법론 선정, 테일러링을 한 번에 복습합니다. --&gt;
&lt;style&gt;&lt;/style&gt;
&lt;article class=&quot;hb-post hb-jeongcheogi-methodology&quot; style=&quot;max-width:780px;margin:0 auto;color:#1f2937;font-size:17px;line-height:1.82;word-break:keep-all;overflow-wrap:break-word;&quot;&gt;
  &lt;p style=&quot;margin:0 0 10px;color:#52606d;font-size:14px;&quot;&gt;정처기 공부 기록 · 7월 23일 · 실기 5과목&lt;/p&gt;
  &lt;h1 style=&quot;margin:0 0 18px;color:#111827;font-size:32px;line-height:1.32;letter-spacing:-0.04em;&quot;&gt;소프트웨어 개발방법론 활용&lt;br&gt;p.5-2~p.5-37&lt;/h1&gt;
  &lt;div style=&quot;margin:0 0 28px;padding:19px 20px;border:1px solid #dbe7ff;border-radius:14px;background:#f5f8ff;&quot;&gt;
    &lt;p style=&quot;margin:0 0 8px;color:#2458bc;font-weight:700;&quot;&gt;오늘의 한 줄 목표&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;방법론 이름을 외우는 데서 멈추지 않고, &lt;strong&gt;어떤 프로젝트에서 왜 그 방법을 고르는지&lt;/strong&gt; 말할 수 있게 정리하기.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:36px 0 14px;color:#111827;font-size:24px;&quot;&gt;1. 오늘 공부한 내용&lt;/h2&gt;
  &lt;p style=&quot;margin:0 0 15px;&quot;&gt;오늘 범위는 5과목 &lt;strong&gt;정보시스템 구축 관리&lt;/strong&gt;의 첫 단원, &lt;strong&gt;소프트웨어 개발방법론 활용&lt;/strong&gt;입니다. 사진의 세부 항목인 ‘소프트웨어 개발방법론 선정(1)·선정(2)·테일러링’을 기준으로, 생명주기 모델부터 프로세스 성숙도와 맞춤 적용까지 흐름으로 묶었습니다.&lt;/p&gt;

  &lt;div style=&quot;margin:16px 0 26px;border:1px solid #d9e2ef;border-radius:14px;overflow:hidden;background:#fff;&quot;&gt;
    &lt;div style=&quot;padding:15px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;display:inline-block;width:28px;height:28px;margin-right:10px;border-radius:8px;background:#315efb;color:#fff;text-align:center;line-height:28px;&quot;&gt;1&lt;/strong&gt;&lt;strong&gt;개발 방법론과 생명주기 모델&lt;/strong&gt;&lt;br&gt;&lt;span style=&quot;display:block;margin-left:40px;color:#52606d;font-size:15px;&quot;&gt;폭포수·프로토타입·나선형·반복/점증·애자일의 차이&lt;/span&gt;&lt;/div&gt;
    &lt;div style=&quot;padding:15px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;display:inline-block;width:28px;height:28px;margin-right:10px;border-radius:8px;background:#315efb;color:#fff;text-align:center;line-height:28px;&quot;&gt;2&lt;/strong&gt;&lt;strong&gt;개발 방법론의 종류와 선정&lt;/strong&gt;&lt;br&gt;&lt;span style=&quot;display:block;margin-left:40px;color:#52606d;font-size:15px;&quot;&gt;구조적·정보공학·객체지향·컴포넌트 기반·애자일&lt;/span&gt;&lt;/div&gt;
    &lt;div style=&quot;padding:15px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;display:inline-block;width:28px;height:28px;margin-right:10px;border-radius:8px;background:#315efb;color:#fff;text-align:center;line-height:28px;&quot;&gt;3&lt;/strong&gt;&lt;strong&gt;프로세스 성숙도 평가&lt;/strong&gt;&lt;br&gt;&lt;span style=&quot;display:block;margin-left:40px;color:#52606d;font-size:15px;&quot;&gt;CMMI 5단계와 SPICE 0~5단계&lt;/span&gt;&lt;/div&gt;
    &lt;div style=&quot;padding:15px 16px;&quot;&gt;&lt;strong style=&quot;display:inline-block;width:28px;height:28px;margin-right:10px;border-radius:8px;background:#315efb;color:#fff;text-align:center;line-height:28px;&quot;&gt;4&lt;/strong&gt;&lt;strong&gt;테일러링&lt;/strong&gt;&lt;br&gt;&lt;span style=&quot;display:block;margin-left:40px;color:#52606d;font-size:15px;&quot;&gt;표준 방법론을 프로젝트 상황에 맞게 조정하는 과정&lt;/span&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;소프트웨어 생명주기(SDLC)란?&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 15px;&quot;&gt;소프트웨어 생명주기는 프로그램이 태어나서 관리될 때까지의 큰 과정입니다. 보통 &lt;strong&gt;계획 → 요구사항 분석 → 설계 → 구현 → 테스트 → 유지보수&lt;/strong&gt; 흐름으로 이해합니다. 생명주기 &lt;strong&gt;모델&lt;/strong&gt;은 이 과정을 어떤 순서와 방식으로 진행할지 정한 개발 전략입니다.&lt;/p&gt;
  &lt;div style=&quot;margin:0 0 20px;padding:17px 18px;border-left:4px solid #315efb;background:#f6f8ff;&quot;&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;헷갈리지 않기:&lt;/strong&gt; SDLC는 ‘개발의 전체 여정’, 방법론은 ‘그 여정을 운영하는 방식’, 테일러링은 ‘우리 프로젝트에 맞게 그 방식을 조정하는 일’입니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;생명주기 모델 비교&lt;/h3&gt;
  &lt;div style=&quot;margin:0 0 22px;border:1px solid #d9e2ef;border-radius:14px;overflow-x:auto;background:#fff;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:680px;border-collapse:collapse;font-size:15px;line-height:1.65;&quot;&gt;
      &lt;thead&gt;&lt;tr style=&quot;background:#f1f5ff;color:#223f7a;&quot;&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;모델&lt;/th&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;초보자 비유&lt;/th&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;핵심 특징&lt;/th&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;잘 맞는 상황&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;폭포수&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;설계도대로 집 짓기&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;이전 단계가 끝나야 다음 단계로 진행. 문서화와 단계 구분이 명확.&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;요구사항이 처음부터 안정적일 때&lt;/td&gt;&lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfe;&quot;&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;프로토타입&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;모델하우스 먼저 보여주기&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;시제품을 먼저 만들고 사용자 피드백으로 요구사항을 구체화.&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;사용자가 원하는 화면·기능이 모호할 때&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;나선형&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;조금씩 돌며 위험 점검하기&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;계획·위험 분석·개발·평가를 반복. &lt;strong&gt;위험 분석&lt;/strong&gt;이 핵심.&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;규모가 크고 실패 비용·위험이 큰 프로젝트&lt;/td&gt;&lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfe;&quot;&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;반복·점증&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;스케치에 계속 덧칠하기&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;짧은 주기로 결과물을 보며 개선하고, 기능을 조금씩 추가.&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;변화를 반영하며 완성도를 높여야 할 때&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;&quot;&gt;&lt;strong&gt;애자일&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;&quot;&gt;레고를 빠르게 조립·수정하기&lt;/td&gt;&lt;td style=&quot;padding:10px;&quot;&gt;짧은 반복 주기(스프린트), 고객 협업, 작동하는 소프트웨어, 변화 대응을 중시.&lt;/td&gt;&lt;td style=&quot;padding:10px;&quot;&gt;요구사항 변경이 잦고 빠른 피드백이 필요할 때&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
  &lt;div style=&quot;margin:0 0 22px;padding:17px 18px;border-radius:12px;background:#fff8e7;border:1px solid #f2d490;&quot;&gt;
    &lt;p style=&quot;margin:0 0 7px;color:#805100;font-weight:700;&quot;&gt;시험 연결 포인트&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;폭포수&lt;/strong&gt;는 순차적, &lt;strong&gt;프로토타입&lt;/strong&gt;은 사용자 요구 파악, &lt;strong&gt;나선형&lt;/strong&gt;은 위험 분석, &lt;strong&gt;애자일&lt;/strong&gt;은 변화 대응·짧은 반복 주기라는 단어로 연결합니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;소프트웨어 개발 방법론의 종류&lt;/h3&gt;
  &lt;div style=&quot;margin:0 0 22px;border:1px solid #d9e2ef;border-radius:14px;overflow:hidden;background:#fff;&quot;&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;구조적 방법론&lt;/strong&gt; — 복잡한 문제를 기능 단위로 나누어 위에서 아래로 해결합니다. 핵심은 &lt;strong&gt;분할과 정복, 하향식, 프로세스 중심&lt;/strong&gt;입니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;border-bottom:1px solid #e7edf5;background:#fbfcfe;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;정보공학 방법론&lt;/strong&gt; — 기업 전체 정보시스템을 대상으로 데이터 흐름과 데이터 구조를 중심으로 계획합니다. &lt;strong&gt;데이터 중심, 기업 중심, 대규모 시스템&lt;/strong&gt;이 단서입니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;border-bottom:1px solid #e7edf5;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;객체지향 방법론&lt;/strong&gt; — 데이터와 기능을 객체로 묶어 모델링합니다. 객체의 &lt;strong&gt;캡슐화·상속·다형성&lt;/strong&gt;으로 재사용성과 유지보수성을 높입니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;border-bottom:1px solid #e7edf5;background:#fbfcfe;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;컴포넌트 기반 방법론(CBD)&lt;/strong&gt; — 이미 검증된 부품(컴포넌트)을 조립해 개발합니다. &lt;strong&gt;재사용, 조립, 개발 기간 단축&lt;/strong&gt;이 핵심입니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;padding:14px 16px;&quot;&gt;&lt;strong style=&quot;color:#2458bc;&quot;&gt;애자일 방법론&lt;/strong&gt; — 계획을 길게 고정하기보다 고객과 협업하며 반복적으로 작동하는 결과물을 제공합니다. 대표 실천 방식에는 Scrum, XP 등이 있습니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;개발 방법론은 어떻게 고를까?&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 15px;&quot;&gt;‘최고의 방법론’ 하나가 항상 있는 것은 아닙니다. 프로젝트의 성격에 맞는 방법론을 선택해야 합니다. 선택 기준은 아래처럼 &lt;strong&gt;업무·기술·프로젝트·조직&lt;/strong&gt; 관점으로 나누면 기억하기 쉽습니다.&lt;/p&gt;
  &lt;div style=&quot;margin:0 0 22px;padding:18px;border:1px solid #d9e2ef;border-radius:14px;background:#fff;&quot;&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;업무 관점&lt;/strong&gt; — 업무 복잡도, 법·제도 준수, 요구사항의 명확성과 변경 가능성을 봅니다. 요구사항이 자주 바뀌면 짧은 반복과 피드백이 가능한 방식이 유리합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;기술 관점&lt;/strong&gt; — 새 기술의 사용 여부, 기술 난이도, 기존 시스템과의 연계, 보안·성능 요구를 확인합니다. 기술 위험이 크면 위험을 먼저 분석하는 접근이 필요합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;프로젝트 관점&lt;/strong&gt; — 규모, 일정, 비용, 품질 목표, 외주 여부, 산출물·문서화 수준을 따집니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;조직 관점&lt;/strong&gt; — 팀의 경험과 역량, 사용 가능한 도구, 표준 프로세스, 고객 참여 가능성을 고려합니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;CMMI와 SPICE: 개발 조직의 ‘일하는 방식’ 평가&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 15px;&quot;&gt;개발 방법론을 고르기 전에 조직이 프로세스를 얼마나 체계적으로 수행하는지도 점검합니다. &lt;strong&gt;CMMI&lt;/strong&gt;와 &lt;strong&gt;SPICE&lt;/strong&gt;는 소프트웨어를 직접 평가하기보다, 소프트웨어를 만드는 &lt;strong&gt;프로세스의 성숙도·수행 능력&lt;/strong&gt;을 평가하고 개선하는 모델입니다.&lt;/p&gt;
  &lt;div style=&quot;margin:0 0 20px;border:1px solid #d9e2ef;border-radius:14px;overflow-x:auto;background:#fff;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:620px;border-collapse:collapse;font-size:15px;line-height:1.65;&quot;&gt;
      &lt;thead&gt;&lt;tr style=&quot;background:#eef7f4;color:#17624f;&quot;&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;CMMI 단계&lt;/th&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;의미&lt;/th&gt;&lt;th style=&quot;padding:11px;text-align:left;border-bottom:1px solid #d9e2ef;&quot;&gt;한 줄 기억법&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;1 초기(Initial)&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;개인 역량에 의존하고 절차가 안정적이지 않음&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;그때그때 한다&lt;/td&gt;&lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfe;&quot;&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;2 관리(Managed)&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;프로젝트 단위로 계획·관리·통제&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;프로젝트를 관리한다&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;3 정의(Defined)&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;조직 표준 프로세스를 정의하고 사용&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;조직의 일하는 법이 있다&lt;/td&gt;&lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfe;&quot;&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;&lt;strong&gt;4 정량적 관리&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;품질·성과를 수치와 통계로 관리&lt;/td&gt;&lt;td style=&quot;padding:10px;border-bottom:1px solid #edf1f6;&quot;&gt;숫자로 관리한다&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:10px;&quot;&gt;&lt;strong&gt;5 최적화&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;padding:10px;&quot;&gt;측정 결과를 바탕으로 지속 개선&lt;/td&gt;&lt;td style=&quot;padding:10px;&quot;&gt;더 나은 방식으로 계속 개선한다&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
  &lt;div style=&quot;margin:0 0 20px;padding:18px;border:1px solid #d9e2ef;border-radius:14px;background:#fff;&quot;&gt;
    &lt;p style=&quot;margin:0 0 9px;&quot;&gt;&lt;strong&gt;SPICE&lt;/strong&gt;는 ISO/IEC 15504 기반의 프로세스 평가·개선 모델입니다. 수준은 &lt;strong&gt;0 불완전 → 1 수행 → 2 관리 → 3 확립 → 4 예측 가능 → 5 최적화&lt;/strong&gt;로 봅니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;구분 포인트:&lt;/strong&gt; CMMI는 조직 성숙도 5단계를, SPICE는 개별 프로세스의 수행 능력 수준 0~5를 떠올리면 문제를 풀기 좋습니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:30px 0 12px;color:#172033;font-size:21px;&quot;&gt;소프트웨어 개발방법론 테일러링&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 15px;&quot;&gt;&lt;strong&gt;테일러링(Tailoring)&lt;/strong&gt;은 조직의 표준 개발 방법론을 프로젝트 상황에 맞게 선택·수정·보완하는 과정입니다. 옷을 체형에 맞게 수선하는 것과 같습니다. 표준을 무시하는 일이 아니라, 표준을 기반으로 필요한 부분만 조정하는 일입니다.&lt;/p&gt;
  &lt;div style=&quot;margin:0 0 22px;padding:18px;border-radius:14px;background:#fffaf0;border:1px solid #f3d99c;&quot;&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;① 표준 프로세스 선정·검증&lt;/strong&gt;&lt;br&gt;조직의 표준 방법론 중 프로젝트에 적용할 기본 프로세스를 정하고, 적용 가능성을 확인합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;② 상위 수준 조정&lt;/strong&gt;&lt;br&gt;비즈니스 요구에 따라 생명주기, 개발 단계, 참여 인력, 산출물의 큰 틀을 조정합니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 11px;&quot;&gt;&lt;strong&gt;③ 세부 수준 조정&lt;/strong&gt;&lt;br&gt;WBS, 일정, 역할, 산출물 양식, 도구, 검토 절차처럼 실제 수행 항목을 프로젝트에 맞춥니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;④ 승인·공유·관리&lt;/strong&gt;&lt;br&gt;누가 어떤 근거로 무엇을 바꿨는지 기록하고 이해관계자와 공유해야, 프로젝트마다 제각각이 되는 것을 막을 수 있습니다.&lt;/p&gt;
  &lt;/div&gt;
  &lt;p style=&quot;margin:0 0 22px;&quot;&gt;&lt;strong&gt;예시:&lt;/strong&gt; 짧은 사내 기능 개선 프로젝트에 대형 공공사업 수준의 모든 산출물·검토 단계를 그대로 적용하면 비용만 커질 수 있습니다. 반대로 보안·규제 요구가 큰 프로젝트에서 검토 단계를 빼면 위험합니다. 테일러링은 이 균형을 맞추는 작업입니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:36px 0 14px;color:#111827;font-size:24px;&quot;&gt;2. 공부하면서 개인적으로 중요하다고 생각하는 용어&lt;/h2&gt;
  &lt;div style=&quot;margin:15px 0 22px;padding:18px;border-radius:14px;background:#f5f8ff;border:1px solid #dbe7ff;&quot;&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;&lt;strong&gt;① 나선형 모델의 위험 분석&lt;/strong&gt;&lt;br&gt;나선형을 다른 반복 모델과 구분하는 가장 강한 키워드다. ‘대형·고위험 프로젝트’가 나오면 함께 떠올린다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;&lt;strong&gt;② CMMI 정량적 관리&lt;/strong&gt;&lt;br&gt;4단계는 단순히 잘 관리하는 수준이 아니라, &lt;strong&gt;측정치와 통계&lt;/strong&gt;로 관리한다는 점이 핵심이다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;&lt;strong&gt;③ SPICE 수행 능력&lt;/strong&gt;&lt;br&gt;결과물 자체가 아니라 프로세스를 어느 수준으로 수행하는지 평가한다는 관점이 중요하다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;④ 테일러링&lt;/strong&gt;&lt;br&gt;방법론을 새로 만드는 것이 아니라, 표준 방법론을 프로젝트 특성에 맞춰 조정하는 것이다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:36px 0 14px;color:#111827;font-size:24px;&quot;&gt;3. 공부하면서 이해하지 못한 용어&lt;/h2&gt;
  &lt;div style=&quot;margin:15px 0 22px;padding:18px;border-radius:14px;background:#fffaf0;border:1px solid #f3d99c;&quot;&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;&lt;strong&gt;① 반복 모델과 애자일의 차이&lt;/strong&gt;&lt;br&gt;반복 모델은 결과물을 반복해서 개선하는 넓은 방식이고, 애자일은 반복·점증을 활용하면서 고객 협업과 변화 대응을 특히 강조하는 개발 철학·실천 방식이다.&lt;/p&gt;
    &lt;p style=&quot;margin:0 0 12px;&quot;&gt;&lt;strong&gt;② CMMI와 SPICE의 차이&lt;/strong&gt;&lt;br&gt;CMMI는 조직의 성숙도를 1~5단계로 보는 관점, SPICE는 프로세스 수행 능력을 0~5수준으로 평가하는 관점으로 구분해 둔다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;strong&gt;③ 방법론 선정과 테일러링의 차이&lt;/strong&gt;&lt;br&gt;선정은 ‘어떤 표준 방법론을 기본으로 쓸지’ 결정하는 일이고, 테일러링은 ‘선정한 방법론을 이번 프로젝트에 어떻게 조정할지’ 정하는 일이다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:36px 0 14px;color:#111827;font-size:24px;&quot;&gt;4. 오늘 공부한것 소회&lt;/h2&gt;
  &lt;div style=&quot;margin:15px 0 26px;padding:19px 20px;border-left:4px solid #315efb;background:#f6f8ff;&quot;&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;처음에는 폭포수·나선형·애자일이 전부 비슷한 개발 방식처럼 보였다. 하지만 &lt;strong&gt;요구사항의 안정성, 사용자 피드백, 위험 분석, 변화 대응&lt;/strong&gt;이라는 기준으로 비교하니 각각을 고르는 이유가 보였다. 특히 테일러링은 어려운 용어였는데, 결국 표준 옷을 프로젝트 체형에 맞게 수선하는 과정이라고 생각하니 이해가 됐다. 다음에는 CMMI와 SPICE 단계 문제를 빈칸 형태로 다시 풀어봐야겠다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:36px 0 12px;color:#111827;font-size:21px;&quot;&gt;범위 확인·추가 복습 자료&lt;/h2&gt;
  &lt;p style=&quot;margin:0 0 8px;font-size:14px;color:#52606d;&quot;&gt;사진의 범위(p.5-2~p.5-37)와 제공 PDF의 생명주기 모델 설명을 바탕으로 작성했습니다. 책의 판본에 따라 세부 페이지·표현은 달라질 수 있습니다.&lt;/p&gt;
  &lt;p style=&quot;margin:0;font-size:14px;line-height:1.75;&quot;&gt;&lt;a href=&quot;https://gfile.gilbut.co.kr/gilbut/bookdata/BN004764/copyright/%EA%B5%90%EC%9E%AC%EC%B1%84%ED%83%9D%EC%9A%A9_2026%EC%8B%9C%EB%82%98%EA%B3%B5_%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC_%EC%8B%A4%EA%B8%B0_%EC%B4%9D%EC%A0%95%EB%A6%AC.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2458bc;text-decoration:underline;&quot;&gt;개발방법론·CMMI·SPICE·테일러링 목차 참고&lt;/a&gt; · &lt;a href=&quot;https://jksqm.org/journal/view.php?doi=10.7469%2FJKSQM.2019.47.1.17&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2458bc;text-decoration:underline;&quot;&gt;CMMI·프로세스 개선 참고&lt;/a&gt;&lt;/p&gt;
&lt;/article&gt;</description>
      <category>AI/정보처리기사_스터디</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/125</guid>
      <comments>https://onethingflow.tistory.com/entry/%EC%A0%95%EC%B2%98%EA%B8%B0-5%EA%B3%BC%EB%AA%A9-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B0%9C%EB%B0%9C%EB%B0%A9%EB%B2%95%EB%A1%A0-%ED%99%9C%EC%9A%A9-%EC%A0%95%EB%A6%AC-p5-2p5-37#entry125comment</comments>
      <pubDate>Thu, 23 Jul 2026 15:45:44 +0900</pubDate>
    </item>
    <item>
      <title>Day 14) 프로그래머스 파이썬 반복문과 리스트 5문제 풀이</title>
      <link>https://onethingflow.tistory.com/entry/Day-14-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EB%B0%98%EB%B3%B5%EB%AC%B8%EA%B3%BC-%EB%A6%AC%EC%8A%A4%ED%8A%B8-5%EB%AC%B8%EC%A0%9C-%ED%92%80%EC%9D%B4</link>
      <description>&lt;!--
Title: Day 14) 프로그래머스 파이썬 반복문과 리스트 5문제 풀이
Meta description: 프로그래머스 코딩 기초 트레이닝 Day 14의 홀수 vs 짝수, 5명씩, 할 일 목록, n보다 커질 때까지 더하기, 수열과 구간 쿼리 1을 직접 작성한 코드와 수정 과정 중심으로 정리했습니다.
Tags: 프로그래머스, 코딩테스트, 파이썬, Day14, 반복문, 리스트, 슬라이싱, enumerate, zip, 누적합, 구간쿼리
--&gt;

&lt;article class=&quot;hb-post hb-day14-loop-list hb-paste-safe&quot; style=&quot;max-width:860px;margin:0 auto;color:#17211d;font-size:17px;line-height:1.8;word-break:keep-all;overflow-wrap:anywhere;&quot;&gt;
  &lt;style&gt;&lt;/style&gt;

  &lt;header style=&quot;margin:0 0 34px;padding:30px 26px;color:#ffffff;background:#145c4b;border-radius:8px;&quot;&gt;
    &lt;p style=&quot;margin:0 0 8px;color:#d7f5e9;font-size:14px;font-weight:800;&quot;&gt;Programmers Coding Test · Day 14 · Python&lt;/p&gt;
    &lt;h1 style=&quot;margin:0;color:#ffffff;font-size:31px;line-height:1.35;letter-spacing:0;&quot;&gt;Day 14&lt;br&gt;파이썬 반복문과 리스트 5문제 풀이&lt;/h1&gt;
    &lt;p style=&quot;margin:14px 0 0;color:#e8fff6;font-size:18px;&quot;&gt;슬라이싱, 두 리스트 동시 순회, 누적 합, 인덱스와 값의 차이를 직접 작성한 코드의 수정 과정과 함께 정리했습니다.&lt;/p&gt;
  &lt;/header&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;오늘 문제들은 모두 리스트를 순서대로 다룬다는 공통점이 있지만, 필요한 도구는 조금씩 달랐다. 결과 리스트를 새로 만드는 문제에서는 슬라이싱과 리스트 컴프리헨션이 잘 맞았고, 조건을 만족하는 순간 계산을 끝내야 하는 문제에서는 일반 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;for&lt;/code&gt;문과 조기 반환이 더 자연스러웠다.&lt;/p&gt;

  &lt;div style=&quot;margin:20px 0;padding:17px 19px;background:#edf8f3;border-left:4px solid #176b57;border-radius:8px;&quot;&gt;
    &lt;strong style=&quot;display:block;margin-bottom:4px;&quot;&gt;이번 기록에서 확인한 기준&lt;/strong&gt;
    코드가 짧은지보다 문제의 결과 형태와 종료 시점에 맞는지가 먼저다. 슬라이싱은 간결하지만 새 리스트를 만들고, &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;range(s, e + 1)&lt;/code&gt;은 범위를 직접 제한하므로 같은 조건을 다시 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;if&lt;/code&gt;로 검사할 필요가 없다.
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:50px 0 16px;padding-bottom:10px;color:#17211d;font-size:27px;line-height:1.4;letter-spacing:0;border-bottom:2px solid #d8e1dc;&quot;&gt;문제 및 공식 링크&lt;/h2&gt;

  &lt;div style=&quot;width:100%;margin:16px 0 24px;overflow-x:auto;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:680px;border-collapse:collapse;font-size:15px;&quot;&gt;
      &lt;caption style=&quot;padding:12px 14px;color:#33433c;background:#f5f8f6;font-weight:800;text-align:left;&quot;&gt;프로그래머스 코딩 기초 트레이닝 Day 14&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;&lt;th scope=&quot;col&quot; style=&quot;padding:12px 14px;text-align:left;background:#f8faf9;border-bottom:1px solid #d8e1dc;&quot;&gt;순서&lt;/th&gt;&lt;th scope=&quot;col&quot; style=&quot;padding:12px 14px;text-align:left;background:#f8faf9;border-bottom:1px solid #d8e1dc;&quot;&gt;문제&lt;/th&gt;&lt;th scope=&quot;col&quot; style=&quot;padding:12px 14px;text-align:left;background:#f8faf9;border-bottom:1px solid #d8e1dc;&quot;&gt;핵심 개념&lt;/th&gt;&lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;1&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181887&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#086f5b;text-underline-offset:3px;&quot;&gt;홀수 vs 짝수&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;인덱스의 홀짝, &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;max()&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;2&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181886&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#086f5b;text-underline-offset:3px;&quot;&gt;5명씩&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;슬라이싱의 간격&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;3&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181885&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#086f5b;text-underline-offset:3px;&quot;&gt;할 일 목록&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;enumerate()&lt;/code&gt;, &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;zip()&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;4&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181884&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#086f5b;text-underline-offset:3px;&quot;&gt;n보다 커질 때까지 더하기&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;누적 합, 조기 반환&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:12px 14px;&quot;&gt;5&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181883&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#086f5b;text-underline-offset:3px;&quot;&gt;수열과 구간 쿼리 1&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;&quot;&gt;인덱스와 값, 구간 반복&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:50px 0 16px;padding-bottom:10px;color:#17211d;font-size:27px;line-height:1.4;letter-spacing:0;border-bottom:2px solid #d8e1dc;&quot;&gt;1. 홀수 vs 짝수&lt;/h2&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;첫 번째 원소를 1번 원소라고 할 때 홀수 번째 원소의 합과 짝수 번째 원소의 합 중 더 큰 값을 반환하는 문제다. 사람의 홀수 번째 위치는 파이썬의 짝수 인덱스 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;0, 2, 4, ...&lt;/code&gt;에 해당한다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;내 풀이&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(num_list):
    answer1 = 0
    answer2 = 0

    for i in range(len(num_list)):
        if i % 2 == 0:
            answer1 += num_list[i]
        else:
            answer2 += num_list[i]

    return answer1 if answer1 &amp;gt; answer2 else answer2&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;이 풀이는 정확한 정답이다. 인덱스가 짝수면 문제에서 말하는 홀수 번째 원소이고, 인덱스가 홀수면 짝수 번째 원소다. 두 합이 같을 때는 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;answer2&lt;/code&gt;를 반환하지만 두 값이 같으므로 결과에는 문제가 없다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;같은 효율로 조금 더 간단하게&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(num_list):
    odd_sum = 0
    even_sum = 0

    for i, num in enumerate(num_list):
        if i % 2 == 0:
            odd_sum += num
        else:
            even_sum += num

    return max(odd_sum, even_sum)&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;&lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;enumerate()&lt;/code&gt;로 인덱스와 값을 함께 받고, 마지막 비교는 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;max()&lt;/code&gt;에 맡겼다. 시간 복잡도는 O(N), 결과 합계 외에 별도 리스트를 만들지 않으므로 추가 공간은 O(1)이다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;슬라이싱을 사용한 짧은 풀이&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(num_list):
    return max(sum(num_list[::2]), sum(num_list[1::2]))&lt;/code&gt;&lt;/pre&gt;

  &lt;div style=&quot;margin:20px 0;padding:17px 19px;background:#edf8f3;border-left:4px solid #176b57;border-radius:8px;&quot;&gt;
    &lt;strong style=&quot;display:block;margin-bottom:4px;&quot;&gt;짧은 코드와 메모리 사용량&lt;/strong&gt;
    두 슬라이싱은 각각 새 리스트를 만들므로 추가 공간은 O(N)이다. 다만 이 문제는 리스트 길이가 최대 50이어서 실제 제출에서 메모리 문제가 될 수준은 아니다. 여기서는 성능 경고보다 슬라이싱이 새 리스트를 만든다는 사실을 이해하는 것이 중요하다.
  &lt;/div&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;&lt;strong&gt;검산:&lt;/strong&gt; &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;[4, 2, 6, 1, 7, 6]&lt;/code&gt;의 홀수 번째 합은 17, 짝수 번째 합은 9이므로 결과는 17이다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:50px 0 16px;padding-bottom:10px;color:#17211d;font-size:27px;line-height:1.4;letter-spacing:0;border-bottom:2px solid #d8e1dc;&quot;&gt;2. 5명씩&lt;/h2&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;이름을 앞에서부터 5명씩 묶고 각 그룹의 첫 번째 사람을 반환하는 문제다. 필요한 인덱스는 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;0, 5, 10, ...&lt;/code&gt;이다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;내 풀이&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(names):
    answer = names[::5]
    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;수정할 오류가 없는 정답이다. 슬라이싱의 형태는 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;[start:stop:step]&lt;/code&gt;이고, 시작과 끝을 생략한 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;[::5]&lt;/code&gt;는 처음부터 끝까지 5칸 간격으로 선택한다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;직접 반환하기&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(names):
    return names[::5]&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;결과를 새 리스트로 반환해야 하는 문제이므로 슬라이싱이 만드는 새 리스트가 문제의 목적과 잘 맞는다. 공식 예제에서는 0번의 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;&quot;nami&quot;&lt;/code&gt;와 5번의 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;&quot;vex&quot;&lt;/code&gt;가 선택된다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:50px 0 16px;padding-bottom:10px;color:#17211d;font-size:27px;line-height:1.4;letter-spacing:0;border-bottom:2px solid #d8e1dc;&quot;&gt;3. 할 일 목록&lt;/h2&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;&lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;todo_list&lt;/code&gt;와 같은 위치의 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;finished&lt;/code&gt; 값을 확인해 아직 끝내지 않은 일만 순서대로 모으는 문제다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;내 풀이&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(todo_list, finished):
    answer = []

    for i in range(len(todo_list)):
        if finished[i] == False:
            answer.append(todo_list[i])

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;이 코드도 정확한 정답이다. 인덱스 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;i&lt;/code&gt;를 이용해 두 리스트의 같은 위치를 연결했다. 다만 불리언 값이 거짓인지 확인할 때는 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;== False&lt;/code&gt;보다 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;not&lt;/code&gt;을 쓰면 의도가 더 자연스럽게 읽힌다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;enumerate()로 정리한 풀이&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(todo_list, finished):
    answer = []

    for i, task in enumerate(todo_list):
        if not finished[i]:
            answer.append(task)

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;zip()과 리스트 컴프리헨션&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(todo_list, finished):
    return [task for task, is_finished in zip(todo_list, finished)
            if not is_finished]&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;&lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;zip()&lt;/code&gt;은 두 리스트의 같은 위치에 있는 값을 한 쌍씩 묶는다. 인덱스가 필요 없는 이 문제에서는 할 일과 완료 여부를 직접 받는 풀이가 가장 간결하다. 다만 두 입력의 길이가 다르면 짧은 쪽에서 멈춘다는 특성이 있으며, 이 문제에서는 두 배열의 위치가 대응하므로 그대로 사용할 수 있다.&lt;/p&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;&lt;strong&gt;검산:&lt;/strong&gt; &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;[True, False, True, False]&lt;/code&gt;에서는 두 번째와 네 번째 할 일만 결과에 들어간다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:50px 0 16px;padding-bottom:10px;color:#17211d;font-size:27px;line-height:1.4;letter-spacing:0;border-bottom:2px solid #d8e1dc;&quot;&gt;4. n보다 커질 때까지 더하기&lt;/h2&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;배열의 원소를 앞에서부터 누적해 더하다가 합이 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;n&lt;/code&gt;보다 커지는 순간의 합을 반환하는 문제다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;처음 작성한 코드&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(numbers, n):
    return [sum(numbers[i]) for i, num in enumerate(numbers)
            if sum(numbers[i]) &amp;gt; n]&lt;/code&gt;&lt;/pre&gt;

  &lt;div style=&quot;display:grid;gap:12px;margin:17px 0 24px;&quot;&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;1&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;정수 하나에는 sum()을 사용할 수 없다&lt;/strong&gt;&lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;numbers[i]&lt;/code&gt;는 리스트가 아니라 정수 하나다. 따라서 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;sum(numbers[i])&lt;/code&gt;는 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;TypeError&lt;/code&gt;를 발생시킨다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;2&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;문제가 요구하는 결과는 리스트가 아니다&lt;/strong&gt;조건을 만족하는 여러 합을 모으는 것이 아니라 처음으로 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;n&lt;/code&gt;을 넘은 합계 하나를 반환해야 한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;3&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;반복 슬라이싱은 같은 값을 다시 더한다&lt;/strong&gt;&lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;sum(numbers[:i + 1])&lt;/code&gt;로 문법만 고치면 매 단계마다 앞부분을 새로 만들고 다시 합산해 최악의 경우 O(N²)이 된다.&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;누적 합을 사용한 기본 풀이&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(numbers, n):
    total = 0

    for num in numbers:
        total += num

        if total &amp;gt; n:
            return total&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;이전 합을 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;total&lt;/code&gt;에 보관하므로 각 원소를 한 번만 더한다. 조건을 만족하는 순간 바로 반환해 뒤쪽 원소도 확인하지 않는다. 시간 복잡도는 실제로 확인한 원소 수를 K라고 할 때 O(K), 추가 공간은 O(1)이다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;itertools.accumulate()를 사용한 풀이&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;from itertools import accumulate


def solution(numbers, n):
    return next(total for total in accumulate(numbers) if total &amp;gt; n)&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;&lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;accumulate()&lt;/code&gt;는 누적 합을 하나씩 생성하고, &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;next()&lt;/code&gt;는 조건을 만족하는 첫 값을 꺼낸다. 문제 조건상 전체 합은 반드시 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;n&lt;/code&gt;보다 크므로 기본값은 필요 없다. 처음 배우는 단계에서는 일반 반복문 풀이가 흐름을 더 잘 보여준다.&lt;/p&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;&lt;strong&gt;검산:&lt;/strong&gt; &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;[34, 5, 71, 29, 100, 34]&lt;/code&gt;를 차례로 더하면 34, 39, 110, 139가 되고 123을 처음 넘은 139를 반환한다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:50px 0 16px;padding-bottom:10px;color:#17211d;font-size:27px;line-height:1.4;letter-spacing:0;border-bottom:2px solid #d8e1dc;&quot;&gt;5. 수열과 구간 쿼리 1&lt;/h2&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;각 쿼리 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;[s, e]&lt;/code&gt;마다 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;s ≤ i ≤ e&lt;/code&gt;를 만족하는 모든 인덱스의 값에 1을 더하는 문제다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;처음 작성한 코드&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(arr, queries):
    for i in arr:
        for s, e in queries:
            if i &amp;gt;= s and e &amp;gt;= i:
                arr[i] += 1

    return arr&lt;/code&gt;&lt;/pre&gt;

  &lt;div style=&quot;margin:20px 0;padding:17px 19px;background:#fff5ed;border-left:4px solid #a84412;border-radius:8px;&quot;&gt;
    &lt;strong style=&quot;display:block;margin-bottom:4px;&quot;&gt;핵심 오류: i에는 인덱스가 아니라 값이 들어간다&lt;/strong&gt;
    &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;for i in arr&lt;/code&gt;에서 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;i&lt;/code&gt;는 0, 1, 2 같은 위치가 아니라 배열에 저장된 실제 값이다. 그 값을 다시 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;arr[i]&lt;/code&gt;의 인덱스로 쓰면 범위를 벗어나거나 엉뚱한 원소를 수정할 수 있다.
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;처음 생각한 흐름을 유지한 수정 풀이&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(arr, queries):
    for i in range(len(arr)):
        for s, e in queries:
            if s &amp;lt;= i &amp;lt;= e:
                arr[i] += 1

    return arr&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;인덱스 전체를 순회하면서 각 쿼리 범위에 포함되는지 확인하는 방식이다. 원래 의도를 그대로 살린 정답이지만 배열의 모든 인덱스와 모든 쿼리를 비교하므로 시간 복잡도는 O(NQ)다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:29px 0 10px;color:#125443;font-size:20px;line-height:1.5;&quot;&gt;필요한 구간만 방문하는 풀이&lt;/h3&gt;

  &lt;pre style=&quot;margin:14px 0 20px;padding:18px;overflow-x:auto;color:#e8f0ec;background:#18201e;border:1px solid #31413b;border-radius:8px;line-height:1.65;tab-size:4;&quot;&gt;&lt;code class=&quot;language-python&quot; style=&quot;padding:0;color:inherit;background:transparent;font-size:14px;white-space:pre;overflow-wrap:normal;&quot;&gt;def solution(arr, queries):
    for s, e in queries:
        for i in range(s, e + 1):
            arr[i] += 1

    return arr&lt;/code&gt;&lt;/pre&gt;

  &lt;div style=&quot;display:grid;gap:12px;margin:17px 0 24px;&quot;&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;1&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;쿼리를 먼저 꺼낸다&lt;/strong&gt;현재 처리할 시작점 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;s&lt;/code&gt;와 끝점 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;e&lt;/code&gt;를 먼저 정한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;2&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;끝점 e를 포함한다&lt;/strong&gt;&lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;range()&lt;/code&gt;는 끝값을 포함하지 않으므로 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;e + 1&lt;/code&gt;까지 지정한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;3&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;if 조건은 이미 범위에 들어 있다&lt;/strong&gt;&lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;range(s, e + 1)&lt;/code&gt;에서 나오는 모든 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;i&lt;/code&gt;는 처음부터 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;s ≤ i ≤ e&lt;/code&gt;를 만족하므로 같은 조건을 다시 검사할 필요가 없다.&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;이 방식의 반복 횟수는 각 쿼리 길이의 합인 O(Σ(e - s + 1))이다. 모든 범위가 배열 전체라면 O(NQ)와 같지만, 짧은 구간이 많을수록 불필요한 비교를 줄인다.&lt;/p&gt;

  &lt;p style=&quot;margin:10px 0;&quot;&gt;&lt;strong&gt;검산:&lt;/strong&gt; &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;[0, 1, 2, 3, 4]&lt;/code&gt;에 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;[[0, 1], [1, 2], [2, 3]]&lt;/code&gt;을 차례로 적용하면 최종 결과는 &lt;code style=&quot;padding:2px 6px;color:#9f1239;background:#fff1f2;border-radius:4px;font-size:.92em;overflow-wrap:anywhere;&quot;&gt;[1, 3, 4, 4, 4]&lt;/code&gt;다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:50px 0 16px;padding-bottom:10px;color:#17211d;font-size:27px;line-height:1.4;letter-spacing:0;border-bottom:2px solid #d8e1dc;&quot;&gt;풀이별 복잡도 정리&lt;/h2&gt;

  &lt;div style=&quot;width:100%;margin:16px 0 24px;overflow-x:auto;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:720px;border-collapse:collapse;font-size:15px;&quot;&gt;
      &lt;caption style=&quot;padding:12px 14px;color:#33433c;background:#f5f8f6;font-weight:800;text-align:left;&quot;&gt;추천 풀이 기준 시간 및 추가 공간&lt;/caption&gt;
      &lt;thead&gt;&lt;tr&gt;&lt;th scope=&quot;col&quot; style=&quot;padding:12px 14px;text-align:left;background:#f8faf9;border-bottom:1px solid #d8e1dc;&quot;&gt;문제&lt;/th&gt;&lt;th scope=&quot;col&quot; style=&quot;padding:12px 14px;text-align:left;background:#f8faf9;border-bottom:1px solid #d8e1dc;&quot;&gt;시간&lt;/th&gt;&lt;th scope=&quot;col&quot; style=&quot;padding:12px 14px;text-align:left;background:#f8faf9;border-bottom:1px solid #d8e1dc;&quot;&gt;추가 공간&lt;/th&gt;&lt;th scope=&quot;col&quot; style=&quot;padding:12px 14px;text-align:left;background:#f8faf9;border-bottom:1px solid #d8e1dc;&quot;&gt;핵심&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;홀수 vs 짝수&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;O(N)&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;O(1)&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;두 합만 누적&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;5명씩&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;O(N)&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;O(N)&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;약 N/5개의 결과 생성&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;할 일 목록&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;O(N)&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;O(K)&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;미완료 K개 저장&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;n보다 커질 때까지 더하기&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;O(K)&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;O(1)&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;border-bottom:1px solid #d8e1dc;&quot;&gt;조건 충족 즉시 반환&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td style=&quot;padding:12px 14px;&quot;&gt;수열과 구간 쿼리 1&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;&quot;&gt;O(구간 길이의 합)&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;&quot;&gt;O(1)&lt;/td&gt;&lt;td style=&quot;padding:12px 14px;&quot;&gt;필요한 인덱스만 수정&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:50px 0 16px;padding-bottom:10px;color:#17211d;font-size:27px;line-height:1.4;letter-spacing:0;border-bottom:2px solid #d8e1dc;&quot;&gt;실수 방지 체크리스트&lt;/h2&gt;

  &lt;div style=&quot;display:grid;gap:10px;margin:15px 0;&quot;&gt;
    &lt;div style=&quot;display:grid;grid-template-columns:25px minmax(0,1fr);gap:8px;align-items:start;&quot;&gt;&lt;span style=&quot;color:#176b57;font-weight:900;text-align:center;&quot;&gt;✓&lt;/span&gt;&lt;div&gt;문제의 홀수 번째와 파이썬의 홀수 인덱스를 같은 것으로 착각하지 않는다.&lt;/div&gt;&lt;/div&gt;
    &lt;div style=&quot;display:grid;grid-template-columns:25px minmax(0,1fr);gap:8px;align-items:start;&quot;&gt;&lt;span style=&quot;color:#176b57;font-weight:900;text-align:center;&quot;&gt;✓&lt;/span&gt;&lt;div&gt;슬라이싱이 새 리스트를 만든다는 점을 기억한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div style=&quot;display:grid;grid-template-columns:25px minmax(0,1fr);gap:8px;align-items:start;&quot;&gt;&lt;span style=&quot;color:#176b57;font-weight:900;text-align:center;&quot;&gt;✓&lt;/span&gt;&lt;div&gt;두 리스트의 같은 위치를 다룰 때 인덱스가 필요한지, &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;zip()&lt;/code&gt;으로 값을 직접 받을 수 있는지 확인한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div style=&quot;display:grid;grid-template-columns:25px minmax(0,1fr);gap:8px;align-items:start;&quot;&gt;&lt;span style=&quot;color:#176b57;font-weight:900;text-align:center;&quot;&gt;✓&lt;/span&gt;&lt;div&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;sum()&lt;/code&gt;에는 정수 하나가 아니라 반복 가능한 값의 묶음을 전달한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div style=&quot;display:grid;grid-template-columns:25px minmax(0,1fr);gap:8px;align-items:start;&quot;&gt;&lt;span style=&quot;color:#176b57;font-weight:900;text-align:center;&quot;&gt;✓&lt;/span&gt;&lt;div&gt;반복 중 계산한 합을 변수에 누적해 같은 구간을 계속 다시 더하지 않는다.&lt;/div&gt;&lt;/div&gt;
    &lt;div style=&quot;display:grid;grid-template-columns:25px minmax(0,1fr);gap:8px;align-items:start;&quot;&gt;&lt;span style=&quot;color:#176b57;font-weight:900;text-align:center;&quot;&gt;✓&lt;/span&gt;&lt;div&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;for i in arr&lt;/code&gt;의 &lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;i&lt;/code&gt;는 인덱스가 아니라 값이라는 점을 확인한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div style=&quot;display:grid;grid-template-columns:25px minmax(0,1fr);gap:8px;align-items:start;&quot;&gt;&lt;span style=&quot;color:#176b57;font-weight:900;text-align:center;&quot;&gt;✓&lt;/span&gt;&lt;div&gt;&lt;code style=&quot;overflow-wrap:anywhere;&quot;&gt;range()&lt;/code&gt;에서 끝점을 포함해야 한다면 1을 더한다.&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:50px 0 16px;padding-bottom:10px;color:#17211d;font-size:27px;line-height:1.4;letter-spacing:0;border-bottom:2px solid #d8e1dc;&quot;&gt;같이 보면 좋은 자료&lt;/h2&gt;

  &lt;div style=&quot;display:grid;gap:12px;margin:17px 0 24px;&quot;&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;1&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;&lt;a href=&quot;https://docs.python.org/3/library/stdtypes.html#common-sequence-operations&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#086f5b;text-underline-offset:3px;&quot;&gt;파이썬 공식 문서: 시퀀스 연산&lt;/a&gt;&lt;/strong&gt;슬라이싱의 시작, 끝, 간격과 리스트 연결 동작을 확인할 수 있다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;2&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;&lt;a href=&quot;https://docs.python.org/3/library/functions.html#enumerate&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#086f5b;text-underline-offset:3px;&quot;&gt;파이썬 공식 문서: enumerate()&lt;/a&gt;&lt;/strong&gt;반복 가능한 객체에서 인덱스와 값을 함께 얻는 방법이다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;3&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;&lt;a href=&quot;https://docs.python.org/3/library/functions.html#zip&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#086f5b;text-underline-offset:3px;&quot;&gt;파이썬 공식 문서: zip()&lt;/a&gt;&lt;/strong&gt;여러 반복 가능한 객체의 같은 위치 값을 묶어 순회하는 방법이다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot; style=&quot;display:grid;grid-template-columns:34px minmax(0,1fr);gap:12px;align-items:start;padding:15px 16px;background:#ffffff;border:1px solid #d8e1dc;border-radius:8px;&quot;&gt;&lt;span class=&quot;hb-number-badge&quot; style=&quot;display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;color:#ffffff;background:#176b57;border-radius:6px;font-size:14px;font-weight:900;line-height:1;&quot;&gt;4&lt;/span&gt;&lt;div&gt;&lt;strong style=&quot;display:block;margin-bottom:3px;&quot;&gt;&lt;a href=&quot;https://docs.python.org/3/library/itertools.html#itertools.accumulate&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#086f5b;text-underline-offset:3px;&quot;&gt;파이썬 공식 문서: itertools.accumulate()&lt;/a&gt;&lt;/strong&gt;누적 합과 같은 중간 결과를 순서대로 생성하는 표준 라이브러리 함수다.&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;div style=&quot;margin-top:48px;padding:23px;background:#f5f8f6;border-top:3px solid #176b57;border-radius:8px;&quot;&gt;
    &lt;strong style=&quot;display:block;margin-bottom:4px;&quot;&gt;마무리&lt;/strong&gt;
    &lt;p style=&quot;margin:8px 0 0;&quot;&gt;이번 다섯 문제를 풀면서 슬라이싱과 리스트 컴프리헨션이 항상 더 좋은 답은 아니라는 점을 확인했다. 새 리스트가 필요한 문제에서는 간결한 문법이 잘 맞지만, 합이 기준을 넘는 순간 멈춰야 할 때는 누적 변수와 조기 반환이 더 정확하다. 마지막 구간 쿼리 문제에서 값과 인덱스를 구분하고 반복 범위 자체로 조건을 표현한 과정은 이후 배열 문제에서도 계속 사용할 수 있는 기본기가 된다.&lt;/p&gt;
  &lt;/div&gt;
&lt;/article&gt;</description>
      <category>AI/Coding_Test</category>
      <category>day14</category>
      <category>enumerate</category>
      <category>zip</category>
      <category>누적합</category>
      <category>리스트</category>
      <category>반복문</category>
      <category>슬라이싱</category>
      <category>코딩테스트</category>
      <category>파이썬</category>
      <category>프로그래머스</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/124</guid>
      <comments>https://onethingflow.tistory.com/entry/Day-14-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EB%B0%98%EB%B3%B5%EB%AC%B8%EA%B3%BC-%EB%A6%AC%EC%8A%A4%ED%8A%B8-5%EB%AC%B8%EC%A0%9C-%ED%92%80%EC%9D%B4#entry124comment</comments>
      <pubDate>Wed, 22 Jul 2026 22:27:55 +0900</pubDate>
    </item>
    <item>
      <title>Day8~9)정처기 공부 기록 | 4과목 네트워크 기초 활용 (p.4-148~p.4-197)</title>
      <link>https://onethingflow.tistory.com/entry/Day89%EC%A0%95%EC%B2%98%EA%B8%B0-%EA%B3%B5%EB%B6%80-%EA%B8%B0%EB%A1%9D-4%EA%B3%BC%EB%AA%A9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B8%B0%EC%B4%88-%ED%99%9C%EC%9A%A9-p4-148p4-197</link>
      <description>&lt;!-- 티스토리 제목: 정처기 4과목 네트워크 기초 활용 정리 | p.4-148~p.4-197 --&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;!-- 티스토리 HTML 모드에서 이 파일 전체를 붙여넣으세요. CSS 블록 없이 작성한 붙여넣기 안전본입니다. --&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;article class=&quot;hb-post hb-jeongcheogi-network&quot; style=&quot;max-width: 780px; margin: 0 auto; color: #1f2937; font-size: 17px; line-height: 1.82; word-break: keep-all; overflow-wrap: break-word;&quot;&gt;
&lt;p style=&quot;margin: 0 0 10px; color: #52606d; font-size: 14px;&quot; data-ke-size=&quot;size16&quot;&gt;정처기 공부 기록 &amp;middot; 7월 23일 &amp;middot; 실기 4과목&lt;/p&gt;
&lt;h1 style=&quot;margin: 0 0 18px; color: #111827; font-size: 32px; line-height: 1.32; letter-spacing: -0.04em;&quot;&gt;네트워크 기초 활용 공부 기록&lt;br /&gt;p.4-148~p.4-197&lt;/h1&gt;
&lt;div style=&quot;margin: 0 0 26px; padding: 19px 20px; border: 1px solid #dbe7ff; border-radius: 14px; background: #f5f8ff;&quot;&gt;
&lt;p style=&quot;margin: 0 0 8px; color: #2458bc; font-weight: bold;&quot; data-ke-size=&quot;size16&quot;&gt;오늘의 한 줄 목표&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;프로토콜을 따로 외우지 말고, &lt;b&gt;어느 계층에서 &amp;middot; 어떤 주소를 쓰며 &amp;middot; 무엇을 해결하는지&lt;/b&gt; 연결해서 기억하기.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin: 34px 0 14px; color: #111827; font-size: 24px;&quot; data-ke-size=&quot;size26&quot;&gt;1. 오늘 공부한 거 인증&lt;/h2&gt;
&lt;div style=&quot;padding: 18px; border: 1px dashed #94a3b8; border-radius: 12px; background: #fafcff; text-align: center; color: #64748b;&quot;&gt;

&lt;/div&gt;
&lt;div style=&quot;margin-top: 12px; padding: 15px 17px; border-left: 4px solid #4f7cff; background: #f7f9ff;&quot;&gt;
&lt;p style=&quot;margin: 0 0 5px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실기 책:&lt;/b&gt; 수제비 4과목 「응용 SW 기초 기술 활용」&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 5px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;파이널 책:&lt;/b&gt; 오늘 범위 기출&amp;middot;오답 표시&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;인강:&lt;/b&gt; OSI 계층, TCP/IP, IP 주소&amp;middot;전송 방식 복습&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin: 36px 0 14px; color: #111827; font-size: 24px;&quot; data-ke-size=&quot;size26&quot;&gt;2. 이번 범위, 무엇을 빠짐없이 봐야 할까?&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 15px;&quot; data-ke-size=&quot;size16&quot;&gt;사진의 범위는 &lt;b&gt;4과목 03. 응용 SW 기초 기술 활용 &amp;rarr; 2. 네트워크 기초 활용&lt;/b&gt;입니다. 현재 수제비 실기 기본서 목차에서도 이 단원은 아래 다섯 묶음으로 나뉩니다. 이전 글은 TCP/IP 일부만 다뤄서 전달 방식&amp;middot;구조&amp;middot;용어가 빠졌습니다. 이번 글은 다섯 묶음을 모두 넣어 복습용으로 다시 정리했습니다.&lt;/p&gt;
&lt;div style=&quot;margin: 16px 0 26px; border: 1px solid #d9e2ef; border-radius: 14px; overflow: hidden; background: #ffffff;&quot;&gt;
&lt;div style=&quot;padding: 15px 16px; border-bottom: 1px solid #e7edf5;&quot;&gt;&lt;b&gt;1&lt;/b&gt;&lt;b&gt;네트워크 계층 구조&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;display: block; margin-left: 40px; color: #52606d; font-size: 15px;&quot;&gt;OSI 7계층, TCP/IP 4계층, 데이터 단위와 장비&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 15px 16px; border-bottom: 1px solid #e7edf5;&quot;&gt;&lt;b&gt;2&lt;/b&gt;&lt;b&gt;네트워크 프로토콜&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;display: block; margin-left: 40px; color: #52606d; font-size: 15px;&quot;&gt;IP, ARP, ICMP, IGMP, TCP, UDP, 라우팅&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 15px 16px; border-bottom: 1px solid #e7edf5;&quot;&gt;&lt;b&gt;3&lt;/b&gt;&lt;b&gt;네트워크 전달 방식&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;display: block; margin-left: 40px; color: #52606d; font-size: 15px;&quot;&gt;단방향&amp;middot;반이중&amp;middot;전이중, 유니&amp;middot;브로드&amp;middot;멀티&amp;middot;애니캐스트, 교환 방식&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 15px 16px; border-bottom: 1px solid #e7edf5;&quot;&gt;&lt;b&gt;4&lt;/b&gt;&lt;b&gt;네트워크 구조&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;display: block; margin-left: 40px; color: #52606d; font-size: 15px;&quot;&gt;LAN&amp;middot;MAN&amp;middot;WAN, 유&amp;middot;무선 LAN, 토폴로지&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;padding: 15px 16px;&quot;&gt;&lt;b&gt;5&lt;/b&gt;&lt;b&gt;네트워크 용어&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;display: block; margin-left: 40px; color: #52606d; font-size: 15px;&quot;&gt;MAC&amp;middot;IP&amp;middot;포트&amp;middot;소켓&amp;middot;서브넷&amp;middot;게이트웨이&amp;middot;DNS&amp;middot;DHCP&amp;middot;NAT&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin: 36px 0 14px; color: #111827; font-size: 24px;&quot; data-ke-size=&quot;size26&quot;&gt;3. 네트워크 계층 구조: &amp;lsquo;택배 과정&amp;rsquo;으로 이해하기&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 15px;&quot; data-ke-size=&quot;size16&quot;&gt;데이터가 앱에서 출발해 상대방 앱에 도착하기까지의 일을 층으로 나눈 약속이 &lt;b&gt;OSI 7계층&lt;/b&gt;입니다. 문제에 프로토콜&amp;middot;장비&amp;middot;전송 단위가 나오면, 먼저 어느 계층인지 찾는 것이 가장 빠릅니다.&lt;/p&gt;
&lt;div style=&quot;margin: 16px 0 20px; border: 1px solid #d9e2ef; border-radius: 14px; overflow-x: auto; background: #fff;&quot;&gt;
&lt;table style=&quot;width: 100%; min-width: 650px; border-collapse: collapse; font-size: 15px; line-height: 1.65;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background: #f1f5ff; color: #223f7a;&quot;&gt;
&lt;th style=&quot;padding: 11px 10px; border-bottom: 1px solid #d9e2ef; text-align: left;&quot;&gt;OSI&lt;/th&gt;
&lt;th style=&quot;padding: 11px 10px; border-bottom: 1px solid #d9e2ef; text-align: left;&quot;&gt;핵심 역할&lt;/th&gt;
&lt;th style=&quot;padding: 11px 10px; border-bottom: 1px solid #d9e2ef; text-align: left;&quot;&gt;예시&amp;middot;단서&lt;/th&gt;
&lt;th style=&quot;padding: 11px 10px; border-bottom: 1px solid #d9e2ef; text-align: left;&quot;&gt;PDU&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;7 응용&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;사용자 서비스&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;HTTP, FTP, SMTP, DNS&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;데이터&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background: #fbfcfe;&quot;&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;6 표현&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;형식 변환&amp;middot;압축&amp;middot;암호화&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;인코딩, 암호화&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;데이터&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;5 세션&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;연결 설정&amp;middot;유지&amp;middot;종료&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;대화 제어, 동기점&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;데이터&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background: #fbfcfe;&quot;&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;4 전송&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;종단 간 전송, 신뢰성, 흐름 제어&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;TCP, UDP, &lt;b&gt;포트&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;세그먼트&amp;middot;데이터그램&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;3 네트워크&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;논리 주소&amp;middot;경로 선택&amp;middot;라우팅&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;IP, ICMP, 라우터, &lt;b&gt;IP 주소&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;패킷&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background: #fbfcfe;&quot;&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;2 데이터 링크&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;같은 네트워크 안 전달, 오류 검출&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;Ethernet, MAC, 스위치&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;프레임&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px;&quot;&gt;&lt;b&gt;1 물리&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px;&quot;&gt;전기&amp;middot;빛&amp;middot;무선 신호로 실제 전송&lt;/td&gt;
&lt;td style=&quot;padding: 10px;&quot;&gt;케이블, 허브, 리피터&lt;/td&gt;
&lt;td style=&quot;padding: 10px;&quot;&gt;비트&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div style=&quot;margin: 16px 0 22px; padding: 17px 18px; border-radius: 12px; background: #fff8e7; border: 1px solid #f2d490;&quot;&gt;
&lt;p style=&quot;margin: 0 0 8px; color: #805100; font-weight: bold;&quot; data-ke-size=&quot;size16&quot;&gt;암기 연결: 주소는 세 종류&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;MAC 주소&lt;/b&gt;는 같은 LAN 안에서 다음 장비를 찾는 물리 주소, &lt;b&gt;IP 주소&lt;/b&gt;는 여러 네트워크를 건너 최종 목적지를 찾는 논리 주소, &lt;b&gt;포트 번호&lt;/b&gt;는 그 컴퓨터 안에서 어느 프로그램으로 보낼지를 구분하는 번호입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;p style=&quot;margin: 0 0 16px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;TCP/IP 4계층으로 묶으면&lt;/b&gt; OSI의 7&amp;middot;6&amp;middot;5계층은 응용 계층, 4계층은 전송 계층, 3계층은 인터넷 계층, 2&amp;middot;1계층은 네트워크 액세스 계층에 대응합니다.&lt;/p&gt;
&lt;h2 style=&quot;margin: 36px 0 14px; color: #111827; font-size: 24px;&quot; data-ke-size=&quot;size26&quot;&gt;4. 네트워크 프로토콜: &amp;lsquo;통신 규칙&amp;rsquo;의 역할 구분&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 15px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;프로토콜&lt;/b&gt;은 장비끼리 통신하기 위한 규칙입니다. 규칙은 &lt;b&gt;구문(Syntax: 데이터 형식)&lt;/b&gt;, &lt;b&gt;의미(Semantics: 필드의 뜻과 제어)&lt;/b&gt;, &lt;b&gt;타이밍(Timing: 언제&amp;middot;얼마나 빠르게 보낼지)&lt;/b&gt;의 세 요소로 설명합니다.&lt;/p&gt;
&lt;div style=&quot;margin: 15px 0 22px; padding: 18px; border: 1px solid #d9e2ef; border-radius: 14px; background: #ffffff;&quot;&gt;
&lt;p style=&quot;margin: 0 0 11px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;IP&lt;/b&gt; &amp;mdash; 목적지 IP 주소를 기준으로 패킷을 전달하는 인터넷 계층 프로토콜. &lt;b&gt;비연결형&lt;/b&gt;이며 도착 보장&amp;middot;순서 보장은 TCP 같은 상위 계층이 맡습니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 11px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ARP&lt;/b&gt; &amp;mdash; 같은 네트워크 안에서 &lt;b&gt;IP 주소를 MAC 주소로 알아내는&lt;/b&gt; 프로토콜. &amp;ldquo;IP는 아는데 실제 LAN에서 누구에게 프레임을 보낼까?&amp;rdquo;를 해결합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 11px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;RARP&lt;/b&gt; &amp;mdash; MAC 주소로 IP 주소를 얻던 과거 방식. 현재는 일반적으로 DHCP가 이 역할을 대신한다고 함께 기억합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 11px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ICMP&lt;/b&gt; &amp;mdash; IP 통신 중 오류&amp;middot;상태를 알리는 제어 메시지. &lt;b&gt;ping&lt;/b&gt;은 대표적으로 ICMP Echo를 이용해 연결 상태를 확인합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 11px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;IGMP&lt;/b&gt; &amp;mdash; 호스트와 인접 라우터 사이에서 &lt;b&gt;멀티캐스트 그룹&lt;/b&gt; 가입 정보를 관리합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;라우팅 프로토콜&lt;/b&gt; &amp;mdash; 라우터가 최적 경로 정보를 주고받는 규칙. &lt;b&gt;RIP&lt;/b&gt;은 홉 수 중심의 거리 벡터, &lt;b&gt;OSPF&lt;/b&gt;는 링크 상태 기반, &lt;b&gt;BGP&lt;/b&gt;는 자율 시스템(AS) 사이 경로 제어에 쓰입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 style=&quot;margin: 27px 0 12px; color: #172033; font-size: 20px;&quot; data-ke-size=&quot;size23&quot;&gt;IPv4와 IPv6&lt;/h3&gt;
&lt;div style=&quot;margin: 0 0 20px; border: 1px solid #d9e2ef; border-radius: 14px; overflow-x: auto; background: #fff;&quot;&gt;
&lt;table style=&quot;width: 100%; min-width: 620px; border-collapse: collapse; font-size: 15px; line-height: 1.65;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background: #eef7f4; color: #17624f;&quot;&gt;
&lt;th style=&quot;padding: 11px; text-align: left; border-bottom: 1px solid #d9e2ef;&quot;&gt;구분&lt;/th&gt;
&lt;th style=&quot;padding: 11px; text-align: left; border-bottom: 1px solid #d9e2ef;&quot;&gt;IPv4&lt;/th&gt;
&lt;th style=&quot;padding: 11px; text-align: left; border-bottom: 1px solid #d9e2ef;&quot;&gt;IPv6&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;주소 길이&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;32비트&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;128비트&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background: #fbfcfe;&quot;&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;표기&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;10진수 4묶음, 점(.) 구분&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;16진수 8묶음, 콜론(:) 구분&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;전송&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;유니캐스트&amp;middot;멀티캐스트&amp;middot;브로드캐스트&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;유니캐스트&amp;middot;멀티캐스트&amp;middot;애니캐스트&lt;br /&gt;브로드캐스트는 없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background: #fbfcfe;&quot;&gt;
&lt;td style=&quot;padding: 10px;&quot;&gt;&lt;b&gt;핵심 특징&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px;&quot;&gt;주소 고갈 문제가 배경&lt;/td&gt;
&lt;td style=&quot;padding: 10px;&quot;&gt;넓은 주소 공간, 간소화된 헤더, IPsec 지원, 자동 구성 기능&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p style=&quot;margin: 0 0 18px;&quot; data-ke-size=&quot;size16&quot;&gt;전환 기술은 &lt;b&gt;듀얼 스택&lt;/b&gt;(두 버전을 함께 사용), &lt;b&gt;터널링&lt;/b&gt;(IPv6 패킷을 IPv4망을 지나가게 캡슐화), &lt;b&gt;주소 변환&lt;/b&gt;(두 주소 체계 사이를 변환)으로 구분합니다.&lt;/p&gt;
&lt;h3 style=&quot;margin: 27px 0 12px; color: #172033; font-size: 20px;&quot; data-ke-size=&quot;size23&quot;&gt;TCP와 UDP: 시험에 가장 잘 나오는 비교&lt;/h3&gt;
&lt;div style=&quot;margin: 0 0 20px; border: 1px solid #d9e2ef; border-radius: 14px; overflow-x: auto; background: #fff;&quot;&gt;
&lt;table style=&quot;width: 100%; min-width: 620px; border-collapse: collapse; font-size: 15px; line-height: 1.65;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background: #f2f5ff; color: #24458a;&quot;&gt;
&lt;th style=&quot;padding: 11px; text-align: left; border-bottom: 1px solid #d9e2ef;&quot;&gt;구분&lt;/th&gt;
&lt;th style=&quot;padding: 11px; text-align: left; border-bottom: 1px solid #d9e2ef;&quot;&gt;TCP&lt;/th&gt;
&lt;th style=&quot;padding: 11px; text-align: left; border-bottom: 1px solid #d9e2ef;&quot;&gt;UDP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;연결&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;연결 지향형&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;비연결형&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background: #fbfcfe;&quot;&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;신뢰성&amp;middot;순서&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;확인 응답&amp;middot;재전송으로 보장&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;보장하지 않음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;제어&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;흐름 제어&amp;middot;혼잡 제어 수행&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;오버헤드가 작고 단순&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background: #fbfcfe;&quot;&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;속도&amp;middot;용도&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;정확성이 중요한 웹&amp;middot;파일&amp;middot;메일&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;지연이 민감한 스트리밍&amp;middot;실시간 통신&amp;middot;멀티캐스트&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px;&quot;&gt;&lt;b&gt;전송 단위&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px;&quot;&gt;세그먼트&lt;/td&gt;
&lt;td style=&quot;padding: 10px;&quot;&gt;데이터그램&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div style=&quot;margin: 0 0 22px; padding: 17px 18px; border-left: 4px solid #22a06b; background: #f0fbf6;&quot;&gt;
&lt;p style=&quot;margin: 0 0 8px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;흐름 제어&lt;/b&gt;는 수신 측이 처리 가능한 만큼만 보내는 제어입니다. 대표 방식은 Stop-and-Wait와 Sliding Window입니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;혼잡 제어&lt;/b&gt;는 네트워크 자체가 붐비지 않게 하는 제어입니다. Slow Start, Congestion Avoidance, Fast Retransmit, Fast Recovery의 이름과 목적을 연결해 둡니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin: 36px 0 14px; color: #111827; font-size: 24px;&quot; data-ke-size=&quot;size26&quot;&gt;5. 네트워크 전달 방식&lt;/h2&gt;
&lt;div style=&quot;margin: 15px 0 20px; padding: 18px; border: 1px solid #d9e2ef; border-radius: 14px; background: #fff;&quot;&gt;
&lt;p style=&quot;margin: 0 0 11px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단방향(Simplex)&lt;/b&gt; &amp;mdash; 한쪽만 송신. 방송처럼 정보가 한 방향으로만 흐릅니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 11px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;반이중(Half Duplex)&lt;/b&gt; &amp;mdash; 양쪽 모두 송신 가능하지만 &lt;b&gt;동시에&lt;/b&gt;는 불가. 무전기처럼 한쪽이 말하면 다른 쪽은 기다립니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;전이중(Full Duplex)&lt;/b&gt; &amp;mdash; 양쪽이 동시에 송수신. 전화 통화처럼 동시에 말하고 들을 수 있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&quot;margin: 15px 0 20px; padding: 18px; border: 1px solid #d9e2ef; border-radius: 14px; background: #fff;&quot;&gt;
&lt;p style=&quot;margin: 0 0 11px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;유니캐스트&lt;/b&gt; &amp;mdash; 1명이 1명에게. 일반적인 1:1 통신입니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 11px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;브로드캐스트&lt;/b&gt; &amp;mdash; 1명이 같은 네트워크의 모두에게. IPv4에서 사용하며 IPv6에는 없습니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 11px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;멀티캐스트&lt;/b&gt; &amp;mdash; 1명이 가입한 특정 그룹에게만. 모든 장비가 받는 브로드캐스트보다 효율적입니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;애니캐스트&lt;/b&gt; &amp;mdash; 같은 주소를 가진 여러 후보 중 &lt;b&gt;가까운 한 곳&lt;/b&gt;에 전달. IPv6의 대표 전달 방식입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;p style=&quot;margin: 0 0 20px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;교환 방식&lt;/b&gt;도 함께 구분합니다. &lt;b&gt;회선 교환&lt;/b&gt;은 통신 전에 전용 경로를 잡아 두고, &lt;b&gt;패킷 교환&lt;/b&gt;은 데이터를 패킷으로 나누어 공유 망을 이용합니다. 패킷 교환은 매 패킷이 독립적으로 경로를 고를 수 있는 &lt;b&gt;데이터그램 방식&lt;/b&gt;과 논리 경로를 먼저 정하는 &lt;b&gt;가상 회선 방식&lt;/b&gt;으로 나눌 수 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin: 36px 0 14px; color: #111827; font-size: 24px;&quot; data-ke-size=&quot;size26&quot;&gt;6. 네트워크 구조: 범위&amp;middot;모양&amp;middot;장비&lt;/h2&gt;
&lt;div style=&quot;margin: 15px 0 20px; padding: 18px; border: 1px solid #d9e2ef; border-radius: 14px; background: #fff;&quot;&gt;
&lt;p style=&quot;margin: 0 0 11px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;LAN&lt;/b&gt; &amp;mdash; 집&amp;middot;사무실&amp;middot;학교처럼 비교적 좁은 지역의 네트워크. Ethernet과 무선 LAN(Wi-Fi)이 대표입니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 11px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;MAN&lt;/b&gt; &amp;mdash; 도시권 규모의 네트워크.&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;WAN&lt;/b&gt; &amp;mdash; 국가&amp;middot;대륙처럼 넓은 지역을 잇는 네트워크. 인터넷은 대표적인 WAN으로 볼 수 있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&quot;margin: 0 0 20px; border: 1px solid #d9e2ef; border-radius: 14px; overflow-x: auto; background: #fff;&quot;&gt;
&lt;table style=&quot;width: 100%; min-width: 650px; border-collapse: collapse; font-size: 15px; line-height: 1.65;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background: #fff6ee; color: #8a4a10;&quot;&gt;
&lt;th style=&quot;padding: 11px; text-align: left; border-bottom: 1px solid #d9e2ef;&quot;&gt;토폴로지&lt;/th&gt;
&lt;th style=&quot;padding: 11px; text-align: left; border-bottom: 1px solid #d9e2ef;&quot;&gt;구조&amp;middot;장점&lt;/th&gt;
&lt;th style=&quot;padding: 11px; text-align: left; border-bottom: 1px solid #d9e2ef;&quot;&gt;주의할 점&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;버스형&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;하나의 공통 전송선 공유, 구성 단순&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;중앙 케이블 장애&amp;middot;충돌 영향이 큼&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background: #fbfcfe;&quot;&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;성형&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;중앙 허브&amp;middot;스위치에 각 장비 연결, 관리 쉬움&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;중앙 장비 장애 시 전체 영향&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;링형&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;고리 형태로 연결, 순서 있는 전달&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;한 지점 장애가 전체에 영향 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background: #fbfcfe;&quot;&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;&lt;b&gt;망형&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;여러 경로를 둬 신뢰성이 높음&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #edf1f6;&quot;&gt;구축 비용&amp;middot;배선이 큼&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px;&quot;&gt;&lt;b&gt;트리형&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px;&quot;&gt;계층적으로 확장하기 좋음&lt;/td&gt;
&lt;td style=&quot;padding: 10px;&quot;&gt;상위 노드 장애가 하위에 영향&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p style=&quot;margin: 0 0 20px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장비 한 줄 구분:&lt;/b&gt; 리피터는 신호를 재생, 허브는 받은 신호를 여러 포트로 단순 전달, 브리지&amp;middot;스위치는 MAC 주소를 보고 같은 LAN 안에서 전달, 라우터는 IP 주소와 라우팅 정보를 보고 다른 네트워크 사이를 연결, 게이트웨이는 서로 다른 프로토콜&amp;middot;시스템 사이의 출입구 역할을 합니다.&lt;/p&gt;
&lt;h2 style=&quot;margin: 36px 0 14px; color: #111827; font-size: 24px;&quot; data-ke-size=&quot;size26&quot;&gt;7. 네트워크 용어: 헷갈리는 것만 짧고 정확하게&lt;/h2&gt;
&lt;div style=&quot;margin: 15px 0 23px; border: 1px solid #d9e2ef; border-radius: 14px; overflow: hidden; background: #fff;&quot;&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; border-bottom: 1px solid #e7edf5;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;MAC 주소&lt;/b&gt; &amp;mdash; 네트워크 인터페이스에 부여된 하드웨어 주소. 같은 LAN 안의 프레임 전달에 사용.&lt;/p&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; border-bottom: 1px solid #e7edf5; background: #fbfcfe;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;IP 주소&lt;/b&gt; &amp;mdash; 네트워크상 위치를 나타내는 논리 주소. 서로 다른 네트워크를 넘는 패킷 전달에 사용.&lt;/p&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; border-bottom: 1px solid #e7edf5;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;포트 번호&lt;/b&gt; &amp;mdash; 한 컴퓨터 안에서 통신할 응용 프로그램을 구분하는 번호. IP가 건물 주소라면 포트는 호수에 가깝습니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; border-bottom: 1px solid #e7edf5; background: #fbfcfe;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;소켓&lt;/b&gt; &amp;mdash; 통신의 끝점. 보통 IP 주소와 포트 번호를 조합해 식별합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; border-bottom: 1px solid #e7edf5;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;서브넷 마스크&lt;/b&gt; &amp;mdash; IP 주소에서 네트워크 부분과 호스트 부분을 나누는 기준.&lt;/p&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; border-bottom: 1px solid #e7edf5; background: #fbfcfe;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기본 게이트웨이&lt;/b&gt; &amp;mdash; 다른 네트워크로 나갈 때 처음 거치는 라우터의 주소.&lt;/p&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; border-bottom: 1px solid #e7edf5;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DNS&lt;/b&gt; &amp;mdash; 사람이 읽는 도메인 이름을 IP 주소로 바꾸는 서비스.&lt;/p&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; border-bottom: 1px solid #e7edf5; background: #fbfcfe;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DHCP&lt;/b&gt; &amp;mdash; IP 주소, 서브넷 마스크, 게이트웨이, DNS 등의 설정을 자동으로 할당하는 프로토콜.&lt;/p&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; border-bottom: 1px solid #e7edf5;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;NAT&lt;/b&gt; &amp;mdash; 사설 IP와 공인 IP 사이의 주소를 변환하는 기술.&lt;/p&gt;
&lt;p style=&quot;margin: 0; padding: 14px 16px; background: #fbfcfe;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대역폭&amp;middot;처리량&amp;middot;지연&lt;/b&gt; &amp;mdash; 대역폭은 이론상 통로 크기, 처리량은 실제 전달된 양, 지연은 도착까지 걸리는 시간입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin: 36px 0 14px; color: #111827; font-size: 24px;&quot; data-ke-size=&quot;size26&quot;&gt;8. 오늘 개인적으로 중요하다고 생각한 용어&lt;/h2&gt;
&lt;div style=&quot;margin: 15px 0 22px; padding: 18px; border-radius: 14px; background: #f5f8ff; border: 1px solid #dbe7ff;&quot;&gt;
&lt;p style=&quot;margin: 0 0 12px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;① OSI 7계층&lt;/b&gt;&lt;br /&gt;프로토콜이나 장비의 위치를 찾는 분류 지도라서 가장 먼저 잡아야 한다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 12px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;② IP &amp;middot; MAC &amp;middot; 포트&lt;/b&gt;&lt;br /&gt;목적지 네트워크, 같은 LAN의 장비, 컴퓨터 내부 프로그램을 각각 구분하는 주소라는 점이 핵심이다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 12px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;③ TCP와 UDP&lt;/b&gt;&lt;br /&gt;신뢰성 우선인지 빠른 전달 우선인지로 비교하면 암기가 아니라 선택 기준이 된다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 12px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;④ ARP&lt;/b&gt;&lt;br /&gt;IP에서 MAC으로 바꾼다는 한 문장이 기출 빈칸 정답이 되기 쉽다.&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;⑤ IPv4와 IPv6&lt;/b&gt;&lt;br /&gt;32비트&amp;middot;128비트, 브로드캐스트 유무, 전환 기술을 묶어서 외운다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin: 36px 0 14px; color: #111827; font-size: 24px;&quot; data-ke-size=&quot;size26&quot;&gt;9. 공부하면서 아직 헷갈렸던 용어&lt;/h2&gt;
&lt;div style=&quot;margin: 15px 0 22px; padding: 18px; border-radius: 14px; background: #fffaf0; border: 1px solid #f3d99c;&quot;&gt;
&lt;p style=&quot;margin: 0 0 12px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;① 흐름 제어와 혼잡 제어&lt;/b&gt;&lt;br /&gt;흐름 제어는 &lt;b&gt;수신자&lt;/b&gt;가 버티게 하는 것, 혼잡 제어는 &lt;b&gt;네트워크 전체&lt;/b&gt;가 막히지 않게 하는 것이다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 12px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;② 브로드캐스트와 멀티캐스트&lt;/b&gt;&lt;br /&gt;브로드캐스트는 같은 네트워크의 모두, 멀티캐스트는 가입한 그룹만 받는다.&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;③ 서브넷 마스크와 기본 게이트웨이&lt;/b&gt;&lt;br /&gt;서브넷 마스크는 우리 동네인지 판단하는 기준, 기본 게이트웨이는 다른 동네로 나갈 때의 출구로 이해하면 된다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin: 36px 0 14px; color: #111827; font-size: 24px;&quot; data-ke-size=&quot;size26&quot;&gt;10. 1분 셀프 점검&lt;/h2&gt;
&lt;div style=&quot;margin: 15px 0 22px; padding: 18px; border: 1px solid #d9e2ef; border-radius: 14px; background: #fff;&quot;&gt;
&lt;p style=&quot;margin: 0 0 10px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q1.&lt;/b&gt; 라우터와 IP 주소는 몇 계층? &lt;span style=&quot;color: #2458bc;&quot;&gt;&amp;rarr; 3계층 네트워크 계층&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 10px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q2.&lt;/b&gt; IP 주소를 MAC 주소로 변환? &lt;span style=&quot;color: #2458bc;&quot;&gt;&amp;rarr; ARP&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 10px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q3.&lt;/b&gt; 연결 지향&amp;middot;순서 보장&amp;middot;재전송? &lt;span style=&quot;color: #2458bc;&quot;&gt;&amp;rarr; TCP&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 10px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q4.&lt;/b&gt; 실시간성 때문에 빠른 전달을 택할 때? &lt;span style=&quot;color: #2458bc;&quot;&gt;&amp;rarr; UDP&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 10px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q5.&lt;/b&gt; IPv6에 없는 전달 방식? &lt;span style=&quot;color: #2458bc;&quot;&gt;&amp;rarr; 브로드캐스트&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 10px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q6.&lt;/b&gt; 가입한 특정 그룹만 받는 방식? &lt;span style=&quot;color: #2458bc;&quot;&gt;&amp;rarr; 멀티캐스트&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 10px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q7.&lt;/b&gt; LAN 안의 프레임 전달과 관련된 주소? &lt;span style=&quot;color: #2458bc;&quot;&gt;&amp;rarr; MAC 주소&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q8.&lt;/b&gt; 다른 네트워크로 나갈 때 처음 거치는 출구? &lt;span style=&quot;color: #2458bc;&quot;&gt;&amp;rarr; 기본 게이트웨이&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin: 36px 0 14px; color: #111827; font-size: 24px;&quot; data-ke-size=&quot;size26&quot;&gt;11. 오늘 공부한 소회&lt;/h2&gt;
&lt;div style=&quot;margin: 15px 0 26px; padding: 19px 20px; border-left: 4px solid #315efb; background: #f6f8ff;&quot;&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;네트워크는 약어가 많아서 처음에는 전부 따로 외워야 하는 느낌이 들었다. 그런데 &lt;b&gt;계층 &amp;rarr; 주소 &amp;rarr; 전달 방식&lt;/b&gt; 순서로 연결해 보니 역할이 훨씬 선명해졌다. 내일은 기출에서 프로토콜 이름만 보고도 계층과 역할을 바로 말할 수 있는지 확인해 봐야겠다. 특히 TCP&amp;middot;UDP, ARP&amp;middot;RARP, 브로드캐스트&amp;middot;멀티캐스트는 짝으로 계속 비교할 예정이다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin: 36px 0 12px; color: #111827; font-size: 21px;&quot; data-ke-size=&quot;size26&quot;&gt;범위 확인&amp;middot;추가 복습 자료&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 8px; font-size: 14px; color: #52606d;&quot; data-ke-size=&quot;size16&quot;&gt;범위의 세부 항목은 수제비 실기 기본서 목차의 &amp;lsquo;네트워크 계층 구조&amp;middot;프로토콜&amp;middot;전달 방식&amp;middot;구조&amp;middot;용어&amp;rsquo;를 기준으로 확인했습니다. 판본에 따라 정확한 페이지 배치는 달라질 수 있으므로, 이 글은 사용자가 제시한 p.4-148~p.4-197을 기준으로 작성했습니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0; font-size: 14px; line-height: 1.75;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;color: #2458bc; text-decoration: underline;&quot; href=&quot;https://m.yes24.com/goods/detail/169807895&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;수제비 정보처리기사 실기 기본서 목차&lt;/a&gt; &amp;middot; &lt;a style=&quot;color: #2458bc; text-decoration: underline;&quot; href=&quot;https://www.rfc-editor.org/rfc/rfc8200&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;IETF RFC 8200 (IPv6)&lt;/a&gt; &amp;middot; &lt;a style=&quot;color: #2458bc; text-decoration: underline;&quot; href=&quot;https://www.rfc-editor.org/rfc/rfc9293&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;IETF RFC 9293 (TCP)&lt;/a&gt; &amp;middot; &lt;a style=&quot;color: #2458bc; text-decoration: underline;&quot; href=&quot;https://www.rfc-editor.org/rfc/rfc768&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;IETF RFC 768 (UDP)&lt;/a&gt;&lt;/p&gt;
&lt;/article&gt;</description>
      <category>AI/정보처리기사_스터디</category>
      <category>IPv4</category>
      <category>TCP</category>
      <category>tcpip</category>
      <category>UDP</category>
      <category>네트워크기초활용</category>
      <category>수제비</category>
      <category>응용SW기초기술활용</category>
      <category>정보처리기사</category>
      <category>정처기</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/123</guid>
      <comments>https://onethingflow.tistory.com/entry/Day89%EC%A0%95%EC%B2%98%EA%B8%B0-%EA%B3%B5%EB%B6%80-%EA%B8%B0%EB%A1%9D-4%EA%B3%BC%EB%AA%A9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B8%B0%EC%B4%88-%ED%99%9C%EC%9A%A9-p4-148p4-197#entry123comment</comments>
      <pubDate>Wed, 22 Jul 2026 16:59:36 +0900</pubDate>
    </item>
    <item>
      <title>Day 13) 프로그래머스 파이썬 슬라이싱 3문제 풀이</title>
      <link>https://onethingflow.tistory.com/entry/Day-13-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%8A%AC%EB%9D%BC%EC%9D%B4%EC%8B%B1-3%EB%AC%B8%EC%A0%9C-%ED%92%80%EC%9D%B4</link>
      <description>&lt;!--
Title: Day 13) 프로그래머스 파이썬 슬라이싱 3문제 풀이
Meta description: 프로그래머스 코딩 기초 트레이닝 Day 13의 n 번째 원소부터, 순서 바꾸기, 왼쪽 오른쪽을 파이썬으로 풀이합니다. 직접 작성한 코드와 수정 과정, 슬라이싱 인덱스와 조기 반환의 핵심을 함께 정리했습니다.
Tags: 프로그래머스, 코딩테스트, 파이썬, Day13, 슬라이싱, 리스트, enumerate, n번째원소부터, 순서바꾸기, 왼쪽오른쪽
--&gt;

&lt;article class=&quot;hb-post hb-day13-slicing&quot;&gt;
  &lt;style&gt;
    .hb-day13-slicing {
      --hb-ink: #17211d;
      --hb-muted: #5e6b65;
      --hb-line: #d8e1dc;
      --hb-soft: #f5f8f6;
      --hb-accent: #176b57;
      --hb-accent-soft: #edf8f3;
      --hb-warn: #a84412;
      --hb-warn-soft: #fff5ed;
      --hb-code: #18201e;
      max-width: 860px;
      margin: 0 auto;
      color: var(--hb-ink);
      font-size: 17px;
      line-height: 1.82;
      word-break: keep-all;
    }

    .hb-day13-slicing * { box-sizing: border-box; }

    .hb-day13-slicing code,
    .hb-post code { overflow-wrap: anywhere; }

    .hb-day13-slicing .hb-hero {
      margin-bottom: 34px;
      padding: 32px 28px;
      color: #fff;
      background: #145c4b;
      border-radius: 8px;
    }

    .hb-day13-slicing .hb-kicker {
      margin: 0 0 8px;
      color: #d7f5e9;
      font-size: 14px;
      font-weight: 800;
    }

    .hb-day13-slicing h1 {
      margin: 0;
      color: #fff;
      font-size: 33px;
      line-height: 1.35;
      letter-spacing: 0;
    }

    .hb-day13-slicing .hb-title-tail { white-space: nowrap; }

    .hb-day13-slicing .hb-lead {
      margin: 14px 0 0;
      color: #e8fff6;
      font-size: 18px;
    }

    .hb-day13-slicing h2 {
      margin: 52px 0 16px;
      padding-bottom: 10px;
      color: #17211d;
      font-size: 27px;
      line-height: 1.4;
      letter-spacing: 0;
      border-bottom: 2px solid var(--hb-line);
    }

    .hb-day13-slicing h3 {
      margin: 30px 0 10px;
      color: #125443;
      font-size: 20px;
      line-height: 1.5;
      letter-spacing: 0;
    }

    .hb-day13-slicing p { margin: 10px 0; }

    .hb-day13-slicing a {
      color: #086f5b;
      text-decoration-thickness: 1px;
      text-underline-offset: 3px;
    }

    .hb-day13-slicing p code,
    .hb-day13-slicing td code,
    .hb-day13-slicing .hb-item-body code {
      padding: 2px 6px;
      color: #9f1239;
      background: #fff1f2;
      border-radius: 4px;
      font-size: 0.92em;
    }

    .hb-day13-slicing pre {
      margin: 14px 0 20px;
      padding: 19px;
      overflow-x: auto;
      color: #e8f0ec;
      background: var(--hb-code);
      border: 1px solid #31413b;
      border-radius: 8px;
      line-height: 1.65;
      tab-size: 4;
    }

    .hb-day13-slicing pre code {
      padding: 0;
      color: inherit;
      background: transparent;
      font-size: 14px;
      white-space: pre;
      overflow-wrap: normal;
    }

    .hb-day13-slicing .hb-summary,
    .hb-day13-slicing .hb-note,
    .hb-day13-slicing .hb-warning {
      margin: 20px 0;
      padding: 17px 19px;
      border-radius: 8px;
    }

    .hb-day13-slicing .hb-summary,
    .hb-day13-slicing .hb-note {
      background: var(--hb-accent-soft);
      border-left: 4px solid var(--hb-accent);
    }

    .hb-day13-slicing .hb-warning {
      background: var(--hb-warn-soft);
      border-left: 4px solid var(--hb-warn);
    }

    .hb-day13-slicing .hb-summary strong,
    .hb-day13-slicing .hb-note strong,
    .hb-day13-slicing .hb-warning strong {
      display: block;
      margin-bottom: 4px;
    }

    .hb-day13-slicing .hb-table-wrap {
      width: 100%;
      margin: 16px 0 24px;
      overflow-x: auto;
      border: 1px solid var(--hb-line);
      border-radius: 8px;
    }

    .hb-day13-slicing table {
      width: 100%;
      min-width: 650px;
      border-collapse: collapse;
      font-size: 15px;
    }

    .hb-day13-slicing caption {
      padding: 12px 14px;
      color: #33433c;
      background: var(--hb-soft);
      font-weight: 800;
      text-align: left;
    }

    .hb-day13-slicing th,
    .hb-day13-slicing td {
      padding: 12px 14px;
      text-align: left;
      vertical-align: top;
      border-bottom: 1px solid var(--hb-line);
    }

    .hb-day13-slicing th {
      color: #33433c;
      background: #f8faf9;
    }

    .hb-day13-slicing tbody tr:last-child td { border-bottom: 0; }

    .hb-day13-slicing .hb-index-list {
      display: grid;
      gap: 12px;
      margin: 17px 0 24px;
    }

    .hb-day13-slicing .hb-index-item {
      display: grid;
      grid-template-columns: 34px minmax(0, 1fr);
      gap: 12px;
      align-items: start;
      padding: 15px 16px;
      background: #fff;
      border: 1px solid var(--hb-line);
      border-radius: 8px;
    }

    .hb-day13-slicing .hb-index-number {
      display: inline-flex;
      width: 30px;
      height: 30px;
      align-items: center;
      justify-content: center;
      color: #fff;
      background: var(--hb-accent);
      border-radius: 6px;
      font-size: 14px;
      font-weight: 900;
      line-height: 1;
    }

    .hb-day13-slicing .hb-item-title {
      display: block;
      margin-bottom: 3px;
      font-weight: 800;
    }

    .hb-day13-slicing .hb-check-list {
      display: grid;
      gap: 10px;
      margin: 15px 0;
    }

    .hb-day13-slicing .hb-check-item {
      display: grid;
      grid-template-columns: 25px minmax(0, 1fr);
      gap: 8px;
      align-items: start;
    }

    .hb-day13-slicing .hb-check-mark {
      color: var(--hb-accent);
      font-weight: 900;
      text-align: center;
    }

    .hb-day13-slicing .hb-closing {
      margin-top: 48px;
      padding: 23px;
      background: var(--hb-soft);
      border-top: 3px solid var(--hb-accent);
      border-radius: 8px;
    }

    @media (max-width: 640px) {
      .hb-day13-slicing {
        font-size: 16px;
        line-height: 1.76;
        word-break: normal;
      }

      .hb-day13-slicing .hb-hero { padding: 26px 20px; }
      .hb-day13-slicing h1 { font-size: 27px; }
      .hb-day13-slicing .hb-title-tail { display: block; }
      .hb-day13-slicing h2 { margin-top: 44px; font-size: 23px; }
      .hb-day13-slicing h3 { font-size: 19px; }
      .hb-day13-slicing pre { padding: 16px; }

      .hb-day13-slicing .hb-index-item {
        grid-template-columns: 30px minmax(0, 1fr);
        gap: 10px;
        padding: 14px;
      }
    }
  &lt;/style&gt;

  &lt;header class=&quot;hb-hero&quot;&gt;
    &lt;p class=&quot;hb-kicker&quot;&gt;Programmers Coding Test · Day 13 · Python&lt;/p&gt;
    &lt;h1&gt;파이썬 슬라이싱 &lt;span class=&quot;hb-title-tail&quot;&gt;3문제 풀이&lt;/span&gt;&lt;/h1&gt;
    &lt;p class=&quot;hb-lead&quot;&gt;n번째 위치를 파이썬 인덱스로 바꾸는 법부터, 기준점을 중심으로 리스트를 나누고 원하는 문자를 찾는 즉시 반환하는 방법까지 정리했습니다.&lt;/p&gt;
  &lt;/header&gt;

  &lt;p&gt;오늘은 슬라이싱을 이용해 리스트의 일부를 꺼내거나 앞뒤 순서를 바꾸는 문제를 풀었다. 처음 두 문제는 접근과 코드가 모두 정확했다. 세 번째 문제인 &lt;strong&gt;왼쪽 오른쪽&lt;/strong&gt;에서는 슬라이싱할 대상, &lt;code&gt;else&lt;/code&gt;와 &lt;code&gt;return&lt;/code&gt;의 위치, 기준 문자를 결과에서 제외하는 방법을 여러 번 고치면서 답을 완성했다.&lt;/p&gt;

  &lt;div class=&quot;hb-summary&quot;&gt;
    &lt;strong&gt;오늘의 핵심&lt;/strong&gt;
    문제의 표현이 &quot;n번째&quot;인지 &quot;n번째 이후&quot;인지 먼저 구분해야 한다. 사람의 순서는 1부터 시작하지만 파이썬 인덱스는 0부터 시작한다. 또한 리스트에서 특정 기준을 처음 발견했을 때 답이 결정된다면 값을 계속 덮어쓰지 말고 바로 &lt;code&gt;return&lt;/code&gt;하는 편이 명확하다.
  &lt;/div&gt;

  &lt;h2&gt;문제 및 공식 링크&lt;/h2&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;프로그래머스 코딩 기초 트레이닝 슬라이싱 문제&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;&lt;th scope=&quot;col&quot;&gt;순서&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;문제&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;핵심 개념&lt;/th&gt;&lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181892&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;n 번째 원소부터&lt;/a&gt;&lt;/td&gt;&lt;td&gt;1-based와 0-based 인덱스&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181891&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;순서 바꾸기&lt;/a&gt;&lt;/td&gt;&lt;td&gt;리스트 분할과 연결&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181890&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;왼쪽 오른쪽&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;enumerate()&lt;/code&gt;, 조기 반환&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;1. n 번째 원소부터&lt;/h2&gt;

  &lt;p&gt;정수 리스트 &lt;code&gt;num_list&lt;/code&gt;와 정수 &lt;code&gt;n&lt;/code&gt;이 주어지면 n번째 원소부터 마지막 원소까지를 새 리스트로 반환하는 문제다.&lt;/p&gt;

  &lt;h3&gt;내 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(num_list, n):
    answer = num_list[n - 1:]
    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;이 풀이는 그대로 정답이다. 문제의 n번째는 1부터 세지만 파이썬 리스트의 인덱스는 0부터 센다. 따라서 n번째 원소의 인덱스는 &lt;code&gt;n - 1&lt;/code&gt;이다. 슬라이싱의 끝을 생략한 &lt;code&gt;[n - 1:]&lt;/code&gt;은 그 위치부터 리스트 끝까지 가져온다.&lt;/p&gt;

  &lt;div class=&quot;hb-index-list&quot;&gt;
    &lt;div class=&quot;hb-index-item&quot;&gt;&lt;span class=&quot;hb-index-number&quot;&gt;1&lt;/span&gt;&lt;div class=&quot;hb-item-body&quot;&gt;&lt;span class=&quot;hb-item-title&quot;&gt;사람이 세는 위치&lt;/span&gt;첫 번째, 두 번째, 세 번째처럼 1부터 시작한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-index-item&quot;&gt;&lt;span class=&quot;hb-index-number&quot;&gt;2&lt;/span&gt;&lt;div class=&quot;hb-item-body&quot;&gt;&lt;span class=&quot;hb-item-title&quot;&gt;파이썬 인덱스&lt;/span&gt;0, 1, 2처럼 0부터 시작하므로 n번째 위치는 &lt;code&gt;n - 1&lt;/code&gt;이다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-index-item&quot;&gt;&lt;span class=&quot;hb-index-number&quot;&gt;3&lt;/span&gt;&lt;div class=&quot;hb-item-body&quot;&gt;&lt;span class=&quot;hb-item-title&quot;&gt;끝점 생략&lt;/span&gt;&lt;code&gt;num_list[n - 1:]&lt;/code&gt;에서 콜론 뒤를 비우면 마지막 원소까지 선택한다.&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;h3&gt;더 간단한 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(num_list, n):
    return num_list[n - 1:]&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;answer&lt;/code&gt;를 별도로 저장할 필요가 없다면 슬라이싱 결과를 바로 반환할 수 있다. 두 코드는 결과와 시간 복잡도가 같다. 길이가 k인 결과 리스트를 새로 만들기 때문에 시간과 추가 공간은 모두 O(k)다.&lt;/p&gt;

  &lt;h3&gt;검산&lt;/h3&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;n 번째 원소부터 입출력 확인&lt;/caption&gt;
      &lt;thead&gt;&lt;tr&gt;&lt;th scope=&quot;col&quot;&gt;num_list&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;n&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;시작 인덱스&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;결과&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td&gt;&lt;code&gt;[2, 1, 6]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[6]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;&lt;code&gt;[5, 2, 1, 7, 5]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[2, 1, 7, 5]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;2. 순서 바꾸기&lt;/h2&gt;

  &lt;p&gt;리스트를 n번째 원소까지의 앞부분과 n번째 원소 이후의 뒷부분으로 나눈 뒤, 뒷부분을 앞에 붙이는 문제다. 이 문제에서는 n번째 원소까지가 앞부분에 포함되므로 자르는 기준이 &lt;code&gt;n&lt;/code&gt;이다.&lt;/p&gt;

  &lt;h3&gt;내 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(num_list, n):
    answer = []
    answer = num_list[n:] + num_list[:n]
    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;핵심 슬라이싱은 정확하다. &lt;code&gt;num_list[n:]&lt;/code&gt;은 n번째 원소 이후의 뒷부분이고, &lt;code&gt;num_list[:n]&lt;/code&gt;은 n번째 원소까지의 앞부분이다. 리스트끼리 &lt;code&gt;+&lt;/code&gt;를 사용하면 원소별 덧셈이 아니라 두 리스트를 차례로 연결한다.&lt;/p&gt;

  &lt;div class=&quot;hb-warning&quot;&gt;
    &lt;strong&gt;수정할 부분은 불필요한 초기화 한 줄뿐이다&lt;/strong&gt;
    처음 만든 빈 리스트 &lt;code&gt;answer = []&lt;/code&gt;는 바로 다음 줄에서 새 리스트로 덮어쓴다. 오류는 아니지만 사용되지 않으므로 지우는 편이 낫다.
  &lt;/div&gt;

  &lt;h3&gt;정리한 기본 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(num_list, n):
    back = num_list[n:]
    front = num_list[:n]
    return back + front&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;처음 슬라이싱을 배울 때는 &lt;code&gt;back&lt;/code&gt;과 &lt;code&gt;front&lt;/code&gt;를 나눠 적으면 문제의 문장과 코드가 바로 연결된다. 동작을 이해한 뒤에는 아래처럼 한 줄로 줄일 수 있다.&lt;/p&gt;

  &lt;h3&gt;더 간단한 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(num_list, n):
    return num_list[n:] + num_list[:n]&lt;/code&gt;&lt;/pre&gt;

  &lt;div class=&quot;hb-note&quot;&gt;
    &lt;strong&gt;왜 n - 1이 아니라 n일까?&lt;/strong&gt;
    첫 번째 문제는 &quot;n번째 원소부터&quot;이므로 n번째 원소를 포함해 &lt;code&gt;n - 1&lt;/code&gt;에서 시작했다. 이번 문제는 &quot;n번째 원소 이후&quot;가 뒷부분의 시작이므로 n번째 원소 바로 다음 인덱스인 &lt;code&gt;n&lt;/code&gt;에서 자른다.
  &lt;/div&gt;

  &lt;h3&gt;검산&lt;/h3&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;순서 바꾸기 입출력 확인&lt;/caption&gt;
      &lt;thead&gt;&lt;tr&gt;&lt;th scope=&quot;col&quot;&gt;입력&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;뒷부분&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;앞부분&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;결과&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td&gt;&lt;code&gt;[2, 1, 6], n=1&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[1, 6]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[2]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[1, 6, 2]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;&lt;code&gt;[5, 2, 1, 7, 5], n=3&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[7, 5]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[5, 2, 1]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[7, 5, 5, 2, 1]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;3. 왼쪽 오른쪽&lt;/h2&gt;

  &lt;p&gt;&lt;code&gt;str_list&lt;/code&gt;를 왼쪽부터 확인해 &lt;code&gt;&quot;l&quot;&lt;/code&gt;과 &lt;code&gt;&quot;r&quot;&lt;/code&gt; 중 먼저 나온 문자를 찾는다. &lt;code&gt;&quot;l&quot;&lt;/code&gt;이 먼저 나오면 그 왼쪽을, &lt;code&gt;&quot;r&quot;&lt;/code&gt;이 먼저 나오면 그 오른쪽을 반환한다. 두 문자가 모두 없으면 빈 리스트를 반환한다.&lt;/p&gt;

  &lt;h3&gt;처음 작성한 코드&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(str_list):
    answer = []

    for i, str in enumerate(str_list):
        if str == &quot;u&quot;:
            answer = [:i]
        elif str == &quot;r&quot;:
            answer = [i:]
        else:
            answer = []

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;인덱스와 현재 문자를 함께 얻기 위해 &lt;code&gt;enumerate()&lt;/code&gt;를 선택한 방향은 좋았다. 다만 슬라이싱 문법과 반복 종료 시점에서 몇 가지 문제가 있었다.&lt;/p&gt;

  &lt;div class=&quot;hb-index-list&quot;&gt;
    &lt;div class=&quot;hb-index-item&quot;&gt;&lt;span class=&quot;hb-index-number&quot;&gt;1&lt;/span&gt;&lt;div class=&quot;hb-item-body&quot;&gt;&lt;span class=&quot;hb-item-title&quot;&gt;비교할 문자가 다르다&lt;/span&gt;문제의 기준은 &lt;code&gt;&quot;l&quot;&lt;/code&gt;과 &lt;code&gt;&quot;r&quot;&lt;/code&gt;이다. 첫 조건의 &lt;code&gt;&quot;u&quot;&lt;/code&gt;는 &lt;code&gt;&quot;l&quot;&lt;/code&gt;로 고쳐야 한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-index-item&quot;&gt;&lt;span class=&quot;hb-index-number&quot;&gt;2&lt;/span&gt;&lt;div class=&quot;hb-item-body&quot;&gt;&lt;span class=&quot;hb-item-title&quot;&gt;슬라이싱 대상이 빠졌다&lt;/span&gt;&lt;code&gt;[:i]&lt;/code&gt;만 쓸 수는 없다. 무엇을 자를지 앞에 적어 &lt;code&gt;str_list[:i]&lt;/code&gt;처럼 작성해야 한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-index-item&quot;&gt;&lt;span class=&quot;hb-index-number&quot;&gt;3&lt;/span&gt;&lt;div class=&quot;hb-item-body&quot;&gt;&lt;span class=&quot;hb-item-title&quot;&gt;r 자체는 결과에서 제외한다&lt;/span&gt;&lt;code&gt;str_list[i:]&lt;/code&gt;는 &lt;code&gt;&quot;r&quot;&lt;/code&gt;도 포함한다. 오른쪽 원소만 가져오려면 &lt;code&gt;str_list[i + 1:]&lt;/code&gt;이어야 한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-index-item&quot;&gt;&lt;span class=&quot;hb-index-number&quot;&gt;4&lt;/span&gt;&lt;div class=&quot;hb-item-body&quot;&gt;&lt;span class=&quot;hb-item-title&quot;&gt;답이 정해지면 즉시 끝낸다&lt;/span&gt;먼저 나온 &lt;code&gt;&quot;l&quot;&lt;/code&gt; 또는 &lt;code&gt;&quot;r&quot;&lt;/code&gt;만 중요하다. 발견한 결과를 저장한 뒤 반복을 계속하면 이후 값으로 덮어쓸 수 있으므로 바로 반환하는 것이 안전하다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-index-item&quot;&gt;&lt;span class=&quot;hb-index-number&quot;&gt;5&lt;/span&gt;&lt;div class=&quot;hb-item-body&quot;&gt;&lt;span class=&quot;hb-item-title&quot;&gt;내장 함수 이름은 변수로 피한다&lt;/span&gt;&lt;code&gt;str&lt;/code&gt;은 문자열 변환에 사용하는 파이썬 내장 함수다. 문법 오류는 아니지만 &lt;code&gt;char&lt;/code&gt;나 &lt;code&gt;direction&lt;/code&gt;처럼 역할이 드러나는 이름이 좋다.&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;h3&gt;두 번째 시도&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(str_list):
    for i, char in enumerate(str_list):
        if char == &quot;l&quot;:
            return char[:i]
        elif char == &quot;r&quot;:
            return char[i:]
        else:
            return []&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;이번에는 답이 정해질 때 바로 &lt;code&gt;return&lt;/code&gt;하도록 바꿨지만, 여전히 전체 리스트가 아닌 한 글자인 &lt;code&gt;char&lt;/code&gt;를 자르고 있다. 또한 첫 원소가 &lt;code&gt;&quot;l&quot;&lt;/code&gt;이나 &lt;code&gt;&quot;r&quot;&lt;/code&gt;이 아니면 &lt;code&gt;else&lt;/code&gt;에서 바로 빈 리스트를 반환하므로 뒤쪽 원소를 확인할 기회를 잃는다.&lt;/p&gt;

  &lt;div class=&quot;hb-warning&quot;&gt;
    &lt;strong&gt;빈 리스트 반환은 반복문이 끝난 뒤에 둔다&lt;/strong&gt;
    &lt;code&gt;&quot;l&quot;&lt;/code&gt;과 &lt;code&gt;&quot;r&quot;&lt;/code&gt;이 없다는 사실은 리스트 전체를 확인한 뒤에야 알 수 있다. 따라서 &lt;code&gt;return []&lt;/code&gt;은 &lt;code&gt;for&lt;/code&gt;문 밖에 있어야 한다.
  &lt;/div&gt;

  &lt;h3&gt;최종 수정 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(str_list):
    for i, char in enumerate(str_list):
        if char == &quot;l&quot;:
            return str_list[:i]
        elif char == &quot;r&quot;:
            return str_list[i + 1:]

    return []&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;enumerate(str_list)&lt;/code&gt;는 인덱스 &lt;code&gt;i&lt;/code&gt;와 현재 값 &lt;code&gt;char&lt;/code&gt;를 동시에 준다. 왼쪽부터 탐색하기 때문에 처음 만난 &lt;code&gt;&quot;l&quot;&lt;/code&gt; 또는 &lt;code&gt;&quot;r&quot;&lt;/code&gt;이 문제에서 요구한 기준 문자가 된다. 답이 결정된 순간 반환하므로 뒤의 원소는 볼 필요가 없다.&lt;/p&gt;

  &lt;h3&gt;range(len())을 사용한 내 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(str_list):
    for i in range(len(str_list)):
        if str_list[i] == &quot;l&quot;:
            return str_list[:i]
        elif str_list[i] == &quot;r&quot;:
            return str_list[i + 1:]

    return []&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;이 코드도 정확한 정답이다. &lt;code&gt;range(len(str_list))&lt;/code&gt;는 인덱스를 직접 순회하고, &lt;code&gt;enumerate(str_list)&lt;/code&gt;는 인덱스와 값을 함께 순회한다. 현재 값과 인덱스가 모두 필요한 이 문제에서는 &lt;code&gt;enumerate()&lt;/code&gt; 쪽이 같은 표현을 반복하지 않아 조금 더 읽기 쉽다.&lt;/p&gt;

  &lt;h3&gt;조건을 묶은 간단한 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(str_list):
    for i, direction in enumerate(str_list):
        if direction in (&quot;l&quot;, &quot;r&quot;):
            return str_list[:i] if direction == &quot;l&quot; else str_list[i + 1:]

    return []&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;두 기준 문자를 한 조건에서 찾고 삼항 조건식으로 반환 범위를 선택하는 방법이다. 코드는 짧지만 슬라이싱을 처음 배우는 단계라면 &lt;code&gt;if&lt;/code&gt;와 &lt;code&gt;elif&lt;/code&gt;를 나눈 최종 수정 풀이가 의도를 더 분명하게 보여준다.&lt;/p&gt;

  &lt;h3&gt;for-else도 가능할까?&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(str_list):
    for i, char in enumerate(str_list):
        if char == &quot;l&quot;:
            return str_list[:i]
        elif char == &quot;r&quot;:
            return str_list[i + 1:]
    else:
        return []&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;이 형태도 동작한다. 파이썬의 &lt;code&gt;for-else&lt;/code&gt;에서 &lt;code&gt;else&lt;/code&gt;는 반복이 정상적으로 끝났을 때 실행된다. 이 코드에서는 기준 문자를 찾으면 함수가 먼저 반환되고, 끝까지 찾지 못했을 때만 빈 리스트를 반환한다. 다만 &lt;code&gt;break&lt;/code&gt;를 사용하지 않는 짧은 함수에서는 &lt;code&gt;for&lt;/code&gt;문 뒤에 &lt;code&gt;return []&lt;/code&gt;을 두는 방식이 더 익숙하고 단순하다.&lt;/p&gt;

  &lt;h3&gt;검산&lt;/h3&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;왼쪽 오른쪽의 기준 문자와 결과&lt;/caption&gt;
      &lt;thead&gt;&lt;tr&gt;&lt;th scope=&quot;col&quot;&gt;str_list&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;먼저 찾은 문자&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;결과&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td&gt;&lt;code&gt;[&quot;u&quot;, &quot;u&quot;, &quot;l&quot;, &quot;r&quot;]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;&quot;l&quot;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[&quot;u&quot;, &quot;u&quot;]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;&lt;code&gt;[&quot;l&quot;]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;&quot;l&quot;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;&lt;code&gt;[&quot;u&quot;, &quot;d&quot;, &quot;r&quot;, &quot;d&quot;]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;&quot;r&quot;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[&quot;d&quot;]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;&lt;code&gt;[&quot;u&quot;, &quot;d&quot;]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;없음&lt;/td&gt;&lt;td&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;보충: 슬라이싱과 파이썬 메모리&lt;/h2&gt;

  &lt;p&gt;공부할 때 프로그램 메모리를 정적 영역, 스택, 힙으로 나누는 그림을 함께 보았다. 프로그램의 메모리 구조를 큰 틀에서 이해하는 데는 유용하지만, 파이썬 코드를 설명할 때 모든 지역 변수가 곧바로 스택에 저장되고 리스트는 힙에 저장된다고 단정하면 실제 구현을 지나치게 단순화하게 된다.&lt;/p&gt;

  &lt;div class=&quot;hb-index-list&quot;&gt;
    &lt;div class=&quot;hb-index-item&quot;&gt;&lt;span class=&quot;hb-index-number&quot;&gt;1&lt;/span&gt;&lt;div class=&quot;hb-item-body&quot;&gt;&lt;span class=&quot;hb-item-title&quot;&gt;변수는 객체를 가리키는 이름이다&lt;/span&gt;&lt;code&gt;num_list&lt;/code&gt;, &lt;code&gt;i&lt;/code&gt;, &lt;code&gt;char&lt;/code&gt; 같은 이름은 실행 중인 함수의 프레임에서 각각의 파이썬 객체를 참조한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-index-item&quot;&gt;&lt;span class=&quot;hb-index-number&quot;&gt;2&lt;/span&gt;&lt;div class=&quot;hb-item-body&quot;&gt;&lt;span class=&quot;hb-item-title&quot;&gt;리스트 슬라이싱은 새 리스트를 만든다&lt;/span&gt;&lt;code&gt;num_list[n - 1:]&lt;/code&gt;은 원본과 별개의 리스트 객체를 만든다. 다만 내부 원소 자체를 깊게 복사하는 것은 아니므로 중첩 리스트에서는 같은 하위 객체를 참조할 수 있다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-index-item&quot;&gt;&lt;span class=&quot;hb-index-number&quot;&gt;3&lt;/span&gt;&lt;div class=&quot;hb-item-body&quot;&gt;&lt;span class=&quot;hb-item-title&quot;&gt;정수와 문자열은 불변 객체다&lt;/span&gt;이번 문제의 정수와 한 글자 문자열은 값을 직접 바꿀 수 없는 불변 객체라서 얕은 복사로 인한 문제가 드러나지 않는다.&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;source = [[1], [2]]
cut = source[:1]

cut[0].append(9)

print(source)  # [[1, 9], [2]]
print(cut)     # [[1, 9]]&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;source&lt;/code&gt;와 &lt;code&gt;cut&lt;/code&gt;은 서로 다른 바깥 리스트지만 첫 번째 내부 리스트는 함께 참조한다. 슬라이싱을 단순히 &quot;원본 전체를 완전히 복제한다&quot;고 이해하지 않고 &lt;strong&gt;새 리스트를 만드는 얕은 복사&lt;/strong&gt;라고 기억하면 이후 중첩 리스트 문제에서 도움이 된다.&lt;/p&gt;

  &lt;h2&gt;실수 방지 체크리스트&lt;/h2&gt;

  &lt;div class=&quot;hb-check-list&quot;&gt;
    &lt;div class=&quot;hb-check-item&quot;&gt;&lt;span class=&quot;hb-check-mark&quot;&gt;✓&lt;/span&gt;&lt;div&gt;문제의 n번째를 파이썬 인덱스로 바꿀 때 &lt;code&gt;n - 1&lt;/code&gt;이 필요한지 확인한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-check-item&quot;&gt;&lt;span class=&quot;hb-check-mark&quot;&gt;✓&lt;/span&gt;&lt;div&gt;&quot;n번째부터&quot;와 &quot;n번째 이후&quot;를 구분한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-check-item&quot;&gt;&lt;span class=&quot;hb-check-mark&quot;&gt;✓&lt;/span&gt;&lt;div&gt;&lt;code&gt;[:i]&lt;/code&gt;처럼 대상을 빠뜨리지 않고 &lt;code&gt;str_list[:i]&lt;/code&gt;처럼 작성한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-check-item&quot;&gt;&lt;span class=&quot;hb-check-mark&quot;&gt;✓&lt;/span&gt;&lt;div&gt;기준 원소를 결과에 포함할지에 따라 &lt;code&gt;i&lt;/code&gt;와 &lt;code&gt;i + 1&lt;/code&gt;을 구분한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-check-item&quot;&gt;&lt;span class=&quot;hb-check-mark&quot;&gt;✓&lt;/span&gt;&lt;div&gt;첫 번째 일치 항목이 답이라면 찾는 즉시 반환한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-check-item&quot;&gt;&lt;span class=&quot;hb-check-mark&quot;&gt;✓&lt;/span&gt;&lt;div&gt;실패 결과는 전체 탐색이 끝난 뒤 반환한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-check-item&quot;&gt;&lt;span class=&quot;hb-check-mark&quot;&gt;✓&lt;/span&gt;&lt;div&gt;&lt;code&gt;str&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt;처럼 파이썬 내장 함수 이름을 변수명으로 사용하지 않는다.&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;h2&gt;같이 보면 좋은 자료&lt;/h2&gt;

  &lt;div class=&quot;hb-index-list&quot;&gt;
    &lt;div class=&quot;hb-index-item&quot;&gt;&lt;span class=&quot;hb-index-number&quot;&gt;1&lt;/span&gt;&lt;div class=&quot;hb-item-body&quot;&gt;&lt;span class=&quot;hb-item-title&quot;&gt;&lt;a href=&quot;https://docs.python.org/3/library/stdtypes.html#common-sequence-operations&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;파이썬 공식 문서: 시퀀스 연산&lt;/a&gt;&lt;/span&gt;슬라이싱과 리스트 연결을 포함한 공통 시퀀스 연산을 확인할 수 있다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-index-item&quot;&gt;&lt;span class=&quot;hb-index-number&quot;&gt;2&lt;/span&gt;&lt;div class=&quot;hb-item-body&quot;&gt;&lt;span class=&quot;hb-item-title&quot;&gt;&lt;a href=&quot;https://docs.python.org/3/library/functions.html#enumerate&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;파이썬 공식 문서: enumerate()&lt;/a&gt;&lt;/span&gt;인덱스와 값을 함께 순회하는 기본 함수의 동작을 정리한 문서다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-index-item&quot;&gt;&lt;span class=&quot;hb-index-number&quot;&gt;3&lt;/span&gt;&lt;div class=&quot;hb-item-body&quot;&gt;&lt;span class=&quot;hb-item-title&quot;&gt;&lt;a href=&quot;https://docs.python.org/3/c-api/memory.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;파이썬 공식 문서: 메모리 관리&lt;/a&gt;&lt;/span&gt;파이썬 메모리 관리가 일반적인 스택과 힙 그림보다 세부적으로 어떻게 설명되는지 살펴볼 수 있다.&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;div class=&quot;hb-closing&quot;&gt;
    &lt;strong&gt;마무리&lt;/strong&gt;
    &lt;p&gt;이번 세 문제에서 가장 중요한 차이는 한 칸이었다. &lt;code&gt;n - 1&lt;/code&gt;, &lt;code&gt;n&lt;/code&gt;, &lt;code&gt;i + 1&lt;/code&gt;은 모두 기준 원소를 포함할지 제외할지에 따라 달라진다. 슬라이싱을 쓰기 전에 시작 위치가 가리키는 원소와 끝 위치가 결과에 포함되는지를 작은 예로 먼저 적어 보면 실수를 크게 줄일 수 있다. 특히 세 번째 문제를 여러 번 고치며 슬라이싱의 대상과 반환 위치를 직접 찾아낸 과정이 다음 탐색 문제에도 그대로 이어질 핵심 연습이었다.&lt;/p&gt;
  &lt;/div&gt;
&lt;/article&gt;
</description>
      <category>AI/Coding_Test</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/122</guid>
      <comments>https://onethingflow.tistory.com/entry/Day-13-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%8A%AC%EB%9D%BC%EC%9D%B4%EC%8B%B1-3%EB%AC%B8%EC%A0%9C-%ED%92%80%EC%9D%B4#entry122comment</comments>
      <pubDate>Tue, 21 Jul 2026 19:03:04 +0900</pubDate>
    </item>
    <item>
      <title>Day8~9)정처기 필기(응용 SW 기초 기술 활용, 운영체제 기초 활용)</title>
      <link>https://onethingflow.tistory.com/entry/Day89%EC%A0%95%EC%B2%98%EA%B8%B0-%ED%95%84%EA%B8%B0%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-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EA%B8%B0%EC%B4%88-%ED%99%9C%EC%9A%A9</link>
      <description>&lt;!--
티스토리 제목 추천: 운영체제 초보자용 정리: FIFO·LRU·스레드·스케줄링 한 번에 이해하기
메타 설명 추천: 정보처리기사 운영체제에서 자주 헷갈리는 페이지 교체, 페이지 부재, 워킹 세트, 스레드, CPU 스케줄링, 리눅스 명령어를 초보자용 예제로 정리합니다.
태그 추천: 정보처리기사, 정처기, 운영체제, FIFO, LRU, LFU, 페이지교체, CPU스케줄링, 리눅스명령어
--&gt;

&lt;style&gt;
.hb-post {
  --hb-ink: #192235;
  --hb-muted: #657085;
  --hb-line: #dfe6ef;
  --hb-blue: #315efb;
  --hb-blue-soft: #f2f6ff;
  --hb-green: #14795f;
  --hb-green-soft: #effaf6;
  --hb-amber: #9d6100;
  --hb-amber-soft: #fff8e8;
  --hb-red: #b63b3b;
  --hb-red-soft: #fff4f4;
  max-width: 780px;
  margin: 0 auto;
  color: var(--hb-ink);
  font-size: 17px;
  line-height: 1.82;
  word-break: keep-all;
  overflow-wrap: break-word;
}

.hb-post,
.hb-post * { box-sizing: border-box; }
.hb-post h1,
.hb-post h2,
.hb-post h3,
.hb-post p,
.hb-post figure { margin-top: 0; }
.hb-post h1 {
  margin-bottom: .58em;
  font-size: clamp(1.72rem, 5vw, 2.2rem);
  line-height: 1.28;
  letter-spacing: -.04em;
}
.hb-post h2 {
  margin: 2.65em 0 .85em;
  padding-bottom: .38em;
  border-bottom: 2px solid #edf1f6;
  font-size: 1.42em;
  line-height: 1.4;
  letter-spacing: -.025em;
}
.hb-post h3 {
  margin: 1.75em 0 .58em;
  font-size: 1.12em;
  line-height: 1.45;
}
.hb-post p { margin-bottom: 1.04em; }
.hb-post code {
  padding: .08em .34em;
  border-radius: 4px;
  background: #eef2f7;
  color: #24314a;
  font-family: Consolas, Monaco, &quot;Courier New&quot;, monospace;
  font-size: .92em;
  overflow-wrap: anywhere;
}
.hb-post .hb-hero {
  margin-bottom: 1.5em;
  padding: 1.5em;
  border: 1px solid #d9e3f2;
  border-radius: 14px;
  background: radial-gradient(circle at 92% 8%, rgba(49, 94, 251, .14), transparent 33%), linear-gradient(135deg, #f7faff, #fff 68%, #fffaf0);
}
.hb-post .hb-eyebrow {
  display: inline-block;
  margin-bottom: .72em;
  padding: .26em .72em;
  border: 1px solid #d5def0;
  border-radius: 999px;
  background: #fff;
  color: #466080;
  font-size: .82em;
  font-weight: 800;
}
.hb-post .hb-lead { margin-bottom: .65em; color: #344054; font-size: 1.06em; }
.hb-post .hb-hero-foot { margin-bottom: 0; color: var(--hb-muted); font-size: .92em; }
.hb-post .hb-card-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: .72em;
  margin: 1.2em 0 1.45em;
}
.hb-post .hb-card {
  min-width: 0;
  padding: .92em;
  border: 1px solid var(--hb-line);
  border-radius: 10px;
  background: #fff;
}
.hb-post .hb-card span { display: block; margin-bottom: .3em; color: var(--hb-muted); font-size: .78em; font-weight: 800; }
.hb-post .hb-card strong { display: block; font-size: .95em; line-height: 1.45; }
.hb-post .hb-callout,
.hb-post .hb-warning,
.hb-post .hb-correct,
.hb-post .hb-source-note {
  margin: 1.25em 0;
  padding: 1em 1.08em;
  border-radius: 9px;
}
.hb-post .hb-callout { border: 1px solid #dbe4f3; border-left: 4px solid var(--hb-blue); background: #f8fbff; }
.hb-post .hb-warning { border: 1px solid #f0d7d7; border-left: 4px solid var(--hb-red); background: var(--hb-red-soft); }
.hb-post .hb-correct { border: 1px solid #d4eadf; border-left: 4px solid var(--hb-green); background: var(--hb-green-soft); }
.hb-post .hb-source-note { border: 1px solid #eadfbd; border-left: 4px solid #d39114; background: var(--hb-amber-soft); color: #594411; }
.hb-post .hb-callout strong,
.hb-post .hb-warning strong,
.hb-post .hb-correct strong,
.hb-post .hb-source-note strong { display: block; margin-bottom: .34em; }
.hb-post .hb-callout p,
.hb-post .hb-warning p,
.hb-post .hb-correct p,
.hb-post .hb-source-note p { margin-bottom: 0; }
.hb-post .hb-number-list { display: grid; gap: .78em; margin: 1.15em 0 1.45em; }
.hb-post .hb-number-item {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  gap: .82em;
  align-items: start;
  min-width: 0;
  padding: .92em 1em;
  border: 1px solid var(--hb-line);
  border-radius: 10px;
  background: #fff;
}
.hb-post .hb-number-badge {
  display: inline-flex;
  width: 36px;
  height: 36px;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  background: var(--hb-blue-soft);
  color: var(--hb-blue);
  font-weight: 900;
}
.hb-post .hb-number-item p { margin: 0; }
.hb-post .hb-number-item strong { display: block; margin-bottom: .18em; }
.hb-post .hb-table-wrap { margin: 1.1em 0 1.4em; overflow-x: auto; border: 1px solid var(--hb-line); border-radius: 10px; -webkit-overflow-scrolling: touch; }
.hb-post table { width: 100%; min-width: 610px; border-collapse: collapse; background: #fff; font-size: .93em; }
.hb-post th,
.hb-post td { padding: .76em .8em; border-bottom: 1px solid var(--hb-line); text-align: left; vertical-align: top; }
.hb-post th { background: #f6f8fc; color: #344054; font-size: .9em; }
.hb-post tr:last-child td { border-bottom: 0; }
.hb-post .hb-step { color: var(--hb-muted); font-weight: 800; white-space: nowrap; }
.hb-post .hb-result-hit { color: var(--hb-green); font-weight: 900; }
.hb-post .hb-result-miss { color: var(--hb-red); font-weight: 900; }
.hb-post .hb-memory-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .72em; margin: 1.1em 0; }
.hb-post .hb-memory-card { min-width: 0; padding: .95em; border: 1px solid #dce6f5; border-radius: 10px; background: #fbfdff; }
.hb-post .hb-memory-card strong { display: block; margin-bottom: .26em; color: #1d3c86; }
.hb-post .hb-memory-card p { margin-bottom: 0; font-size: .94em; }
.hb-post .hb-quiz-grid { display: grid; gap: .72em; margin: 1.05em 0; }
.hb-post .hb-quiz { padding: .92em 1em; border: 1px solid var(--hb-line); border-radius: 10px; background: #fff; }
.hb-post .hb-quiz strong { display: block; margin-bottom: .2em; }
.hb-post details { margin: 1em 0; padding: .95em 1em; border: 1px solid #d9e3f2; border-radius: 10px; background: #fafcff; }
.hb-post summary { cursor: pointer; color: #264da9; font-weight: 900; }
.hb-post .hb-footer-note { color: var(--hb-muted); font-size: .94em; }
@media (max-width: 560px) {
  .hb-post { font-size: 16px; }
  .hb-post .hb-hero { padding: 1.2em; }
  .hb-post .hb-card-grid,
  .hb-post .hb-memory-grid { grid-template-columns: 1fr; }
  .hb-post .hb-number-item { grid-template-columns: 34px minmax(0, 1fr); gap: .7em; padding: .85em; }
  .hb-post .hb-number-badge { width: 32px; height: 32px; border-radius: 9px; }
}
&lt;/style&gt;

&lt;article class=&quot;hb-post hb-jeongcheogi-note&quot;&gt;
  &lt;header class=&quot;hb-hero&quot;&gt;
    &lt;span class=&quot;hb-eyebrow&quot;&gt;정보처리기사 필기 · 운영체제 초보자용&lt;/span&gt;
    &lt;h1&gt;운영체제 질문 18개를 5개 개념으로 정리하기&lt;/h1&gt;
    &lt;p class=&quot;hb-lead&quot;&gt;FIFO, LRU, LFU를 외웠는데 계산이 막히고, 스레드·스케줄링·리눅스 명령어가 한꺼번에 섞일 때 보는 정리입니다. 먼저 비유로 감을 잡고, 바로 시험에서 쓰는 기준으로 연결합니다.&lt;/p&gt;
    &lt;p class=&quot;hb-hero-foot&quot;&gt;범위: 페이지 교체 · 메모리 관리 · 스레드 · CPU 스케줄링 · Linux/Unix 명령어&lt;/p&gt;
  &lt;/header&gt;

  &lt;section id=&quot;hb-study-scope&quot;&gt;
    &lt;h2&gt;이 글을 읽기 전에&lt;/h2&gt;
    &lt;div class=&quot;hb-card-grid&quot;&gt;
      &lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;대상&lt;/span&gt;&lt;strong&gt;운영체제를 처음 정리하는 정처기 수험생&lt;/strong&gt;&lt;/div&gt;
      &lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;목표&lt;/span&gt;&lt;strong&gt;용어를 보고 어떤 규칙인지 구분하기&lt;/strong&gt;&lt;/div&gt;
      &lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;핵심 습관&lt;/span&gt;&lt;strong&gt;매 단계마다 메모리 상태를 적기&lt;/strong&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;aside class=&quot;hb-source-note&quot;&gt;
      &lt;strong&gt;이 글의 정리 방식&lt;/strong&gt;
      &lt;p&gt;원문에 있던 18개의 질문을 빠짐없이 주제별로 묶었습니다. 같은 FIFO·LRU·LFU 예제가 여러 번 반복된 부분은 한 번의 계산표로 합쳤고, 깨진 수식과 실제로 없는 시뮬레이터 언급은 학습용 설명으로 바로잡았습니다.&lt;/p&gt;
    &lt;/aside&gt;
    &lt;aside class=&quot;hb-callout&quot;&gt;
      &lt;strong&gt;가장 먼저 구분할 두 상황&lt;/strong&gt;
      &lt;p&gt;&lt;code&gt;페이지 교체&lt;/code&gt;는 메모리가 꽉 찼을 때 무엇을 내보낼지 정하는 규칙이고, &lt;code&gt;CPU 스케줄링&lt;/code&gt;은 CPU를 누구에게 먼저 줄지 정하는 규칙입니다. 둘 다 FIFO라는 말을 쓰지만 계산 대상이 다릅니다.&lt;/p&gt;
    &lt;/aside&gt;
  &lt;/section&gt;

  &lt;section id=&quot;hb-beginner-explanation&quot;&gt;
    &lt;h2&gt;핵심 개념 이해하기&lt;/h2&gt;

    &lt;h3&gt;1. 페이지 교체: FIFO · LRU · LFU&lt;/h3&gt;
    &lt;div class=&quot;hb-number-list&quot;&gt;
      &lt;div class=&quot;hb-number-item&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;&lt;div&gt;&lt;strong&gt;FIFO: 가장 먼저 들어온 페이지를 교체&lt;/strong&gt;&lt;p&gt;줄 서기처럼 먼저 메모리에 들어온 페이지가 먼저 나갑니다. 최근에 다시 사용했는지는 따지지 않습니다.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
      &lt;div class=&quot;hb-number-item&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;&lt;div&gt;&lt;strong&gt;LRU: 가장 오래 사용하지 않은 페이지를 교체&lt;/strong&gt;&lt;p&gt;마지막으로 사용한 시점을 봅니다. 그래서 &lt;em&gt;Hit&lt;/em&gt;가 나도 그 페이지는 “방금 사용함”으로 순서를 갱신해야 합니다.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
      &lt;div class=&quot;hb-number-item&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;3&lt;/span&gt;&lt;div&gt;&lt;strong&gt;LFU: 사용 횟수가 가장 적은 페이지를 교체&lt;/strong&gt;&lt;p&gt;마지막 사용 시점이 아니라 누적 사용 횟수를 봅니다. 횟수가 같으면 문제에서 준 동점 규칙을 따르고, 규칙이 없으면 보통 FIFO 같은 보조 규칙을 명시해야 합니다.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
    &lt;/div&gt;

    &lt;h3&gt;2. 메모리 관리: 페이지 부재 · 워킹 세트 · PFF&lt;/h3&gt;
    &lt;p&gt;&lt;strong&gt;페이지 부재(Page Fault)&lt;/strong&gt;는 필요한 페이지가 메모리에 없어 저장장치에서 다시 가져와야 하는 상황입니다. &lt;strong&gt;Hit&lt;/strong&gt;는 이미 메모리에 있어 바로 사용할 수 있는 상황입니다.&lt;/p&gt;
    &lt;div class=&quot;hb-memory-grid&quot;&gt;
      &lt;div class=&quot;hb-memory-card&quot;&gt;&lt;strong&gt;워킹 세트&lt;/strong&gt;&lt;p&gt;최근 일정 시간 동안 자주 쓴 페이지의 묶음입니다. “지금 책상 위에 꼭 필요한 책 세트”라고 생각하면 됩니다.&lt;/p&gt;&lt;/div&gt;
      &lt;div class=&quot;hb-memory-card&quot;&gt;&lt;strong&gt;PFF(페이지 부재 빈도)&lt;/strong&gt;&lt;p&gt;부재가 너무 자주 나면 프레임을 늘리고, 너무 적게 나면 남는 프레임을 회수하는 조절 방식입니다.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;

    &lt;h3&gt;3. 스레드와 CPU 스케줄링&lt;/h3&gt;
    &lt;p&gt;사용자 수준 스레드가 하나 막히면 모두 멈춘다는 설명은 &lt;strong&gt;다대일(Many-to-One) 모델&lt;/strong&gt;에서의 이야기입니다. 커널이 여러 사용자 스레드를 하나의 커널 스레드로만 보기 때문에, 그 통로가 I/O 등으로 블록되면 다른 사용자 스레드도 실행할 수 없습니다.&lt;/p&gt;
    &lt;p&gt;CPU 스케줄링은 “CPU라는 한 자리”를 누구에게 줄지 정합니다. &lt;strong&gt;선점형&lt;/strong&gt;은 더 급한 작업이 오면 현재 작업에서 CPU를 빼앗을 수 있고, 대표적으로 RR·SRT·다단계 큐·다단계 피드백 큐가 있습니다.&lt;/p&gt;

    &lt;h3&gt;4. Linux/Unix 명령어&lt;/h3&gt;
    &lt;p&gt;명령어는 기능의 범위를 기준으로 구분하면 덜 헷갈립니다. &lt;code&gt;df&lt;/code&gt;는 파일 시스템 전체의 여유 공간, &lt;code&gt;du&lt;/code&gt;는 특정 파일·디렉터리의 사용량, &lt;code&gt;uname -r&lt;/code&gt;은 커널의 릴리즈 버전을 확인합니다.&lt;/p&gt;

    &lt;h3&gt;5. 페이지 크기가 작아지면&lt;/h3&gt;
    &lt;p&gt;페이지가 작아지면 한 페이지의 남는 공간이 줄어 &lt;strong&gt;내부 단편화는 감소&lt;/strong&gt;합니다. 대신 같은 프로그램을 더 많은 페이지로 나누므로 &lt;strong&gt;페이지 테이블은 커집니다&lt;/strong&gt;. 시험에서는 “작은 페이지 → 내부 단편화 감소, 페이지 테이블 증가”를 가장 먼저 잡으면 됩니다.&lt;/p&gt;

    &lt;aside class=&quot;hb-warning&quot;&gt;
      &lt;strong&gt;원문에서 특히 바로잡을 부분&lt;/strong&gt;
      &lt;p&gt;FCFS 평균 대기 시간은 &lt;code&gt;(0 + 2 + 3) / 3 = 1.67&lt;/code&gt;입니다. 또 LFU에서 페이지 4를 교체해 페이지 5를 넣었다면, 현재 프레임의 빈도표에서는 페이지 4를 지워야 합니다.&lt;/p&gt;
    &lt;/aside&gt;
  &lt;/section&gt;

  &lt;section id=&quot;hb-code-trace&quot;&gt;
    &lt;h2&gt;예제로 단계별 따라가기&lt;/h2&gt;

    &lt;h3&gt;예제 1. FIFO 페이지 교체: 페이지 부재는 왜 6회일까?&lt;/h3&gt;
    &lt;p&gt;프레임이 3개이고 참조열이 &lt;code&gt;1, 2, 1, 0, 4, 1, 3&lt;/code&gt;일 때입니다. 빈 프레임도 “메모리에 없어서 가져온 것”이므로 페이지 부재로 셉니다.&lt;/p&gt;
    &lt;div class=&quot;hb-table-wrap&quot;&gt;
      &lt;table&gt;
        &lt;thead&gt;&lt;tr&gt;&lt;th&gt;참조&lt;/th&gt;&lt;th&gt;프레임 상태&lt;/th&gt;&lt;th&gt;판정&lt;/th&gt;&lt;th&gt;누적 부재&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
        &lt;tbody&gt;
          &lt;tr&gt;&lt;td class=&quot;hb-step&quot;&gt;1&lt;/td&gt;&lt;td&gt;[1]&lt;/td&gt;&lt;td class=&quot;hb-result-miss&quot;&gt;Miss&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td class=&quot;hb-step&quot;&gt;2&lt;/td&gt;&lt;td&gt;[1, 2]&lt;/td&gt;&lt;td class=&quot;hb-result-miss&quot;&gt;Miss&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td class=&quot;hb-step&quot;&gt;1&lt;/td&gt;&lt;td&gt;[1, 2]&lt;/td&gt;&lt;td class=&quot;hb-result-hit&quot;&gt;Hit&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td class=&quot;hb-step&quot;&gt;0&lt;/td&gt;&lt;td&gt;[1, 2, 0]&lt;/td&gt;&lt;td class=&quot;hb-result-miss&quot;&gt;Miss&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td class=&quot;hb-step&quot;&gt;4&lt;/td&gt;&lt;td&gt;[4, 2, 0] · 1 교체&lt;/td&gt;&lt;td class=&quot;hb-result-miss&quot;&gt;Miss&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td class=&quot;hb-step&quot;&gt;1&lt;/td&gt;&lt;td&gt;[4, 1, 0] · 2 교체&lt;/td&gt;&lt;td class=&quot;hb-result-miss&quot;&gt;Miss&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td class=&quot;hb-step&quot;&gt;3&lt;/td&gt;&lt;td&gt;[4, 1, 3] · 0 교체&lt;/td&gt;&lt;td class=&quot;hb-result-miss&quot;&gt;Miss&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;/tr&gt;
        &lt;/tbody&gt;
      &lt;/table&gt;
    &lt;/div&gt;
    &lt;aside class=&quot;hb-correct&quot;&gt;
      &lt;strong&gt;풀이 기준&lt;/strong&gt;
      &lt;p&gt;FIFO는 &lt;em&gt;현재 가장 오래 메모리에 있던 페이지&lt;/em&gt;만 찾으면 됩니다. 1을 다시 참조해 Hit가 나도 FIFO의 교체 순서는 바뀌지 않습니다. 이 점이 LRU와의 핵심 차이입니다.&lt;/p&gt;
    &lt;/aside&gt;

    &lt;h3&gt;예제 2. LRU: 페이지 부재가 5회인 이유&lt;/h3&gt;
    &lt;p&gt;프레임 3개, 참조열 &lt;code&gt;7, 0, 1, 2, 0, 3&lt;/code&gt;을 보겠습니다. 5번째 참조인 0은 이미 프레임에 있으므로 Hit입니다. 다만 LRU에서는 0을 가장 최근 사용 페이지로 옮겨야 합니다.&lt;/p&gt;
    &lt;div class=&quot;hb-table-wrap&quot;&gt;
      &lt;table&gt;
        &lt;thead&gt;&lt;tr&gt;&lt;th&gt;순서&lt;/th&gt;&lt;th&gt;참조&lt;/th&gt;&lt;th&gt;최근 사용 순서&lt;br&gt;(오래됨 → 최신)&lt;/th&gt;&lt;th&gt;결과&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
        &lt;tbody&gt;
          &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;td class=&quot;hb-result-miss&quot;&gt;Miss 1&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;7, 0&lt;/td&gt;&lt;td class=&quot;hb-result-miss&quot;&gt;Miss 2&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;7, 0, 1&lt;/td&gt;&lt;td class=&quot;hb-result-miss&quot;&gt;Miss 3&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;0, 1, 2 · 7 교체&lt;/td&gt;&lt;td class=&quot;hb-result-miss&quot;&gt;Miss 4&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;1, 2, 0 · 순서만 갱신&lt;/td&gt;&lt;td class=&quot;hb-result-hit&quot;&gt;Hit&lt;/td&gt;&lt;/tr&gt;
          &lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;2, 0, 3 · 1 교체&lt;/td&gt;&lt;td class=&quot;hb-result-miss&quot;&gt;Miss 5&lt;/td&gt;&lt;/tr&gt;
        &lt;/tbody&gt;
      &lt;/table&gt;
    &lt;/div&gt;

    &lt;h3&gt;예제 3. FCFS(FIFO) 스케줄링: 평균 대기 시간&lt;/h3&gt;
    &lt;p&gt;프로세스가 &lt;code&gt;P1(도착 0, 실행 3)&lt;/code&gt;, &lt;code&gt;P2(도착 1, 실행 2)&lt;/code&gt;, &lt;code&gt;P3(도착 2, 실행 1)&lt;/code&gt; 순서로 도착하면 처리 순서는 P1 → P2 → P3입니다.&lt;/p&gt;
    &lt;div class=&quot;hb-number-list&quot;&gt;
      &lt;div class=&quot;hb-number-item&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;&lt;div&gt;&lt;strong&gt;P1의 대기 시간&lt;/strong&gt;&lt;p&gt;도착하자마자 시작하므로 &lt;code&gt;0&lt;/code&gt;입니다.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
      &lt;div class=&quot;hb-number-item&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;&lt;div&gt;&lt;strong&gt;P2의 대기 시간&lt;/strong&gt;&lt;p&gt;P1이 3에 끝난 뒤 시작하므로 &lt;code&gt;3 - 1 = 2&lt;/code&gt;입니다.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
      &lt;div class=&quot;hb-number-item&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;3&lt;/span&gt;&lt;div&gt;&lt;strong&gt;P3의 대기 시간&lt;/strong&gt;&lt;p&gt;P1과 P2가 끝나는 5에 시작하므로 &lt;code&gt;5 - 2 = 3&lt;/code&gt;입니다. 평균은 &lt;code&gt;(0 + 2 + 3) / 3 = 1.67&lt;/code&gt;입니다.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section id=&quot;hb-mini-quiz&quot;&gt;
    &lt;h2&gt;시험에 적용하고 바로 복습하기&lt;/h2&gt;

    &lt;h3&gt;기출형 재구성 예제&lt;/h3&gt;
    &lt;aside class=&quot;hb-callout&quot;&gt;
      &lt;strong&gt;문제&lt;/strong&gt;
      &lt;p&gt;다단계 큐와 다단계 피드백 큐의 차이로 옳은 것은 무엇일까요? “큐 사이 이동 가능 여부”만으로 답을 골라 보세요.&lt;/p&gt;
    &lt;/aside&gt;
    &lt;div class=&quot;hb-number-list&quot;&gt;
      &lt;div class=&quot;hb-number-item&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;A&lt;/span&gt;&lt;div&gt;&lt;strong&gt;다단계 큐&lt;/strong&gt;&lt;p&gt;한 번 배정된 큐에서 다른 큐로 이동하지 않습니다. 낮은 우선순위 큐가 오래 굶을 수 있습니다.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
      &lt;div class=&quot;hb-number-item&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;B&lt;/span&gt;&lt;div&gt;&lt;strong&gt;다단계 피드백 큐&lt;/strong&gt;&lt;p&gt;프로세스가 실행 성격과 대기 시간에 따라 큐를 오갈 수 있습니다. 에이징으로 기아 현상을 줄일 수 있습니다.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;aside class=&quot;hb-correct&quot;&gt;
      &lt;strong&gt;정답 기준&lt;/strong&gt;
      &lt;p&gt;“이동 불가”면 다단계 큐, “승격·강등 가능”이면 다단계 피드백 큐입니다. 라운드 로빈은 한 개의 준비 큐에서 시간 할당량만큼 돌아가며 실행한다는 점도 함께 구분합니다.&lt;/p&gt;
    &lt;/aside&gt;

    &lt;h3&gt;시험 직전 암기 카드&lt;/h3&gt;
    &lt;div class=&quot;hb-memory-grid&quot;&gt;
      &lt;div class=&quot;hb-memory-card&quot;&gt;&lt;strong&gt;FIFO vs LRU&lt;/strong&gt;&lt;p&gt;들어온 순서 vs 마지막 사용 순서&lt;/p&gt;&lt;/div&gt;
      &lt;div class=&quot;hb-memory-card&quot;&gt;&lt;strong&gt;페이지 부재&lt;/strong&gt;&lt;p&gt;필요한 페이지가 메모리에 없음&lt;/p&gt;&lt;/div&gt;
      &lt;div class=&quot;hb-memory-card&quot;&gt;&lt;strong&gt;df vs du&lt;/strong&gt;&lt;p&gt;전체 파일 시스템 여유 공간 vs 특정 경로 사용량&lt;/p&gt;&lt;/div&gt;
      &lt;div class=&quot;hb-memory-card&quot;&gt;&lt;strong&gt;uname -r&lt;/strong&gt;&lt;p&gt;커널 릴리즈 버전&lt;/p&gt;&lt;/div&gt;
      &lt;div class=&quot;hb-memory-card&quot;&gt;&lt;strong&gt;작은 페이지&lt;/strong&gt;&lt;p&gt;내부 단편화 감소 · 페이지 테이블 증가&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;

    &lt;h3&gt;미니 퀴즈&lt;/h3&gt;
    &lt;div class=&quot;hb-quiz-grid&quot;&gt;
      &lt;div class=&quot;hb-quiz&quot;&gt;&lt;strong&gt;Q1.&lt;/strong&gt; LRU에서 Hit가 났을 때도 사용 순서를 갱신해야 할까요?&lt;/div&gt;
      &lt;div class=&quot;hb-quiz&quot;&gt;&lt;strong&gt;Q2.&lt;/strong&gt; 사용자 수준 스레드 하나가 블록되면 항상 모든 스레드가 멈출까요?&lt;/div&gt;
      &lt;div class=&quot;hb-quiz&quot;&gt;&lt;strong&gt;Q3.&lt;/strong&gt; &lt;code&gt;du -h&lt;/code&gt;는 어떤 정보를 사람이 읽기 쉬운 단위로 보여줄까요?&lt;/div&gt;
      &lt;div class=&quot;hb-quiz&quot;&gt;&lt;strong&gt;Q4.&lt;/strong&gt; 라운드 로빈의 시간 할당량이 지나치게 크면 어떤 알고리즘과 비슷해질까요?&lt;/div&gt;
    &lt;/div&gt;
    &lt;details&gt;
      &lt;summary&gt;정답과 해설 확인하기&lt;/summary&gt;
      &lt;p&gt;&lt;strong&gt;Q1.&lt;/strong&gt; 네. LRU의 기준이 “최근 사용 시점”이기 때문입니다.&lt;/p&gt;
      &lt;p&gt;&lt;strong&gt;Q2.&lt;/strong&gt; 아닙니다. 대표적으로 다대일 모델에서 발생하는 한계입니다.&lt;/p&gt;
      &lt;p&gt;&lt;strong&gt;Q3.&lt;/strong&gt; 특정 파일 또는 디렉터리의 디스크 사용량입니다.&lt;/p&gt;
      &lt;p&gt;&lt;strong&gt;Q4.&lt;/strong&gt; 먼저 온 작업이 거의 끝날 때까지 실행되므로 FCFS/FIFO와 비슷해집니다.&lt;/p&gt;
    &lt;/details&gt;
  &lt;/section&gt;

  &lt;section id=&quot;hb-closing&quot;&gt;
    &lt;h2&gt;오늘의 회고와 다음 단계&lt;/h2&gt;
    &lt;p&gt;오늘은 “무엇을 교체하는가”, “무엇을 기준으로 순서를 바꾸는가”, “CPU를 누구에게 주는가”를 분리해 보았습니다. 이 세 질문만 분명해도 운영체제 문제의 절반은 정리됩니다.&lt;/p&gt;
    &lt;p&gt;다음에는 참조열을 직접 적어 FIFO·LRU·LFU를 같은 표에 나란히 풀어 보세요. 알고리즘 이름을 외우는 것보다 프레임 상태를 한 칸씩 쓰는 연습이 훨씬 오래 남습니다.&lt;/p&gt;
    &lt;p class=&quot;hb-footer-note&quot;&gt;학습 팁: 계산 문제는 정답부터 보지 말고, 참조할 때마다 프레임·교체 대상·Hit/Miss 세 칸을 먼저 채운 뒤 마지막에 횟수를 세면 실수가 줄어듭니다.&lt;/p&gt;
  &lt;/section&gt;
&lt;/article&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;/p&gt;</description>
      <category>AI/정보처리기사_스터디</category>
      <category>CPU스케줄링</category>
      <category>FIFO</category>
      <category>LFU</category>
      <category>lru</category>
      <category>리눅스명령어</category>
      <category>운영체제</category>
      <category>정보처리기사</category>
      <category>정처기</category>
      <category>페이지교체</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/121</guid>
      <comments>https://onethingflow.tistory.com/entry/Day89%EC%A0%95%EC%B2%98%EA%B8%B0-%ED%95%84%EA%B8%B0%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-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EA%B8%B0%EC%B4%88-%ED%99%9C%EC%9A%A9#entry121comment</comments>
      <pubDate>Tue, 21 Jul 2026 10:40:02 +0900</pubDate>
    </item>
    <item>
      <title>Day 12) 프로그래머스 파이썬 슬라이싱 5문제 풀이</title>
      <link>https://onethingflow.tistory.com/entry/Day-12-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%8A%AC%EB%9D%BC%EC%9D%B4%EC%8B%B1-5%EB%AC%B8%EC%A0%9C-%ED%92%80%EC%9D%B4</link>
      <description>&lt;!--
Title: Day 12) 프로그래머스 파이썬 슬라이싱 5문제 풀이
Meta description: 프로그래머스 코딩 기초 트레이닝 Day 12의 리스트 자르기, 첫 번째로 나오는 음수, 배열 만들기 3, 2의 영역, 배열 조각하기를 파이썬으로 풀이합니다. 직접 작성한 코드의 실수와 수정 과정까지 함께 정리했습니다.
Tags: 프로그래머스, 코딩테스트, 파이썬, Day12, 슬라이싱, 리스트자르기, 첫번째음수, 배열만들기3, 2의영역, 배열조각하기
--&gt;

&lt;article class=&quot;hb-post hb-day12-slicing&quot;&gt;
  &lt;style&gt;
    .hb-day12-slicing {
      --hb-ink: #172033;
      --hb-muted: #5d687a;
      --hb-line: #dbe2ea;
      --hb-soft: #f5f7fb;
      --hb-blue: #2457c5;
      --hb-blue-soft: #eef4ff;
      --hb-green: #087f5b;
      --hb-green-soft: #edf9f4;
      --hb-orange: #c2410c;
      --hb-orange-soft: #fff7ed;
      max-width: 860px;
      margin: 0 auto;
      color: var(--hb-ink);
      font-size: 17px;
      line-height: 1.8;
      word-break: keep-all;
    }

    .hb-day12-slicing * { box-sizing: border-box; }

    .hb-day12-slicing code,
    .hb-post code { overflow-wrap: anywhere; }

    .hb-day12-slicing .hb-hero {
      margin-bottom: 34px;
      padding: 32px 28px;
      color: #fff;
      background: #172554;
      border-radius: 8px;
    }

    .hb-day12-slicing .hb-kicker {
      margin: 0 0 8px;
      color: #bfdbfe;
      font-size: 14px;
      font-weight: 800;
    }

    .hb-day12-slicing h1 {
      margin: 0;
      color: #fff;
      font-size: 33px;
      line-height: 1.35;
      letter-spacing: 0;
    }

    .hb-day12-slicing .hb-lead {
      margin: 14px 0 0;
      color: #e7edff;
      font-size: 18px;
    }

    .hb-day12-slicing h2 {
      margin: 52px 0 16px;
      padding-bottom: 10px;
      color: #111827;
      font-size: 27px;
      line-height: 1.4;
      letter-spacing: 0;
      border-bottom: 2px solid var(--hb-line);
    }

    .hb-day12-slicing h3 {
      margin: 29px 0 10px;
      color: #1e3a8a;
      font-size: 20px;
      line-height: 1.5;
      letter-spacing: 0;
    }

    .hb-day12-slicing p { margin: 10px 0; }

    .hb-day12-slicing a {
      color: #1d4ed8;
      text-decoration-thickness: 1px;
      text-underline-offset: 3px;
    }

    .hb-day12-slicing p code,
    .hb-day12-slicing li code,
    .hb-day12-slicing td code {
      padding: 2px 6px;
      color: #9f1239;
      background: #fff1f2;
      border-radius: 4px;
      font-size: 0.92em;
    }

    .hb-day12-slicing pre {
      margin: 14px 0 20px;
      padding: 19px;
      overflow-x: auto;
      color: #e5e7eb;
      background: #111827;
      border: 1px solid #273449;
      border-radius: 8px;
      line-height: 1.65;
      tab-size: 4;
    }

    .hb-day12-slicing pre code {
      padding: 0;
      color: inherit;
      background: transparent;
      font-size: 14px;
      white-space: pre;
      overflow-wrap: normal;
    }

    .hb-day12-slicing .hb-summary,
    .hb-day12-slicing .hb-note,
    .hb-day12-slicing .hb-warning {
      margin: 20px 0;
      padding: 17px 19px;
      border-radius: 8px;
    }

    .hb-day12-slicing .hb-summary {
      background: var(--hb-blue-soft);
      border-left: 4px solid var(--hb-blue);
    }

    .hb-day12-slicing .hb-note {
      background: var(--hb-green-soft);
      border-left: 4px solid var(--hb-green);
    }

    .hb-day12-slicing .hb-warning {
      background: var(--hb-orange-soft);
      border-left: 4px solid var(--hb-orange);
    }

    .hb-day12-slicing .hb-summary strong,
    .hb-day12-slicing .hb-note strong,
    .hb-day12-slicing .hb-warning strong {
      display: block;
      margin-bottom: 4px;
    }

    .hb-day12-slicing .hb-table-wrap {
      width: 100%;
      margin: 16px 0 24px;
      overflow-x: auto;
      border: 1px solid var(--hb-line);
      border-radius: 8px;
    }

    .hb-day12-slicing table {
      width: 100%;
      min-width: 680px;
      border-collapse: collapse;
      font-size: 15px;
    }

    .hb-day12-slicing caption {
      padding: 12px 14px;
      color: #334155;
      background: var(--hb-soft);
      font-weight: 800;
      text-align: left;
    }

    .hb-day12-slicing th,
    .hb-day12-slicing td {
      padding: 12px 14px;
      text-align: left;
      vertical-align: top;
      border-bottom: 1px solid var(--hb-line);
    }

    .hb-day12-slicing th {
      color: #334155;
      background: #f8fafc;
    }

    .hb-day12-slicing tbody tr:last-child td { border-bottom: 0; }

    .hb-day12-slicing .hb-steps {
      display: grid;
      gap: 12px;
      margin: 17px 0 24px;
    }

    .hb-day12-slicing .hb-step {
      display: grid;
      grid-template-columns: 34px minmax(0, 1fr);
      gap: 12px;
      align-items: start;
      padding: 15px 16px;
      background: #fff;
      border: 1px solid var(--hb-line);
      border-radius: 8px;
    }

    .hb-day12-slicing .hb-step-number {
      display: inline-flex;
      width: 30px;
      height: 30px;
      align-items: center;
      justify-content: center;
      color: #fff;
      background: var(--hb-blue);
      border-radius: 6px;
      font-size: 14px;
      font-weight: 900;
      line-height: 1;
    }

    .hb-day12-slicing .hb-step-title {
      display: block;
      margin-bottom: 3px;
      font-weight: 800;
    }

    .hb-day12-slicing .hb-checklist {
      margin: 15px 0;
      padding: 0;
      list-style: none;
    }

    .hb-day12-slicing .hb-checklist li {
      position: relative;
      margin: 9px 0;
      padding-left: 29px;
    }

    .hb-day12-slicing .hb-checklist li::before {
      position: absolute;
      top: 1px;
      left: 0;
      content: &quot;✓&quot;;
      color: var(--hb-green);
      font-weight: 900;
    }

    .hb-day12-slicing .hb-closing {
      margin-top: 48px;
      padding: 23px;
      background: var(--hb-soft);
      border-top: 3px solid var(--hb-blue);
      border-radius: 8px;
    }

    @media (max-width: 640px) {
      .hb-day12-slicing {
        font-size: 16px;
        line-height: 1.76;
        word-break: normal;
      }

      .hb-day12-slicing .hb-hero { padding: 26px 20px; }
      .hb-day12-slicing h1 { font-size: 27px; }
      .hb-day12-slicing h2 { margin-top: 44px; font-size: 23px; }
      .hb-day12-slicing h3 { font-size: 19px; }
      .hb-day12-slicing pre { padding: 16px; }

      .hb-day12-slicing .hb-step {
        grid-template-columns: 30px minmax(0, 1fr);
        gap: 10px;
        padding: 14px;
      }
    }
  &lt;/style&gt;

  &lt;header class=&quot;hb-hero&quot;&gt;
    &lt;p class=&quot;hb-kicker&quot;&gt;Programmers Coding Test · Day 12 · Python&lt;/p&gt;
    &lt;h1&gt;파이썬 슬라이싱 5문제 풀이&lt;/h1&gt;
    &lt;p class=&quot;hb-lead&quot;&gt;끝 인덱스를 포함하는 방법부터 누적 슬라이싱, 첫 위치와 마지막 위치 찾기까지 직접 작성한 코드의 수정 과정을 정리했다.&lt;/p&gt;
  &lt;/header&gt;

  &lt;p&gt;Day 12 문제들은 모두 배열을 자르는 문법을 사용하지만, 단순히 &lt;code&gt;[시작:끝]&lt;/code&gt;만 외워서는 풀기 어려웠다. &lt;strong&gt;끝 인덱스는 포함되지 않는다는 점&lt;/strong&gt;, &lt;strong&gt;현재 값과 반복 순서의 차이&lt;/strong&gt;, &lt;strong&gt;이전 작업 결과를 다음 작업에 반영해야 하는지&lt;/strong&gt;를 함께 판단해야 했다.&lt;/p&gt;

  &lt;div class=&quot;hb-summary&quot;&gt;
    &lt;strong&gt;오늘의 핵심 문법&lt;/strong&gt;
    슬라이싱은 &lt;code&gt;리스트[시작:끝:간격]&lt;/code&gt; 형태로 사용한다. 닫힌 구간처럼 마지막 위치까지 포함해야 한다면 끝값에 1을 더하고, 연속 작업이라면 자른 결과를 원본 변수에 다시 저장해야 한다.
  &lt;/div&gt;

  &lt;h2&gt;Day 12 문제와 공식 링크&lt;/h2&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;프로그래머스 코딩 기초 트레이닝 Day 12&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;&lt;th scope=&quot;col&quot;&gt;순서&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;문제&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;핵심 개념&lt;/th&gt;&lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181897&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;리스트 자르기&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[시작:끝:간격]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181896&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;첫 번째로 나오는 음수&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;return&lt;/code&gt;, &lt;code&gt;enumerate()&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181895&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;배열 만들기 3&lt;/a&gt;&lt;/td&gt;&lt;td&gt;닫힌 구간, 리스트 연결&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181894&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2의 영역&lt;/a&gt;&lt;/td&gt;&lt;td&gt;첫 위치와 마지막 위치&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181893&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;배열 조각하기&lt;/a&gt;&lt;/td&gt;&lt;td&gt;인덱스와 값, 누적 갱신&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;1. 리스트 자르기&lt;/h2&gt;

  &lt;p&gt;&lt;code&gt;slicer&lt;/code&gt;의 세 값을 &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, &lt;code&gt;c&lt;/code&gt;라고 할 때, &lt;code&gt;n&lt;/code&gt;에 따라 시작점과 끝점, 간격을 다르게 적용하는 문제다.&lt;/p&gt;

  &lt;h3&gt;내가 작성한 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(n, slicer, num_list):
    a, b, c = slicer
    b += 1

    if n == 1:
        return num_list[0:b]
    if n == 2:
        return num_list[a:]
    if n == 3:
        return num_list[a:b]
    if n == 4:
        return num_list[a:b:c]&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;이 풀이는 그대로 정답이다. &lt;code&gt;a, b, c = slicer&lt;/code&gt;로 세 값을 한 번에 꺼냈고, 모든 경우에서 &lt;code&gt;b&lt;/code&gt;번 인덱스까지 포함해야 하므로 공통으로 &lt;code&gt;b += 1&lt;/code&gt;을 먼저 적용했다.&lt;/p&gt;

  &lt;div class=&quot;hb-steps&quot;&gt;
    &lt;div class=&quot;hb-step&quot;&gt;&lt;span class=&quot;hb-step-number&quot;&gt;1&lt;/span&gt;&lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;&lt;code&gt;n = 1&lt;/code&gt;&lt;/span&gt;처음부터 b번 인덱스까지이므로 &lt;code&gt;num_list[:b + 1]&lt;/code&gt;과 같다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-step&quot;&gt;&lt;span class=&quot;hb-step-number&quot;&gt;2&lt;/span&gt;&lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;&lt;code&gt;n = 2&lt;/code&gt;&lt;/span&gt;a번 인덱스부터 끝까지이므로 &lt;code&gt;num_list[a:]&lt;/code&gt;를 사용한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-step&quot;&gt;&lt;span class=&quot;hb-step-number&quot;&gt;3&lt;/span&gt;&lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;&lt;code&gt;n = 3&lt;/code&gt;&lt;/span&gt;a부터 b까지 포함하므로 &lt;code&gt;num_list[a:b + 1]&lt;/code&gt;이다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-step&quot;&gt;&lt;span class=&quot;hb-step-number&quot;&gt;4&lt;/span&gt;&lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;&lt;code&gt;n = 4&lt;/code&gt;&lt;/span&gt;a부터 b까지 c 간격으로 선택하므로 &lt;code&gt;num_list[a:b + 1:c]&lt;/code&gt;다.&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;h3&gt;공통 계산을 더 분명하게 쓴 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(n, slicer, num_list):
    a, b, c = slicer
    end = b + 1

    if n == 1:
        return num_list[:end]
    if n == 2:
        return num_list[a:]
    if n == 3:
        return num_list[a:end]
    return num_list[a:end:c]&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;b&lt;/code&gt; 자체를 바꾸는 대신 &lt;code&gt;end&lt;/code&gt;라는 이름을 사용하면, 슬라이싱에서 제외되는 끝 위치를 저장했다는 의미가 더 분명하다. &lt;code&gt;n&lt;/code&gt;은 1부터 4 중 하나이므로 앞의 세 조건이 아니면 마지막 경우는 자동으로 &lt;code&gt;n = 4&lt;/code&gt;다.&lt;/p&gt;

  &lt;h2&gt;2. 첫 번째로 나오는 음수&lt;/h2&gt;

  &lt;p&gt;리스트를 앞에서부터 확인해 처음 만난 음수의 인덱스를 반환하고, 음수가 하나도 없다면 -1을 반환하는 문제다.&lt;/p&gt;

  &lt;h3&gt;처음 작성한 코드&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(num_list):
    ans = 0

    for i in range(len(num_list)):
        if num_list[i] &amp;gt; 0:
            ans = -1
        elif num_list[i] &amp;lt; 0:
            ans = i

    return ans&lt;/code&gt;&lt;/pre&gt;

  &lt;div class=&quot;hb-warning&quot;&gt;
    &lt;strong&gt;문제점: 찾은 정답이 계속 덮어써진다&lt;/strong&gt;
    음수를 찾은 뒤에도 반복문이 끝까지 진행된다. 뒤에서 양수를 만나면 -1로 바뀌고, 다른 음수를 만나면 더 뒤의 인덱스로 바뀐다. 문제에서 필요한 값은 마지막 음수가 아니라 첫 번째 음수의 위치다. 모든 값이 0일 때 초기값 0이 그대로 반환되는 문제도 있다.
  &lt;/div&gt;

  &lt;h3&gt;두 번째 시도와 너무 이른 반환&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(num_list):
    for i in range(len(num_list)):
        if num_list[i] &amp;gt; 0:
            return -1
        elif num_list[i] &amp;lt; 0:
            return i&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;음수를 발견했을 때 즉시 반환하는 방향은 맞다. 하지만 첫 번째 값이 양수라는 이유만으로 -1을 반환하면 뒤에 있는 음수를 확인하지 못한다. -1은 리스트 전체를 확인한 뒤에도 음수가 없을 때만 반환해야 한다.&lt;/p&gt;

  &lt;h3&gt;수정한 기본 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(num_list):
    for i in range(len(num_list)):
        if num_list[i] &amp;lt; 0:
            return i

    return -1&lt;/code&gt;&lt;/pre&gt;

  &lt;h3&gt;더 읽기 쉬운 enumerate() 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(num_list):
    for i, num in enumerate(num_list):
        if num &amp;lt; 0:
            return i

    return -1&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;enumerate()&lt;/code&gt;는 인덱스와 값을 동시에 꺼낸다. &lt;code&gt;num_list[i]&lt;/code&gt;로 다시 접근하지 않아도 되어 현재 값과 위치의 역할이 명확하다.&lt;/p&gt;

  &lt;h3&gt;한 줄로 표현한 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(num_list):
    return next((i for i, num in enumerate(num_list) if num &amp;lt; 0), -1)&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;next()&lt;/code&gt;는 조건을 만족하는 첫 번째 인덱스를 반환한다. 해당 값이 없을 때 사용할 기본값으로 -1을 지정했다. 처음 배우는 단계에서는 반복문 풀이가 흐름을 확인하기 더 쉽다.&lt;/p&gt;

  &lt;h2&gt;3. 배열 만들기 3&lt;/h2&gt;

  &lt;p&gt;두 개의 닫힌 구간을 각각 잘라 앞뒤로 이어 붙이는 문제다. 닫힌 구간은 시작점과 끝점을 모두 포함한다.&lt;/p&gt;

  &lt;h3&gt;내가 작성한 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(arr, intervals):
    answer = []

    for a, b in intervals:
        answer += arr[a:b + 1]

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;이 코드도 정답이다. 구간의 두 값을 &lt;code&gt;a&lt;/code&gt;와 &lt;code&gt;b&lt;/code&gt;로 바로 언패킹했고, b번 인덱스까지 포함하기 위해 &lt;code&gt;b + 1&lt;/code&gt;을 사용했다. 슬라이싱 결과는 리스트이므로 &lt;code&gt;+=&lt;/code&gt;로 결과 리스트 뒤에 이어 붙일 수 있다.&lt;/p&gt;

  &lt;div class=&quot;hb-note&quot;&gt;
    &lt;strong&gt;리스트의 +는 원소별 덧셈이 아니다&lt;/strong&gt;
    기본 리스트에서 &lt;code&gt;[1, 2, 3] + [4, 5, 6]&lt;/code&gt;의 결과는 &lt;code&gt;[5, 7, 9]&lt;/code&gt;가 아니라 &lt;code&gt;[1, 2, 3, 4, 5, 6]&lt;/code&gt;이다. 두 리스트를 순서대로 연결하기 때문에 이 문제에 사용할 수 있다.
  &lt;/div&gt;

  &lt;h3&gt;구간이 두 개라는 조건을 그대로 사용한 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(arr, intervals):
    (s1, e1), (s2, e2) = intervals
    return arr[s1:e1 + 1] + arr[s2:e2 + 1]&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;문제에서 구간이 항상 두 개라고 보장하므로 이렇게 한 번에 언패킹할 수도 있다. 반면 처음 작성한 반복문 풀이는 구간 수가 늘어나도 그대로 사용할 수 있다는 장점이 있다.&lt;/p&gt;

  &lt;h3&gt;리스트 컴프리헨션 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(arr, intervals):
    return [num for a, b in intervals for num in arr[a:b + 1]]&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;먼저 구간을 꺼내고, 해당 구간에서 숫자를 하나씩 꺼내 새 리스트에 담는다. 짧지만 반복 순서가 낯설 수 있어 이 문제에서는 원래 작성한 반복문 풀이도 충분히 좋다.&lt;/p&gt;

  &lt;h2&gt;4. 2의 영역&lt;/h2&gt;

  &lt;p&gt;배열에 있는 모든 2를 포함하는 가장 작은 연속 부분 배열을 반환한다. 결국 첫 번째 2의 위치부터 마지막 2의 위치까지 자르면 된다.&lt;/p&gt;

  &lt;h3&gt;처음 생각한 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(arr):
    if arr.count(2) &amp;gt; 1:
        for i, num in enumerate(range(len(arr))):
            for j, num in enumerate(range(i + 1, len(arr))):
                if num == 2:
                    return arr[i:j]
    elif arr.count(2) == 1:
        for k, num in enumerate(range(len(arr))):
            if num == 2:
                return [arr[k]]
    else:
        return [-1]

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;div class=&quot;hb-steps&quot;&gt;
    &lt;div class=&quot;hb-step&quot;&gt;&lt;span class=&quot;hb-step-number&quot;&gt;1&lt;/span&gt;&lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;&lt;code&gt;enumerate(range(...))&lt;/code&gt;의 값&lt;/span&gt;&lt;code&gt;num&lt;/code&gt;에는 arr의 원소가 아니라 0, 1, 2 같은 인덱스 숫자가 들어간다. 배열 값을 함께 꺼내려면 &lt;code&gt;enumerate(arr)&lt;/code&gt;를 사용해야 한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-step&quot;&gt;&lt;span class=&quot;hb-step-number&quot;&gt;2&lt;/span&gt;&lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;두 번째 2에서 멈추면 안 된다&lt;/span&gt;2가 세 개 이상이면 뒤의 2를 포함하지 못한다. 첫 번째 위치와 마지막 위치가 필요하다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-step&quot;&gt;&lt;span class=&quot;hb-step-number&quot;&gt;3&lt;/span&gt;&lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;끝 인덱스가 빠진다&lt;/span&gt;&lt;code&gt;arr[i:j]&lt;/code&gt;는 j번 인덱스를 포함하지 않는다. j까지 포함하려면 &lt;code&gt;j + 1&lt;/code&gt;이 필요하다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-step&quot;&gt;&lt;span class=&quot;hb-step-number&quot;&gt;4&lt;/span&gt;&lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;정의되지 않은 변수&lt;/span&gt;마지막의 &lt;code&gt;return answer&lt;/code&gt;에서 answer를 만든 적이 없으므로 해당 경로에 도달하면 오류가 발생한다.&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;h3&gt;인덱스를 모으는 과정에서 생긴 실수&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(arr):
    num_list = []

    for i, num in enumerate(arr):
        if num == 2:
            num_list.append(i)

    if num_list == []:
        return [-1]
    elif len(num_list) == 1:
        return [arr[num_list[0]]
    elif len(num_list) == 2:
        return [arr[num_list[0]:num_list[1] + 1]]]
    else:
        return [arr[num_list[0]:num_list[-1]]]&lt;/code&gt;&lt;/pre&gt;

  &lt;div class=&quot;hb-warning&quot;&gt;
    &lt;strong&gt;괄호, 중첩 리스트, 끝점 오류&lt;/strong&gt;
    닫는 대괄호의 개수가 맞지 않아 문법 오류가 발생한다. 또한 &lt;code&gt;arr[a:b]&lt;/code&gt;는 이미 리스트인데 다시 대괄호로 감싸면 &lt;code&gt;[[...]]&lt;/code&gt; 형태의 중첩 리스트가 된다. 마지막 2까지 포함하려면 &lt;code&gt;num_list[-1] + 1&lt;/code&gt;도 필요하다.
  &lt;/div&gt;

  &lt;h3&gt;수정한 기본 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(arr):
    indices = []

    for i, num in enumerate(arr):
        if num == 2:
            indices.append(i)

    if not indices:
        return [-1]

    start = indices[0]
    end = indices[-1]
    return arr[start:end + 1]&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;2가 하나뿐이어도 &lt;code&gt;indices[0]&lt;/code&gt;과 &lt;code&gt;indices[-1]&lt;/code&gt;은 같은 위치다. 따라서 별도의 조건 없이 &lt;code&gt;arr[start:start + 1]&lt;/code&gt;이 되어 &lt;code&gt;[2]&lt;/code&gt;를 반환한다.&lt;/p&gt;

  &lt;h3&gt;내가 완성한 짧은 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(arr):
    if 2 not in arr:
        return [-1]

    start = arr.index(2)
    end = len(arr) - arr[::-1].index(2)
    return arr[start:end]&lt;/code&gt;&lt;/pre&gt;

  &lt;div class=&quot;hb-note&quot;&gt;
    &lt;strong&gt;왜 끝점에 따로 +1을 하지 않을까?&lt;/strong&gt;
    배열 길이를 L, 뒤집은 배열에서 마지막 2의 위치를 k라고 하면 원래 인덱스는 &lt;code&gt;L - 1 - k&lt;/code&gt;다. 이 원소까지 포함하는 슬라이싱 끝점은 여기에 1을 더한 &lt;code&gt;L - k&lt;/code&gt;다. 따라서 &lt;code&gt;len(arr) - arr[::-1].index(2)&lt;/code&gt; 자체가 이미 끝 인덱스 다음 위치다.
  &lt;/div&gt;

  &lt;p&gt;마지막 원소가 2라면 뒤집은 배열에서 위치는 0이고 끝점은 &lt;code&gt;len(arr)&lt;/code&gt;가 된다. 슬라이싱에서 &lt;code&gt;arr[:len(arr)]&lt;/code&gt;는 마지막 인덱스 바로 다음까지 자르므로 마지막 원소도 정상적으로 포함한다.&lt;/p&gt;

  &lt;h2&gt;5. 배열 조각하기&lt;/h2&gt;

  &lt;p&gt;&lt;code&gt;query&lt;/code&gt;를 순서대로 처리하면서, 짝수 번째 작업에서는 기준 위치 뒤를 버리고 홀수 번째 작업에서는 기준 위치 앞을 버린다. 매번 남은 배열을 다시 다음 작업의 대상으로 사용한다.&lt;/p&gt;

  &lt;h3&gt;처음 작성한 코드&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(arr, query):
    answer = []

    for i in query:
        n = arr.index(i)

        if i % 2 == 0:
            answer = arr[:n + 1]
        else:
            answer = arr[n:]

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;div class=&quot;hb-steps&quot;&gt;
    &lt;div class=&quot;hb-step&quot;&gt;&lt;span class=&quot;hb-step-number&quot;&gt;1&lt;/span&gt;&lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;짝수·홀수 기준이 다르다&lt;/span&gt;&lt;code&gt;i&lt;/code&gt;는 query의 실제 값이다. 문제는 실제 값이 아니라 query에서 현재 처리 중인 &lt;strong&gt;인덱스&lt;/strong&gt;가 짝수인지 확인해야 한다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-step&quot;&gt;&lt;span class=&quot;hb-step-number&quot;&gt;2&lt;/span&gt;&lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;&lt;code&gt;arr.index(i)&lt;/code&gt;는 필요하지 않다&lt;/span&gt;query의 값은 arr에서 찾을 값이 아니라 배열을 자를 위치 자체다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-step&quot;&gt;&lt;span class=&quot;hb-step-number&quot;&gt;3&lt;/span&gt;&lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;자른 결과를 누적해야 한다&lt;/span&gt;다음 작업은 원본 arr가 아니라 직전 작업에서 남은 배열을 대상으로 한다. 결과를 &lt;code&gt;arr&lt;/code&gt;에 다시 저장해야 한다.&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;h3&gt;두 가지를 수정한 중간 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(arr, query):
    for value in query:
        if value % 2 == 0:
            arr = arr[:value + 1]
        else:
            arr = arr[value:]

    return arr&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;arr.index()&lt;/code&gt;를 제거하고 결과를 arr에 다시 저장한 점은 맞다. 하지만 여전히 query의 값이 짝수인지 검사하고 있다. 예제 &lt;code&gt;[4, 1, 2]&lt;/code&gt;에서는 값의 홀짝과 인덱스의 홀짝이 우연히 같아 보이지만 다른 입력에서는 틀린다.&lt;/p&gt;

  &lt;h3&gt;최종 수정 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(arr, query):
    for index, value in enumerate(query):
        if index % 2 == 0:
            arr = arr[:value + 1]
        else:
            arr = arr[value:]

    return arr&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;index&lt;/code&gt;는 현재 작업 순서의 홀짝을 판단하고, &lt;code&gt;value&lt;/code&gt;는 실제 슬라이싱 위치로 사용한다. 짝수 번째 작업에서는 기준 위치를 남겨야 하므로 &lt;code&gt;value + 1&lt;/code&gt;까지 자르고, 홀수 번째 작업에서도 기준 위치는 남겨야 하므로 &lt;code&gt;arr[value:]&lt;/code&gt;를 사용한다.&lt;/p&gt;

  &lt;div class=&quot;hb-note&quot;&gt;
    &lt;strong&gt;공식 예제 흐름&lt;/strong&gt;
    &lt;code&gt;[0, 1, 2, 3, 4, 5]&lt;/code&gt;에 query &lt;code&gt;[4, 1, 2]&lt;/code&gt;를 적용하면 &lt;code&gt;[0, 1, 2, 3, 4]&lt;/code&gt;, &lt;code&gt;[1, 2, 3, 4]&lt;/code&gt;, &lt;code&gt;[1, 2, 3]&lt;/code&gt; 순서로 배열이 갱신된다.
  &lt;/div&gt;

  &lt;h2&gt;공식 예제로 검산하기&lt;/h2&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;대표 입력과 결과&lt;/caption&gt;
      &lt;thead&gt;&lt;tr&gt;&lt;th scope=&quot;col&quot;&gt;문제&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;대표 입력&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;결과&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td&gt;리스트 자르기&lt;/td&gt;&lt;td&gt;&lt;code&gt;n=4, slicer=[1, 5, 2]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[2, 4, 6]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;첫 번째 음수&lt;/td&gt;&lt;td&gt;&lt;code&gt;[12, 4, 15, 46, 38, -2, 15]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;5&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;배열 만들기 3&lt;/td&gt;&lt;td&gt;&lt;code&gt;[1,2,3,4,5], [[1,3],[0,4]]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[2,3,4,1,2,3,4,5]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;2의 영역&lt;/td&gt;&lt;td&gt;&lt;code&gt;[1,2,1,4,5,2,9]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[2,1,4,5,2]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;배열 조각하기&lt;/td&gt;&lt;td&gt;&lt;code&gt;[0,1,2,3,4,5], [4,1,2]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[1,2,3]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;실수 방지 체크리스트&lt;/h2&gt;

  &lt;ul class=&quot;hb-checklist&quot;&gt;
    &lt;li&gt;슬라이싱의 끝 인덱스는 결과에 포함되지 않는다.&lt;/li&gt;
    &lt;li&gt;닫힌 구간의 끝값까지 필요하면 보통 &lt;code&gt;end + 1&lt;/code&gt;을 사용한다.&lt;/li&gt;
    &lt;li&gt;첫 번째 값을 찾는 문제에서는 발견한 순간 반환할 수 있는지 확인한다.&lt;/li&gt;
    &lt;li&gt;실패 결과는 반복문 안이 아니라 전체 탐색이 끝난 뒤 반환해야 하는 경우가 많다.&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;enumerate(range(...))&lt;/code&gt;와 &lt;code&gt;enumerate(arr)&lt;/code&gt;의 차이를 구분한다.&lt;/li&gt;
    &lt;li&gt;슬라이싱 결과는 이미 리스트이므로 불필요하게 대괄호로 다시 감싸지 않는다.&lt;/li&gt;
    &lt;li&gt;반복문의 변수에 실제 값이 들어오는지, 인덱스가 들어오는지 확인한다.&lt;/li&gt;
    &lt;li&gt;연속 작업은 직전 결과를 다음 작업에 다시 사용해야 하는지 확인한다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h2&gt;같이 보면 좋은 개념&lt;/h2&gt;

  &lt;div class=&quot;hb-steps&quot;&gt;
    &lt;div class=&quot;hb-step&quot;&gt;&lt;span class=&quot;hb-step-number&quot;&gt;1&lt;/span&gt;&lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;언패킹&lt;/span&gt;&lt;code&gt;a, b, c = slicer&lt;/code&gt;처럼 정해진 구조의 값을 이름 있는 변수로 나누면 인덱스 접근을 줄일 수 있다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-step&quot;&gt;&lt;span class=&quot;hb-step-number&quot;&gt;2&lt;/span&gt;&lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;&lt;code&gt;append()&lt;/code&gt;와 &lt;code&gt;extend()&lt;/code&gt;&lt;/span&gt;값 하나를 추가할 때와 리스트의 여러 값을 이어 붙일 때의 차이를 함께 복습하면 좋다.&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;hb-step&quot;&gt;&lt;span class=&quot;hb-step-number&quot;&gt;3&lt;/span&gt;&lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;Early Return&lt;/span&gt;정답을 확정할 수 있는 순간과 아직 탐색을 계속해야 하는 순간을 구분하는 연습이 필요하다.&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;div class=&quot;hb-closing&quot;&gt;
    &lt;strong&gt;마무리&lt;/strong&gt;
    &lt;p&gt;이번 다섯 문제를 풀면서 슬라이싱 문법 자체보다 중요한 것은 범위와 상태를 정확히 읽는 일이라는 점을 확인했다. 시작점과 끝점을 어디까지 포함하는지, 현재 반복문의 변수가 값인지 인덱스인지, 잘라낸 결과가 다음 단계의 입력이 되는지를 먼저 적어 보면 복잡해 보이는 배열 문제도 훨씬 단순해진다.&lt;/p&gt;
  &lt;/div&gt;
&lt;/article&gt;</description>
      <category>AI/Coding_Test</category>
      <category>2의영역</category>
      <category>DAY12</category>
      <category>리스트자르기</category>
      <category>배열만들기3</category>
      <category>배열조각하기</category>
      <category>슬라이싱</category>
      <category>첫번째음수</category>
      <category>코딩테스트</category>
      <category>파이썬</category>
      <category>프로그래머스</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/120</guid>
      <comments>https://onethingflow.tistory.com/entry/Day-12-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%8A%AC%EB%9D%BC%EC%9D%B4%EC%8B%B1-5%EB%AC%B8%EC%A0%9C-%ED%92%80%EC%9D%B4#entry120comment</comments>
      <pubDate>Mon, 20 Jul 2026 22:36:46 +0900</pubDate>
    </item>
    <item>
      <title>Day 10) 프로그래머스 파이썬 문자열 5문제 풀이</title>
      <link>https://onethingflow.tistory.com/entry/Day-10-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EB%AC%B8%EC%9E%90%EC%97%B4-5%EB%AC%B8%EC%A0%9C-%ED%92%80%EC%9D%B4</link>
      <description>&lt;!--
Title: Day 10) 프로그래머스 파이썬 문자열 5문제 풀이
Meta description: 프로그래머스 코딩 기초 트레이닝 Day 10 문자열 문제 5개를 파이썬으로 풀이합니다. 문자열 슬라이싱, 접두사 확인, 부분 문자열 뒤집기, 세로 읽기, 인덱스 나머지 조건을 반복문 풀이부터 간단한 풀이까지 정리했습니다.
Tags: 프로그래머스, 코딩테스트, 파이썬, 코딩기초트레이닝, Day10, 문자열, 문자열슬라이싱, 접두사, 세로읽기, QR코드
--&gt;

&lt;article class=&quot;hb-post hb-day10-string&quot;&gt;
  &lt;style&gt;
    .hb-day10-string {
      --hb-ink: #172033;
      --hb-muted: #596579;
      --hb-line: #dbe2ea;
      --hb-soft: #f4f7fb;
      --hb-blue: #2563eb;
      --hb-blue-soft: #eef4ff;
      --hb-green: #087f5b;
      --hb-green-soft: #edf9f4;
      max-width: 860px;
      margin: 0 auto;
      color: var(--hb-ink);
      font-size: 17px;
      line-height: 1.82;
      word-break: keep-all;
    }

    .hb-day10-string * {
      box-sizing: border-box;
    }

    .hb-day10-string .hb-hero {
      margin: 0 0 34px;
      padding: 34px 30px;
      color: #ffffff;
      background: #172554;
      border-radius: 8px;
    }

    .hb-day10-string .hb-kicker {
      margin: 0 0 8px;
      color: #bfdbfe;
      font-size: 14px;
      font-weight: 800;
    }

    .hb-day10-string h1 {
      margin: 0;
      color: #ffffff;
      font-size: 34px;
      line-height: 1.3;
      letter-spacing: 0;
    }

    .hb-day10-string .hb-lead {
      margin: 16px 0 0;
      color: #e5edff;
      font-size: 18px;
    }

    .hb-day10-string h2 {
      margin: 52px 0 16px;
      padding-bottom: 10px;
      color: #111827;
      font-size: 27px;
      line-height: 1.4;
      letter-spacing: 0;
      border-bottom: 2px solid var(--hb-line);
    }

    .hb-day10-string h3 {
      margin: 30px 0 10px;
      color: #1e3a8a;
      font-size: 20px;
      line-height: 1.5;
      letter-spacing: 0;
    }

    .hb-day10-string p {
      margin: 10px 0;
    }

    .hb-day10-string a {
      color: #1d4ed8;
      text-decoration-thickness: 1px;
      text-underline-offset: 3px;
    }

    .hb-day10-string code,
    .hb-post code {
      overflow-wrap: anywhere;
    }

    .hb-day10-string p code,
    .hb-day10-string li code,
    .hb-day10-string td code {
      padding: 2px 6px;
      color: #9f1239;
      background: #fff1f2;
      border-radius: 4px;
      font-size: 0.92em;
    }

    .hb-day10-string pre {
      margin: 14px 0 20px;
      padding: 20px;
      overflow-x: auto;
      color: #e5e7eb;
      background: #111827;
      border: 1px solid #273449;
      border-radius: 8px;
      line-height: 1.65;
      tab-size: 4;
    }

    .hb-day10-string pre code {
      padding: 0;
      color: inherit;
      background: transparent;
      font-size: 14px;
      white-space: pre;
      overflow-wrap: normal;
    }

    .hb-day10-string .hb-summary,
    .hb-day10-string .hb-note,
    .hb-day10-string .hb-warning {
      margin: 20px 0;
      padding: 18px 20px;
      border-radius: 8px;
    }

    .hb-day10-string .hb-summary {
      background: var(--hb-blue-soft);
      border-left: 4px solid var(--hb-blue);
    }

    .hb-day10-string .hb-note {
      background: var(--hb-green-soft);
      border-left: 4px solid var(--hb-green);
    }

    .hb-day10-string .hb-warning {
      background: #fff7ed;
      border-left: 4px solid #ea580c;
    }

    .hb-day10-string .hb-summary strong,
    .hb-day10-string .hb-note strong,
    .hb-day10-string .hb-warning strong {
      display: block;
      margin-bottom: 4px;
    }

    .hb-day10-string .hb-link-table,
    .hb-day10-string .hb-example-table {
      width: 100%;
      margin: 16px 0 24px;
      border-collapse: collapse;
      font-size: 15px;
    }

    .hb-day10-string .hb-table-wrap {
      width: 100%;
      overflow-x: auto;
      border: 1px solid var(--hb-line);
      border-radius: 8px;
    }

    .hb-day10-string .hb-table-wrap table {
      margin: 0;
      min-width: 660px;
    }

    .hb-day10-string caption {
      padding: 12px 14px;
      color: #334155;
      background: var(--hb-soft);
      font-weight: 800;
      text-align: left;
    }

    .hb-day10-string th,
    .hb-day10-string td {
      padding: 12px 14px;
      text-align: left;
      vertical-align: top;
      border-bottom: 1px solid var(--hb-line);
    }

    .hb-day10-string th {
      color: #334155;
      background: #f8fafc;
      font-weight: 800;
    }

    .hb-day10-string tbody tr:last-child td {
      border-bottom: 0;
    }

    .hb-day10-string .hb-steps {
      display: grid;
      gap: 12px;
      margin: 18px 0 24px;
    }

    .hb-day10-string .hb-step {
      display: grid;
      grid-template-columns: 34px minmax(0, 1fr);
      gap: 12px;
      align-items: start;
      padding: 15px 16px;
      background: #ffffff;
      border: 1px solid var(--hb-line);
      border-radius: 8px;
    }

    .hb-day10-string .hb-step-number {
      display: inline-flex;
      width: 30px;
      height: 30px;
      align-items: center;
      justify-content: center;
      color: #ffffff;
      background: #1d4ed8;
      border-radius: 6px;
      font-size: 14px;
      font-weight: 900;
      line-height: 1;
    }

    .hb-day10-string .hb-step-title {
      display: block;
      margin-bottom: 3px;
      color: #172033;
      font-weight: 800;
    }

    .hb-day10-string .hb-checklist {
      margin: 16px 0;
      padding: 0;
      list-style: none;
    }

    .hb-day10-string .hb-checklist li {
      position: relative;
      margin: 9px 0;
      padding-left: 30px;
    }

    .hb-day10-string .hb-checklist li::before {
      position: absolute;
      top: 1px;
      left: 0;
      content: &quot;✓&quot;;
      color: var(--hb-green);
      font-weight: 900;
    }

    .hb-day10-string .hb-footer {
      margin-top: 50px;
      padding: 24px;
      background: var(--hb-soft);
      border-top: 3px solid #1d4ed8;
      border-radius: 8px;
    }

    @media (max-width: 640px) {
      .hb-day10-string {
        font-size: 16px;
        line-height: 1.76;
        word-break: normal;
      }

      .hb-day10-string .hb-hero {
        padding: 26px 20px;
      }

      .hb-day10-string h1 {
        font-size: 28px;
      }

      .hb-day10-string h2 {
        margin-top: 44px;
        font-size: 23px;
      }

      .hb-day10-string h3 {
        font-size: 19px;
      }

      .hb-day10-string pre {
        margin-right: -2px;
        margin-left: -2px;
        padding: 16px;
      }

      .hb-day10-string .hb-step {
        grid-template-columns: 30px minmax(0, 1fr);
        gap: 10px;
        padding: 14px;
      }
    }
  &lt;/style&gt;

  &lt;header class=&quot;hb-hero&quot;&gt;
    &lt;p class=&quot;hb-kicker&quot;&gt;Programmers Coding Test · Day 10 · Python&lt;/p&gt;
    &lt;h1&gt;문자열 문제 5개 풀이&lt;/h1&gt;
    &lt;p class=&quot;hb-lead&quot;&gt;앞부분 자르기부터 접두사, 부분 뒤집기, 세로 읽기, QR 코드까지 문자열 인덱스를 다루는 방법을 한 번에 복습했다.&lt;/p&gt;
  &lt;/header&gt;

  &lt;p&gt;Day 10은 다섯 문제 모두 문자열을 다룬다. 겉보기에는 서로 다른 문제지만, 실제로는 &lt;strong&gt;시작 위치, 끝 위치, 간격&lt;/strong&gt;을 어떻게 정하느냐가 핵심이었다. 먼저 반복문으로 조건을 직접 확인하고, 그다음 파이썬의 슬라이싱으로 코드를 줄여 보니 각 문법이 어떤 역할을 하는지 더 분명하게 보였다.&lt;/p&gt;

  &lt;div class=&quot;hb-summary&quot;&gt;
    &lt;strong&gt;오늘의 핵심&lt;/strong&gt;
    파이썬 슬라이싱 &lt;code&gt;문자열[시작:끝:간격]&lt;/code&gt;에서 &lt;code&gt;끝&lt;/code&gt; 위치의 문자는 포함되지 않는다. 문제에서 마지막 인덱스까지 포함하라고 하면 보통 &lt;code&gt;끝 + 1&lt;/code&gt;이 필요하다.
  &lt;/div&gt;

  &lt;h2&gt;Day 10 문제와 공식 링크&lt;/h2&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table class=&quot;hb-link-table&quot;&gt;
      &lt;caption&gt;프로그래머스 코딩 기초 트레이닝 Day 10&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;순서&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;문제&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;핵심 문법&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;1&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181907&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;문자열의 앞의 n글자&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;my_string[:n]&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;2&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181906&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;접두사인지 확인하기&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;startswith()&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;3&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181905&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;문자열 뒤집기&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;[::-1]&lt;/code&gt;, 구간 분리&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;4&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181904&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;세로 읽기&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;[c - 1::m]&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;5&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181903&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;qr code&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;index % q == r&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;div class=&quot;hb-steps&quot;&gt;
    &lt;div class=&quot;hb-step&quot;&gt;
      &lt;span class=&quot;hb-step-number&quot;&gt;1&lt;/span&gt;
      &lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;인덱스 기준부터 확인하기&lt;/span&gt;파이썬 문자열 인덱스는 0부터 시작하지만, 문제의 열 번호 &lt;code&gt;c&lt;/code&gt;는 1부터 시작한다.&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-step&quot;&gt;
      &lt;span class=&quot;hb-step-number&quot;&gt;2&lt;/span&gt;
      &lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;포함 범위를 확인하기&lt;/span&gt;&lt;code&gt;s&lt;/code&gt;부터 &lt;code&gt;e&lt;/code&gt;까지 모두 포함하려면 슬라이싱의 끝을 &lt;code&gt;e + 1&lt;/code&gt;로 잡아야 한다.&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-step&quot;&gt;
      &lt;span class=&quot;hb-step-number&quot;&gt;3&lt;/span&gt;
      &lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;문자와 인덱스를 구분하기&lt;/span&gt;QR 코드 문제는 문자의 값이 아니라 문자가 놓인 &lt;strong&gt;인덱스&lt;/strong&gt;를 &lt;code&gt;q&lt;/code&gt;로 나눈 나머지를 검사한다.&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;h2&gt;1. 문자열의 앞의 n글자&lt;/h2&gt;

  &lt;p&gt;&lt;code&gt;my_string&lt;/code&gt;의 맨 앞에서부터 &lt;code&gt;n&lt;/code&gt;글자를 반환하는 문제다. 처음에는 반복문으로 앞의 문자를 하나씩 이어 붙일 수 있다.&lt;/p&gt;

  &lt;h3&gt;기본 풀이: 반복문으로 직접 누적하기&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(my_string, n):
    answer = ''

    for i in range(n):
        answer += my_string[i]

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;range(n)&lt;/code&gt;은 &lt;code&gt;0&lt;/code&gt;부터 &lt;code&gt;n - 1&lt;/code&gt;까지 만든다. 따라서 앞의 &lt;code&gt;n&lt;/code&gt;글자를 정확히 한 번씩 가져올 수 있다.&lt;/p&gt;

  &lt;h3&gt;더 간단한 풀이: 슬라이싱&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(my_string, n):
    return my_string[:n]&lt;/code&gt;&lt;/pre&gt;

  &lt;div class=&quot;hb-note&quot;&gt;
    &lt;strong&gt;&lt;code&gt;[:n]&lt;/code&gt;은 왜 n글자일까?&lt;/strong&gt;
    시작 위치를 생략하면 처음부터 자르고, 끝 위치 &lt;code&gt;n&lt;/code&gt;은 포함하지 않는다. 결국 인덱스 &lt;code&gt;0&lt;/code&gt;부터 &lt;code&gt;n - 1&lt;/code&gt;까지, 총 &lt;code&gt;n&lt;/code&gt;글자가 남는다.
  &lt;/div&gt;

  &lt;h2&gt;2. 접두사인지 확인하기&lt;/h2&gt;

  &lt;p&gt;접두사는 문자열의 &lt;strong&gt;맨 앞에서 시작하는 문자열&lt;/strong&gt;이다. 예를 들어 &lt;code&gt;banana&lt;/code&gt; 안에 &lt;code&gt;nan&lt;/code&gt;이 들어 있기는 하지만 맨 앞에서 시작하지 않으므로 접두사가 아니다.&lt;/p&gt;

  &lt;h3&gt;기본 풀이: 앞부분을 잘라 비교하기&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(my_string, is_prefix):
    if my_string[:len(is_prefix)] == is_prefix:
        return 1
    return 0&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;is_prefix&lt;/code&gt;의 길이만큼 &lt;code&gt;my_string&lt;/code&gt; 앞부분을 잘라 두 문자열이 같은지 확인했다. 접두사가 원본 문자열보다 길어도 슬라이싱은 오류 없이 가능한 범위까지만 반환하므로 결과는 자연스럽게 0이 된다.&lt;/p&gt;

  &lt;h3&gt;더 간단한 풀이: startswith()&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(my_string, is_prefix):
    return int(my_string.startswith(is_prefix))&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;startswith()&lt;/code&gt;는 특정 문자열로 시작하면 &lt;code&gt;True&lt;/code&gt;, 아니면 &lt;code&gt;False&lt;/code&gt;를 반환한다. 여기에 &lt;code&gt;int()&lt;/code&gt;를 적용하면 각각 1과 0으로 바뀐다.&lt;/p&gt;

  &lt;div class=&quot;hb-warning&quot;&gt;
    &lt;strong&gt;주의: &lt;code&gt;in&lt;/code&gt;을 쓰면 다른 문제가 된다&lt;/strong&gt;
    &lt;code&gt;is_prefix in my_string&lt;/code&gt;은 문자열이 중간이나 끝에 있어도 참이 된다. 이 문제는 포함 여부가 아니라 맨 앞에서 시작하는지를 확인해야 한다.
  &lt;/div&gt;

  &lt;h2&gt;3. 문자열 뒤집기&lt;/h2&gt;

  &lt;p&gt;&lt;code&gt;my_string&lt;/code&gt; 전체를 뒤집는 문제가 아니라, 인덱스 &lt;code&gt;s&lt;/code&gt;부터 &lt;code&gt;e&lt;/code&gt;까지의 구간만 뒤집어야 한다. 문자열을 앞, 뒤집을 구간, 뒤의 세 부분으로 나누면 이해하기 쉽다.&lt;/p&gt;

  &lt;h3&gt;내가 작성한 코드&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(my_string, s, e):
    answer = my_string[:s] + my_string[e:s - 1:-1] + my_string[e + 1:]
    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;문자열을 앞부분, 뒤집을 구간, 뒷부분으로 나눠 다시 조립하려는 방향은 정확했다. 특히 가운데 구간에서 간격을 &lt;code&gt;-1&lt;/code&gt;로 두어 역순으로 읽으려 한 점이 좋았다.&lt;/p&gt;

  &lt;div class=&quot;hb-warning&quot;&gt;
    &lt;strong&gt;&lt;code&gt;s = 0&lt;/code&gt;일 때 생기는 숨은 문제&lt;/strong&gt;
    &lt;code&gt;s - 1&lt;/code&gt;은 &lt;code&gt;-1&lt;/code&gt;이 된다. 이때 &lt;code&gt;my_string[e:-1:-1]&lt;/code&gt;의 &lt;code&gt;-1&lt;/code&gt;은 단순히 처음보다 앞이라는 뜻이 아니라 문자열의 마지막 인덱스로 해석된다. 역방향 슬라이싱의 끝 위치는 포함되지 않기 때문에 원하는 구간 대신 빈 문자열이 나올 수 있다.
  &lt;/div&gt;

  &lt;h3&gt;안전하게 고친 기본 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(my_string, s, e):
    front = my_string[:s]
    middle = my_string[s:e + 1]
    back = my_string[e + 1:]

    return front + middle[::-1] + back&lt;/code&gt;&lt;/pre&gt;

  &lt;div class=&quot;hb-steps&quot;&gt;
    &lt;div class=&quot;hb-step&quot;&gt;
      &lt;span class=&quot;hb-step-number&quot;&gt;1&lt;/span&gt;
      &lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;앞부분&lt;/span&gt;&lt;code&gt;my_string[:s]&lt;/code&gt;로 &lt;code&gt;s&lt;/code&gt; 바로 전까지 보존한다.&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-step&quot;&gt;
      &lt;span class=&quot;hb-step-number&quot;&gt;2&lt;/span&gt;
      &lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;가운데 구간&lt;/span&gt;&lt;code&gt;my_string[s:e + 1]&lt;/code&gt;로 먼저 안전하게 자른 뒤 &lt;code&gt;[::-1]&lt;/code&gt;로 뒤집는다.&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-step&quot;&gt;
      &lt;span class=&quot;hb-step-number&quot;&gt;3&lt;/span&gt;
      &lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;뒷부분&lt;/span&gt;&lt;code&gt;my_string[e + 1:]&lt;/code&gt;로 뒤집을 범위 다음의 문자를 이어 붙인다.&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;h3&gt;한 줄로 정리한 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(my_string, s, e):
    return my_string[:s] + my_string[s:e + 1][::-1] + my_string[e + 1:]&lt;/code&gt;&lt;/pre&gt;

  &lt;div class=&quot;hb-warning&quot;&gt;
    &lt;strong&gt;가장 자주 생기는 실수&lt;/strong&gt;
    가운데를 &lt;code&gt;my_string[s:e]&lt;/code&gt;로 자르면 인덱스 &lt;code&gt;e&lt;/code&gt;의 문자가 빠진다. 문제의 범위는 &lt;code&gt;s&lt;/code&gt;와 &lt;code&gt;e&lt;/code&gt;를 모두 포함하므로 &lt;code&gt;e + 1&lt;/code&gt;이 필요하다.
  &lt;/div&gt;

  &lt;h2&gt;4. 세로 읽기&lt;/h2&gt;

  &lt;p&gt;문자열을 한 줄에 &lt;code&gt;m&lt;/code&gt;글자씩 나누었을 때, 왼쪽에서 &lt;code&gt;c&lt;/code&gt;번째 열의 문자를 위에서 아래로 읽는 문제다. 같은 열의 문자는 인덱스가 &lt;code&gt;m&lt;/code&gt;씩 증가한다.&lt;/p&gt;

  &lt;h3&gt;내가 작성한 코드&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(my_string, m, c):
    answer = ''
    new = list(my_string.split(' '))

    for i in new[c - 1::m]:
        answer += my_string[i]

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;[c - 1::m]&lt;/code&gt;으로 일정한 간격의 값을 고르려 한 방향은 문제의 핵심과 맞았다. 다만 슬라이싱을 적용한 대상과 반복문 변수 &lt;code&gt;i&lt;/code&gt;의 자료형 때문에 코드가 정상적으로 실행되지 않는다.&lt;/p&gt;

  &lt;div class=&quot;hb-steps&quot;&gt;
    &lt;div class=&quot;hb-step&quot;&gt;
      &lt;span class=&quot;hb-step-number&quot;&gt;1&lt;/span&gt;
      &lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;&lt;code&gt;split(' ')&lt;/code&gt;은 필요하지 않다&lt;/span&gt;입력 문자열에는 공백이 없다. 따라서 분리하면 글자 목록이 아니라 원본 문자열 하나를 담은 리스트가 된다.&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-step&quot;&gt;
      &lt;span class=&quot;hb-step-number&quot;&gt;2&lt;/span&gt;
      &lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;&lt;code&gt;i&lt;/code&gt;는 인덱스가 아니다&lt;/span&gt;&lt;code&gt;for i in new[...]&lt;/code&gt;에서 &lt;code&gt;i&lt;/code&gt;는 숫자가 아니라 문자열 값이다. &lt;code&gt;my_string[i]&lt;/code&gt;처럼 문자열을 인덱스로 사용하면 &lt;code&gt;TypeError&lt;/code&gt;가 발생한다.&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;h3&gt;초보자가 이해하기 쉬운 기본 풀이&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(my_string, m, c):
    answer = ''

    for i in range(c - 1, len(my_string), m):
        answer += my_string[i]

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;range(c - 1, len(my_string), m)&lt;/code&gt;은 &lt;code&gt;c - 1&lt;/code&gt;에서 시작해 &lt;code&gt;m&lt;/code&gt;칸씩 증가하는 인덱스를 만든다. 이제 &lt;code&gt;i&lt;/code&gt;가 실제 숫자 인덱스이므로 &lt;code&gt;my_string[i]&lt;/code&gt;로 문자를 안전하게 꺼낼 수 있다.&lt;/p&gt;

  &lt;h3&gt;더 간단한 풀이: 간격이 있는 슬라이싱&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(my_string, m, c):
    return my_string[c - 1::m]&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;[c - 1::m]&lt;/code&gt;은 인덱스 &lt;code&gt;c - 1&lt;/code&gt;에서 시작해 끝까지 &lt;code&gt;m&lt;/code&gt;칸 간격으로 문자를 선택한다. 반복문의 범위와 슬라이싱의 세 요소가 정확히 대응한다.&lt;/p&gt;

  &lt;div class=&quot;hb-note&quot;&gt;
    &lt;strong&gt;예제로 인덱스 확인하기&lt;/strong&gt;
    &lt;code&gt;m = 4&lt;/code&gt;, &lt;code&gt;c = 2&lt;/code&gt;라면 선택되는 인덱스는 &lt;code&gt;1, 5, 9, 13, 17&lt;/code&gt;이다. 공식 예제 문자열에서 이 문자를 이어 붙이면 &lt;code&gt;happy&lt;/code&gt;가 된다.
  &lt;/div&gt;

  &lt;h2&gt;5. qr code&lt;/h2&gt;

  &lt;p&gt;&lt;code&gt;code&lt;/code&gt;의 각 인덱스를 &lt;code&gt;q&lt;/code&gt;로 나누었을 때 나머지가 &lt;code&gt;r&lt;/code&gt;인 위치의 문자만 순서대로 이어 붙이는 문제다.&lt;/p&gt;

  &lt;h3&gt;내가 처음 작성한 코드&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(q, r, code):
    answer = ''

    for i in code:
        if r == i % q:
            answer += i

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;나머지 연산으로 조건을 확인하려는 생각은 맞았다. 하지만 &lt;code&gt;for i in code&lt;/code&gt;에서 &lt;code&gt;i&lt;/code&gt;에는 인덱스가 아니라 &lt;code&gt;'a'&lt;/code&gt;, &lt;code&gt;'b'&lt;/code&gt; 같은 문자가 들어간다. 문자열에 나머지 연산을 적용할 수 없으므로 &lt;code&gt;TypeError&lt;/code&gt;가 발생한다.&lt;/p&gt;

  &lt;h3&gt;기본 풀이: 인덱스를 직접 반복하기&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(q, r, code):
    answer = ''

    for i in range(len(code)):
        if i % q == r:
            answer += code[i]

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;range(len(code))&lt;/code&gt;를 사용하면 &lt;code&gt;i&lt;/code&gt;가 0부터 시작하는 인덱스가 된다. 나머지 조건은 &lt;code&gt;i&lt;/code&gt;로 확인하고, 선택한 문자는 &lt;code&gt;code[i]&lt;/code&gt;로 가져오면 된다.&lt;/p&gt;

  &lt;h3&gt;내가 수정한 최종 풀이: r에서 시작해 q칸씩 이동하기&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def solution(q, r, code):
    return code[r::q]&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;인덱스를 &lt;code&gt;q&lt;/code&gt;로 나눈 나머지가 &lt;code&gt;r&lt;/code&gt;인 위치는 &lt;code&gt;r, r + q, r + 2q, ...&lt;/code&gt;로 이어진다. 따라서 인덱스 &lt;code&gt;r&lt;/code&gt;에서 시작해 &lt;code&gt;q&lt;/code&gt;칸씩 건너뛰는 슬라이싱으로 같은 결과를 얻을 수 있다.&lt;/p&gt;

  &lt;div class=&quot;hb-warning&quot;&gt;
    &lt;strong&gt;주의: r이 0일 수도 있다&lt;/strong&gt;
    제한사항은 &lt;code&gt;0 ≤ r &amp;lt; q&lt;/code&gt;다. 나머지가 0인 인덱스도 선택 대상이므로 시작 위치를 임의로 1로 고정하면 안 된다.
  &lt;/div&gt;

  &lt;h2&gt;공식 예제로 한 번에 검산하기&lt;/h2&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table class=&quot;hb-example-table&quot;&gt;
      &lt;caption&gt;각 문제의 대표 입력과 결과&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;문제&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;대표 입력&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;결과&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;앞의 n글자&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;&quot;ProgrammerS123&quot;, 11&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;&quot;ProgrammerS&quot;&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;접두사&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;&quot;banana&quot;, &quot;ban&quot;&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;문자열 뒤집기&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;&quot;Progra21Sremm3&quot;, 6, 12&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;&quot;ProgrammerS123&quot;&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;세로 읽기&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;&quot;ihrhbakrfpndopljhygc&quot;, 4, 2&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;&quot;happy&quot;&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;qr code&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;3, 1, &quot;qjnwezgrpirldywt&quot;&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;&quot;jerry&quot;&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;이번 문제에서 기억할 실수 체크리스트&lt;/h2&gt;

  &lt;ul class=&quot;hb-checklist&quot;&gt;
    &lt;li&gt;슬라이싱의 끝 인덱스는 결과에 포함되지 않는다.&lt;/li&gt;
    &lt;li&gt;문제의 위치가 1부터 시작하는지, 인덱스가 0부터 시작하는지 확인한다.&lt;/li&gt;
    &lt;li&gt;접두사 문제에서 단순 포함 연산자 &lt;code&gt;in&lt;/code&gt;을 사용하지 않는다.&lt;/li&gt;
    &lt;li&gt;부분 문자열 뒤집기에서는 앞, 가운데, 뒤 구간을 빠뜨리지 않는다.&lt;/li&gt;
    &lt;li&gt;QR 코드 문제는 문자의 값이 아니라 인덱스의 나머지를 검사한다.&lt;/li&gt;
    &lt;li&gt;짧은 풀이를 외우기 전에 반복문이 어떤 위치를 선택하는지 먼저 설명해 본다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h2&gt;같이 보면 좋은 개념&lt;/h2&gt;

  &lt;div class=&quot;hb-steps&quot;&gt;
    &lt;div class=&quot;hb-step&quot;&gt;
      &lt;span class=&quot;hb-step-number&quot;&gt;1&lt;/span&gt;
      &lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;문자열 슬라이싱&lt;/span&gt;&lt;code&gt;[시작:끝:간격]&lt;/code&gt;의 세 자리에 어떤 값이 들어가는지 예제로 익혀 두면 네 문제를 거의 같은 방식으로 풀 수 있다.&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-step&quot;&gt;
      &lt;span class=&quot;hb-step-number&quot;&gt;2&lt;/span&gt;
      &lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;문자열 메서드&lt;/span&gt;&lt;code&gt;startswith()&lt;/code&gt;와 &lt;code&gt;endswith()&lt;/code&gt;의 차이를 함께 비교하면 접두사와 접미사를 헷갈리지 않는다.&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-step&quot;&gt;
      &lt;span class=&quot;hb-step-number&quot;&gt;3&lt;/span&gt;
      &lt;div&gt;&lt;span class=&quot;hb-step-title&quot;&gt;enumerate()&lt;/span&gt;문자열이나 리스트를 반복하면서 인덱스와 값을 모두 사용해야 할 때 유용하다.&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class=&quot;hb-footer&quot;&gt;
    &lt;strong&gt;마무리&lt;/strong&gt;
    &lt;p&gt;Day 10의 다섯 문제는 결국 문자열에서 필요한 위치를 정확히 고르는 연습이었다. 반복문 풀이로 인덱스의 움직임을 확인한 뒤 슬라이싱으로 바꾸면, 한 줄 풀이도 단순 암기가 아니라 이해한 코드가 된다. 특히 &lt;code&gt;e + 1&lt;/code&gt;, &lt;code&gt;c - 1&lt;/code&gt;, &lt;code&gt;index % q == r&lt;/code&gt;은 다음 문자열 문제에서도 계속 등장하므로 따로 기억해 두는 것이 좋다.&lt;/p&gt;
  &lt;/div&gt;
&lt;/article&gt;</description>
      <category>AI/Coding_Test</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/119</guid>
      <comments>https://onethingflow.tistory.com/entry/Day-10-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EB%AC%B8%EC%9E%90%EC%97%B4-5%EB%AC%B8%EC%A0%9C-%ED%92%80%EC%9D%B4#entry119comment</comments>
      <pubDate>Fri, 17 Jul 2026 12:40:35 +0900</pubDate>
    </item>
    <item>
      <title>5일차_정보처리기사 필기 C언어 오답노트: 시험장에서 틀리기 쉬운 8가지 함정</title>
      <link>https://onethingflow.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%8B%A4%EA%B8%B0-C%EC%96%B8%EC%96%B4-%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8-%EC%8B%9C%ED%97%98%EC%9E%A5%EC%97%90%EC%84%9C-%ED%8B%80%EB%A6%AC%EA%B8%B0-%EC%89%AC%EC%9A%B4-8%EA%B0%80%EC%A7%80-%ED%95%A8%EC%A0%95</link>
      <description>&lt;div&gt;
&lt;style&gt;
.hb-post {
  --hb-ink: #172033;
  --hb-muted: #657085;
  --hb-line: #dfe6ef;
  --hb-soft: #f6f8fb;
  --hb-accent: #315efb;
  --hb-accent-soft: #eef3ff;
  --hb-good: #17876d;
  --hb-good-soft: #edf9f5;
  --hb-warn: #b45309;
  --hb-warn-soft: #fff8e8;
  max-width: 780px;
  margin: 0 auto;
  color: var(--hb-ink);
  font-size: 17px;
  line-height: 1.85;
  word-break: normal;
  overflow-wrap: break-word;
}

.hb-post,
.hb-post * {
  box-sizing: border-box;
}

.hb-post h1,
.hb-post h2,
.hb-post h3,
.hb-post p {
  margin-top: 0;
}

.hb-post h1 {
  margin-bottom: .68em;
  font-size: 2em;
  line-height: 1.3;
  font-weight: 800;
  word-break: keep-all;
}

.hb-post h2 {
  margin: 2.45em 0 .75em;
  padding-bottom: .36em;
  border-bottom: 2px solid var(--hb-line);
  font-size: 1.34em;
  line-height: 1.42;
  font-weight: 800;
  word-break: keep-all;
}

.hb-post h3 {
  margin: 1.8em 0 .55em;
  font-size: 1.08em;
  line-height: 1.45;
  font-weight: 800;
  word-break: keep-all;
}

.hb-post p {
  margin-bottom: 1.08em;
}

.hb-post a {
  color: var(--hb-accent);
  text-decoration: none;
  border-bottom: 1px solid rgba(49, 94, 251, .3);
}

.hb-post strong {
  font-weight: 800;
}

.hb-post code {
  padding: .08em .38em;
  border: 1px solid #e5e8ee;
  border-radius: 4px;
  background: #f4f5f7;
  color: #b4234d;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .92em;
  overflow-wrap: anywhere;
}

.hb-post pre {
  margin: 1.25em 0;
  padding: 1.1em 1.2em;
  overflow-x: auto;
  border-radius: 8px;
  background: #1f2430;
  color: #eef2ff;
  font-size: .88em;
  line-height: 1.62;
  -webkit-overflow-scrolling: touch;
}

.hb-post pre code {
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font-size: 1em;
  white-space: pre;
  overflow-wrap: normal;
}

.hb-post .hb-hero {
  margin-bottom: 1.55em;
  padding: 1.35em 1.4em;
  border: 1px solid var(--hb-line);
  border-radius: 10px;
  background: linear-gradient(135deg, #eef3ff 0%, #fff 62%, #fff8e8 100%);
}

.hb-post .hb-eyebrow {
  display: inline-block;
  margin-bottom: .55em;
  color: var(--hb-accent);
  font-size: .82em;
  font-weight: 800;
}

.hb-post .hb-lead {
  margin-bottom: 0;
  color: #343a46;
  font-size: 1.06em;
}

.hb-post .hb-card-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: .8em;
  margin: 1.35em 0;
}

.hb-post .hb-card,
.hb-post .hb-memory-card {
  min-width: 0;
  padding: 1em;
  border: 1px solid var(--hb-line);
  border-radius: 8px;
  background: #fff;
}

.hb-post .hb-card span {
  display: block;
  margin-bottom: .24em;
  color: var(--hb-muted);
  font-size: .82em;
}

.hb-post .hb-card strong {
  display: block;
  line-height: 1.38;
}

.hb-post .hb-memory-card strong {
  display: block;
  margin-bottom: .35em;
  color: var(--hb-accent);
}

.hb-post .hb-number-list {
  display: grid;
  gap: .9em;
  margin: 1.35em 0;
}

.hb-post .hb-number-item {
  display: grid;
  grid-template-columns: 2em minmax(0, 1fr);
  gap: .65em;
  align-items: start;
  margin: 0;
}

.hb-post .hb-number-badge {
  display: flex;
  width: 1.75em;
  height: 1.75em;
  align-items: center;
  justify-content: center;
  margin-top: .12em;
  border-radius: 999px;
  background: var(--hb-accent);
  color: #fff;
  font-weight: 800;
  line-height: 1;
}

.hb-post .hb-number-body {
  min-width: 0;
}

.hb-post .hb-number-title {
  display: block;
  margin-bottom: .2em;
}

.hb-post .hb-number-body p:last-child {
  margin-bottom: 0;
}

.hb-post .hb-code-label {
  display: inline-block;
  margin-bottom: -.45em;
  padding: .28em .62em;
  border-radius: 6px 6px 0 0;
  background: #343b4c;
  color: #fff;
  font-size: .78em;
  font-weight: 700;
}

.hb-post .hb-table-wrap {
  margin: 1.4em 0;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.hb-post table {
  width: 100%;
  min-width: 620px;
  border-collapse: collapse;
  border: 1px solid var(--hb-line);
  font-size: .93em;
}

.hb-post caption {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
}

.hb-post th,
.hb-post td {
  padding: .72em .8em;
  border: 1px solid var(--hb-line);
  text-align: left;
  vertical-align: top;
}

.hb-post th {
  background: var(--hb-soft);
  font-weight: 800;
}

.hb-post tbody tr:nth-child(even) {
  background: #fbfcfd;
}

.hb-post .hb-callout {
  margin: 1.35em 0;
  padding: 1.05em 1.18em;
  border: 1px solid var(--hb-line);
  border-left: 4px solid var(--hb-accent);
  border-radius: 8px;
  background: var(--hb-accent-soft);
}

.hb-post .hb-callout.is-good {
  border-left-color: var(--hb-good);
  background: var(--hb-good-soft);
}

.hb-post .hb-callout.is-warning {
  border-left-color: var(--hb-warn);
  background: var(--hb-warn-soft);
}

.hb-post .hb-callout p:last-child {
  margin-bottom: 0;
}

.hb-post details {
  margin: .8em 0;
  padding: .9em 1em;
  border: 1px solid var(--hb-line);
  border-radius: 8px;
  background: #fff;
}

.hb-post summary {
  cursor: pointer;
  font-weight: 800;
}

.hb-post .hb-references {
  margin-top: 2.5em;
  padding-top: 1.15em;
  border-top: 1px solid var(--hb-line);
  color: #4b5565;
  font-size: .92em;
}

.hb-post .hb-footer-note {
  margin-top: 1.4em;
  color: #747e8e;
  font-size: .88em;
}

@media (max-width: 680px) {
  .hb-post {
    font-size: 16px;
  }

  .hb-post h1 {
    font-size: 1.6em;
  }

  .hb-post .hb-hero {
    padding: 1.1em;
  }

  .hb-post .hb-card-grid {
    grid-template-columns: 1fr;
  }

  .hb-post .hb-number-item {
    grid-template-columns: 1.8em minmax(0, 1fr);
    gap: .55em;
  }

  .hb-post .hb-number-badge {
    width: 1.6em;
    height: 1.6em;
  }

  .hb-post table {
    font-size: .9em;
  }
}
&lt;/style&gt;
&lt;/div&gt;
&lt;article class=&quot;hb-post hb-jeongcheogi-note&quot;&gt;&lt;header class=&quot;hb-hero&quot;&gt;&lt;span class=&quot;hb-eyebrow&quot;&gt;정보처리기사 실기 &amp;middot; C언어 오답노트&lt;/span&gt;
&lt;h1&gt;정보처리기사 필기 C언어 오답노트: 시험장에서 틀리기 쉬운 8가지 함정&lt;/h1&gt;
&lt;p class=&quot;hb-lead&quot; data-ke-size=&quot;size16&quot;&gt;암기 문장을 예외 없이 적용하지 않고 문장 경계 &amp;rarr; 주소 &amp;rarr; 값 &amp;rarr; 자료형&amp;middot;평가 시점 순서로 추적한 학습 기록입니다.&lt;/p&gt;
&lt;/header&gt;
&lt;section id=&quot;hb-study-scope&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;오늘 학습 범위&lt;/h2&gt;
&lt;div class=&quot;hb-card-grid&quot;&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;과목&lt;/span&gt; &lt;b&gt;정보처리기사 필기 프로그래밍 언어 활용&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;교재 범위&lt;/span&gt; &lt;b&gt;수제비 기반 개인 오답노트 문서 1&amp;middot;2&amp;middot;4절&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;오늘의 목표&lt;/span&gt; &lt;b&gt;문장 경계, 주소, 값, 자료형과 평가 시점을 차례로 설명하기&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정보처리기사 실기에서 C언어 문제를 틀리는 이유는 문법을 전혀 몰라서보다 &lt;b&gt;아는 규칙을 너무 넓게 적용해서&lt;/b&gt;인 경우가 많았습니다. 세미콜론 하나, 배열 변환의 예외, 후위 감소가 값을 내보내는 시점처럼 작은 경계가 출력값을 바꿉니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;핵심 개념 카드&lt;/h3&gt;
&lt;div class=&quot;hb-card-grid&quot;&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;1단계 &amp;middot; 문장 경계&lt;/span&gt; &lt;b&gt;세미콜론과 중괄호로 실제 실행 범위를 표시합니다.&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;2단계 &amp;middot; 주소&lt;/span&gt; &lt;b&gt;&lt;code&gt;&amp;amp;&lt;/code&gt;, 배열 변환, 포인터 덧셈이 가리키는 위치를 적습니다.&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;3단계 &amp;middot; 값&lt;/span&gt; &lt;b&gt;&lt;code&gt;*&lt;/code&gt;나 &lt;code&gt;[]&lt;/code&gt;가 있을 때 그 위치의 값을 읽습니다.&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;4단계 &amp;middot; 자료형&lt;/span&gt; &lt;b&gt;포인터 보폭과 &lt;code&gt;sizeof&lt;/code&gt;의 대상을 확인합니다.&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;5단계 &amp;middot; 평가 시점&lt;/span&gt; &lt;b&gt;후위 감소의 식 결과와 문장 뒤 저장값을 나눕니다.&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;제목에서 약속한 8가지&lt;/h3&gt;
&lt;div class=&quot;hb-number-list&quot; role=&quot;list&quot;&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;&lt;code&gt;true&lt;/code&gt;의 의미&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C 표준 버전과 헤더에 따라 확인합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;&lt;code&gt;if (조건);&lt;/code&gt;의 빈 문장&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세미콜론 하나가 조건문의 본문을 끝냅니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;3&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;주소 연산과 역참조&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;amp;&lt;/code&gt;는 주소를 얻고 &lt;code&gt;*&lt;/code&gt;는 주소가 가리키는 객체를 지정합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;4&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;배열 식의 포인터 변환&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분 첫 원소 포인터로 변환되지만 예외가 있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;5&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;배열 첨자의 의미&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;a[i]&lt;/code&gt;는 &lt;code&gt;*(a + i)&lt;/code&gt;와 같은 원리입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;6&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;포인터의 보폭&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;+1&lt;/code&gt;은 가리키는 자료형의 원소 한 칸입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;7&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;문자열의 종단 널&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자열 배열에는 끝을 나타내는 &lt;code&gt;\0&lt;/code&gt;가 들어갑니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;8&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;후위 감소의 결과값&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감소 전 값을 식의 결과로 내보낸 뒤 저장값이 감소합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;aside class=&quot;hb-callout is-warning&quot;&gt;&lt;b&gt;출처 한계&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원본에는 실제 기출 문제 번호, 문제 원문, 선택지, 사용자가 고른 오답과 채점 결과가 없습니다. 따라서 특정 기출을 풀었다고 주장하지 않으며, 아래 통합 코드와 기출형 예제는 원본 개념을 연습하기 위해 새로 구성했습니다. 왼쪽 시프트는 여덟 번째 항목에 섞지 않고 별도의 보충 함정으로 분리했습니다.&lt;/p&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id=&quot;hb-confusions&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;내가 헷갈린 지점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오답노트에 남은 다섯 혼동을 정답 문장만 다시 외우지 않고, 잘못 적용한 규칙과 그것이 깨지는 반례, 시험장에서 던질 질문으로 바꿨습니다.&lt;/p&gt;
&lt;div class=&quot;hb-number-list&quot; role=&quot;list&quot;&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;&lt;code&gt;if&lt;/code&gt; 뒤 세미콜론&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;처음 외운 규칙:&lt;/b&gt; 들여쓰기 된 다음 문장까지 &lt;code&gt;if&lt;/code&gt;의 본문이라고 읽었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;반례:&lt;/b&gt; &lt;code&gt;if (0); x = 1;&lt;/code&gt;에서는 세미콜론이 빈 문장을 완성하므로 &lt;code&gt;x = 1;&lt;/code&gt;이 조건과 관계없이 실행됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;시험장 확인 질문:&lt;/b&gt; 조건문 바로 뒤에 세미콜론이 있는가, 실제 본문은 어느 문장까지인가?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;배열 이름과 포인터&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;처음 외운 규칙:&lt;/b&gt; 배열 이름은 포인터 변수와 완전히 같은 객체라고 외웠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;반례:&lt;/b&gt; &lt;code&gt;int a[3]; int *p = a;&lt;/code&gt;에서 &lt;code&gt;sizeof(a)&lt;/code&gt;는 배열 전체 크기지만 &lt;code&gt;sizeof(p)&lt;/code&gt;는 포인터 자체 크기입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;시험장 확인 질문:&lt;/b&gt; 지금 식이 포인터로 변환되는 문맥인가, 아니면 &lt;code&gt;sizeof(a)&lt;/code&gt;나 &lt;code&gt;&amp;amp;a&lt;/code&gt;처럼 배열 자체가 남는 예외인가?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;3&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;포인터의 &lt;code&gt;+1&lt;/code&gt;&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;처음 외운 규칙:&lt;/b&gt; 포인터에 1을 더하면 주소가 언제나 1바이트 증가한다고 생각했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;반례:&lt;/b&gt; &lt;code&gt;char *&lt;/code&gt;와 &lt;code&gt;int *&lt;/code&gt;는 각각 자기 자료형의 다음 원소로 이동하므로 실제 바이트 간격이 같다고 단정할 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;시험장 확인 질문:&lt;/b&gt; 이 포인터가 가리키는 자료형은 무엇이며 이동 후에도 같은 배열 안의 원소 또는 끝 바로 다음을 가리키는가?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;4&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;문자열 크기&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;처음 외운 규칙:&lt;/b&gt; 화면에 보이는 글자 수가 곧 문자열 배열의 &lt;code&gt;sizeof&lt;/code&gt; 결과라고 생각했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;반례:&lt;/b&gt; &lt;code&gt;char word[] = &quot;C&quot;;&lt;/code&gt;에는 문자 &lt;code&gt;C&lt;/code&gt;와 종단 널 문자 &lt;code&gt;\0&lt;/code&gt;가 들어가므로 &lt;code&gt;sizeof(word)&lt;/code&gt;는 2입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;시험장 확인 질문:&lt;/b&gt; 지금 세는 대상은 보이는 문자 수인가, 널 문자까지 포함한 배열의 저장 크기인가?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;5&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;후위 감소&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;처음 외운 규칙:&lt;/b&gt; &lt;code&gt;B = A--;&lt;/code&gt;에서 &lt;code&gt;A&lt;/code&gt;를 먼저 감소시킨 뒤 그 값을 &lt;code&gt;B&lt;/code&gt;에 넣는다고 생각했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;반례:&lt;/b&gt; &lt;code&gt;A&lt;/code&gt;가 5라면 식의 결과는 5이므로 &lt;code&gt;B&lt;/code&gt;에 5가 들어가고, 저장된 &lt;code&gt;A&lt;/code&gt;는 그 뒤 4가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;시험장 확인 질문:&lt;/b&gt; 지금 필요한 값은 후위 감소식이 내보내는 값인가, 문장이 끝난 뒤 변수에 저장된 값인가?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id=&quot;hb-beginner-explanation&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;초보자 눈높이 개념 설명&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;먼저 보는 용어 상자&lt;/h3&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;초보자가 먼저 알아둘 C언어 용어&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;용어&lt;/th&gt;
&lt;th&gt;정확한 정의&lt;/th&gt;
&lt;th&gt;쉬운 말&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;식별자&lt;/th&gt;
&lt;td&gt;변수&amp;middot;함수처럼 프로그램 요소에 붙이는 이름입니다.&lt;/td&gt;
&lt;td&gt;코드 안의 이름표입니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;키워드&lt;/th&gt;
&lt;td&gt;C 문법이 미리 정해 둔 뜻으로 예약한 토큰입니다.&lt;/td&gt;
&lt;td&gt;언어 사전에 이미 등록되어 다른 이름표로 쓸 수 없는 단어입니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;매크로&lt;/th&gt;
&lt;td&gt;전처리 단계에서 이름을 다른 토큰으로 바꾸도록 정의한 규칙입니다.&lt;/td&gt;
&lt;td&gt;본격적인 컴파일 전에 적용되는 치환 메모입니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;단항 연산자&lt;/th&gt;
&lt;td&gt;피연산자 하나에 작용하는 연산자입니다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;amp;value&lt;/code&gt;, &lt;code&gt;*p&lt;/code&gt;처럼 대상 하나만 받는 기호입니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;구현&lt;/th&gt;
&lt;td&gt;C 표준이 허용한 선택지를 실제 컴파일러와 실행 환경이 정한 방식입니다.&lt;/td&gt;
&lt;td&gt;컴파일러나 환경에 따라 달라질 수 있는 부분입니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;A. 이름과 문장 경계&lt;/h3&gt;
&lt;div class=&quot;hb-number-list&quot; role=&quot;list&quot;&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;&lt;code&gt;true&lt;/code&gt;를 모든 C에서 같은 종류의 이름으로 읽기&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C는 대소문자를 구분하므로 &lt;code&gt;true&lt;/code&gt;, &lt;code&gt;True&lt;/code&gt;, &lt;code&gt;TRUE&lt;/code&gt;는 같은 이름이 아닙니다. 더 중요한 점은 소문자 &lt;code&gt;true&lt;/code&gt;의 지위도 표준 버전에 따라 다르다는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C11에서는 &lt;code&gt;&amp;lt;stdbool.h&amp;gt;&lt;/code&gt;가 &lt;code&gt;bool&lt;/code&gt;, &lt;code&gt;true&lt;/code&gt;, &lt;code&gt;false&lt;/code&gt;를 매크로로 제공합니다. 근거: &lt;a href=&quot;https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;WG14 N1570(C11) &amp;sect;7.18&lt;/a&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C23에서는 &lt;code&gt;true&lt;/code&gt;와 &lt;code&gt;false&lt;/code&gt;가 &lt;code&gt;bool&lt;/code&gt;형의 미리 정의된 상수 키워드입니다. 근거: &lt;a href=&quot;https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;WG14 N3096(C23) &amp;sect;6.4.1, &amp;sect;6.4.4.5&lt;/a&gt;.&lt;/p&gt;
&lt;span class=&quot;hb-code-label&quot;&gt;C11&lt;/span&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;stdbool.h&amp;gt;

bool done = true;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;&lt;code&gt;if&lt;/code&gt; 뒤의 세미콜론을 장식처럼 보기&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세미콜론은 문장의 마침표입니다. &lt;code&gt;if (조건);&lt;/code&gt;에서는 세미콜론 하나가 아무 작업도 하지 않는 빈 문장을 만들고, 그것이 &lt;code&gt;if&lt;/code&gt;의 본문이 됩니다.&lt;/p&gt;
&lt;span class=&quot;hb-code-label&quot;&gt;C&lt;/span&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;if (score &amp;gt;= 60)
    ;              /* 조건문의 빈 본문 */

result = 1;        /* 조건문 밖: 항상 실행 */&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;들여쓰기는 사람이 읽기 좋게 만든 모양일 뿐 실행 범위를 정하지 않습니다. 정확한 범위는 세미콜론과 중괄호가 결정합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;B. 주소와 값&lt;/h3&gt;
&lt;div class=&quot;hb-number-list&quot; role=&quot;list&quot;&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;3&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;&lt;code&gt;&amp;amp;&lt;/code&gt;와 &lt;code&gt;*&lt;/code&gt;를 둘 다 포인터 기호라고만 외우기&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단항 &lt;code&gt;&amp;amp;&lt;/code&gt;는 객체의 주소를 얻고, 단항 &lt;code&gt;*&lt;/code&gt;는 포인터가 가리키는 객체를 지정합니다. 사물함 비유로 보면 &lt;code&gt;&amp;amp;value&lt;/code&gt;는 사물함 번호표를 받는 일이고, &lt;code&gt;*p&lt;/code&gt;는 &lt;code&gt;p&lt;/code&gt;에 적힌 번호의 사물함을 여는 일입니다.&lt;/p&gt;
&lt;span class=&quot;hb-code-label&quot;&gt;C&lt;/span&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;int value = 10;
int *p = &amp;amp;value;&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;hb-card-grid&quot;&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;&lt;code&gt;p&lt;/code&gt;&lt;/span&gt; &lt;b&gt;&lt;code&gt;value&lt;/code&gt;의 주소&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;&lt;code&gt;*p&lt;/code&gt;&lt;/span&gt; &lt;b&gt;그 주소에 저장된 값 10&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;&lt;code&gt;*&amp;amp;value&lt;/code&gt;&lt;/span&gt; &lt;b&gt;같은 객체를 다시 지정하므로 값은 10&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;4&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;배열 이름을 포인터 변수와 완전히 같다고 보기&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열 식은 대부분의 식에서 첫 원소를 가리키는 포인터로 변환됩니다.&lt;/p&gt;
&lt;span class=&quot;hb-code-label&quot;&gt;C&lt;/span&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int a[] = {10, 20, 30};
int *p = a;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 배열 객체와 포인터 변수는 서로 다른 객체입니다. 특히 &lt;code&gt;sizeof(a)&lt;/code&gt;와 단항 &lt;code&gt;&amp;amp;a&lt;/code&gt;에서는 배열이 첫 원소 포인터로 변환되지 않습니다. &lt;code&gt;sizeof(a)&lt;/code&gt;는 배열 전체 크기를 구하고, &lt;code&gt;&amp;amp;a&lt;/code&gt;는 배열 전체를 가리키는 포인터가 됩니다. 근거: &lt;a href=&quot;https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;WG14 N1570(C11) &amp;sect;6.3.2.1&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;5&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;&lt;code&gt;a[i]&lt;/code&gt;와 &lt;code&gt;*(a + i)&lt;/code&gt;를 별개 문법으로 보기&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열 첨자는 포인터 덧셈과 역참조를 합친 표기입니다.&lt;/p&gt;
&lt;span class=&quot;hb-code-label&quot;&gt;관계식&lt;/span&gt;
&lt;pre class=&quot;gcode&quot;&gt;&lt;code&gt;a[i] == *(a + i)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;a + i&lt;/code&gt;로 i번째 원소의 위치를 구하고, &lt;code&gt;*&lt;/code&gt;로 그 위치의 값을 읽습니다. 근거: &lt;a href=&quot;https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;WG14 N1570(C11) &amp;sect;6.5.2.1&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;C. 자료형과 평가 시점&lt;/h3&gt;
&lt;div class=&quot;hb-number-list&quot; role=&quot;list&quot;&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;6&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;포인터의 &lt;code&gt;+1&lt;/code&gt;을 1바이트로 계산하기&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;p + 1&lt;/code&gt;은 주소 숫자에 무조건 1을 더한다는 뜻이 아니라, 같은 배열에서 가리키는 자료형의 다음 원소로 이동한다는 뜻입니다.&lt;/p&gt;
&lt;div class=&quot;hb-card-grid&quot;&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;&lt;code&gt;char *p&lt;/code&gt;&lt;/span&gt; &lt;b&gt;&lt;code&gt;char&lt;/code&gt; 한 칸&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;&lt;code&gt;int *p&lt;/code&gt;&lt;/span&gt; &lt;b&gt;&lt;code&gt;int&lt;/code&gt; 한 칸&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;&lt;code&gt;double *p&lt;/code&gt;&lt;/span&gt; &lt;b&gt;&lt;code&gt;double&lt;/code&gt; 한 칸&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 바이트 수는 해당 구현의 &lt;code&gt;sizeof(*p)&lt;/code&gt;에 달려 있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;7&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;문자열의 보이는 글자만 배열 원소로 세기&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자열 리터럴로 배열을 초기화하면 끝을 표시하는 널 문자 &lt;code&gt;\0&lt;/code&gt;가 함께 저장됩니다.&lt;/p&gt;
&lt;span class=&quot;hb-code-label&quot;&gt;C&lt;/span&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;char word[] = &quot;Apple&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;word&lt;/code&gt;에는 &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;p&lt;/code&gt;, &lt;code&gt;p&lt;/code&gt;, &lt;code&gt;l&lt;/code&gt;, &lt;code&gt;e&lt;/code&gt;, &lt;code&gt;\0&lt;/code&gt;의 여섯 원소가 들어가므로 &lt;code&gt;sizeof(word)&lt;/code&gt;는 6입니다. 반면 &lt;code&gt;char *p = &quot;Apple&quot;; sizeof(p)&lt;/code&gt;는 문자열 길이가 아니라 포인터 자체 크기입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;8&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;후위 감소를 감소한 값으로 읽기&lt;/b&gt; &lt;span class=&quot;hb-code-label&quot;&gt;C&lt;/span&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;int a = 5;
int b = a--;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후위 감소식 &lt;code&gt;a--&lt;/code&gt;의 결과값은 감소 전 값 5입니다. 따라서 &lt;code&gt;b&lt;/code&gt;에는 5가 들어가고, 저장된 &lt;code&gt;a&lt;/code&gt;는 그 뒤 4가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전위 감소 &lt;code&gt;--a&lt;/code&gt;는 먼저 감소한 값을 식의 결과로 사용합니다. 시험에서는 식이 내보낸 값과 문장이 끝난 뒤 저장된 값을 두 칸으로 나눠 적습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;aside class=&quot;hb-callout is-warning&quot;&gt;&lt;b&gt;보충 함정: 왼쪽 시프트는 항상 2의 거듭제곱을 곱하는 것이 아닙니다&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;1u &amp;lt;&amp;lt; 3&lt;/code&gt;은 8이지만, 시프트 횟수가 음수이거나 승격된 왼쪽 피연산자의 비트 폭 이상이면 동작이 정의되지 않습니다. C11에서 부호 있는 값을 왼쪽 시프트할 때도 값이 음수이거나 결과를 해당 타입으로 표현할 수 없으면 동작이 정의되지 않습니다. 근거: &lt;a href=&quot;https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;WG14 N1570(C11) &amp;sect;6.5.7&lt;/a&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class=&quot;hb-callout is-good&quot;&gt;&lt;b&gt;내 식으로 다시 설명하면&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C 코드는 줄 모양이 아니라 문장 부호로 범위를 찾고, 포인터는 주소를 먼저 적은 뒤 값을 꺼내며, 마지막에 자료형의 보폭과 연산 결과가 나오는 시점을 확인하는 문제입니다.&lt;/p&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id=&quot;hb-code-trace&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;코드와 값의 흐름&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;언어는 C입니다. &lt;code&gt;a&lt;/code&gt;의 원소 자료형은 &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;p&lt;/code&gt;는 &lt;code&gt;int *&lt;/code&gt;, &lt;code&gt;result&lt;/code&gt;는 &lt;code&gt;int&lt;/code&gt;입니다.&lt;/p&gt;
&lt;span class=&quot;hb-code-label&quot;&gt;C &amp;middot; 통합 예제&lt;/span&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

int main(void) {
    int a[] = {10, 20, 30};
    int *p = a;
    int result = *p;

    if (*(p + 1) == 999);
        result = a[2];

    printf(&quot;%d %zu\n&quot;, result, sizeof(&quot;Apple&quot;));
    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;통합 C 코드 실행 흐름&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;순서&lt;/th&gt;
&lt;th&gt;실행 내용&lt;/th&gt;
&lt;th&gt;변수&amp;middot;메모리 값&lt;/th&gt;
&lt;th&gt;출력&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;1&lt;/th&gt;
&lt;td&gt;&lt;code&gt;a&lt;/code&gt; 배열 생성&lt;/td&gt;
&lt;td&gt;&lt;code&gt;a[0]=10&lt;/code&gt;, &lt;code&gt;a[1]=20&lt;/code&gt;, &lt;code&gt;a[2]=30&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;2&lt;/th&gt;
&lt;td&gt;&lt;code&gt;p = a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;p&lt;/code&gt;는 &lt;code&gt;a[0]&lt;/code&gt;를 가리킴&lt;/td&gt;
&lt;td&gt;없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;3&lt;/th&gt;
&lt;td&gt;&lt;code&gt;result = *p&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;result=10&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;4&lt;/th&gt;
&lt;td&gt;&lt;code&gt;*(p + 1) == 999&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*(p+1)=20&lt;/code&gt;, 조건은 거짓&lt;/td&gt;
&lt;td&gt;없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;5&lt;/th&gt;
&lt;td&gt;&lt;code&gt;if&lt;/code&gt; 뒤의 &lt;code&gt;;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;조건문의 본문은 빈 문장&lt;/td&gt;
&lt;td&gt;없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;6&lt;/th&gt;
&lt;td&gt;&lt;code&gt;result = a[2]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;조건문 밖이므로 &lt;code&gt;result=30&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;7&lt;/th&gt;
&lt;td&gt;&lt;code&gt;sizeof(&quot;Apple&quot;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;종단 널을 포함해 6&lt;/td&gt;
&lt;td&gt;&lt;code&gt;30 6&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;aside class=&quot;hb-callout is-good&quot;&gt;&lt;b&gt;최종 출력&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;30 6&lt;/code&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id=&quot;hb-exam-application&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기출 유형에 적용하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 두 문제는 실제 기출 원문이나 사용자의 실제 오답이 아닙니다. 본문과 같은 출제 원리를 낯선 코드에 적용하기 위해 새로 만든 &lt;b&gt;기출형 예제&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기출형 예제 1. 기준 포인터가 이미 이동했다면&lt;/h3&gt;
&lt;span class=&quot;hb-code-label&quot;&gt;C &amp;middot; 재구성 예제&lt;/span&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

int main(void) {
    int data[] = {2, 4, 8, 16};
    int *p = data + 1;

    printf(&quot;%d %d\n&quot;, *p, *(p + 2));
    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;hb-card-grid&quot;&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;질문 형태&lt;/span&gt; &lt;b&gt;최종 출력 두 값을 구합니다.&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;흔한 오답&lt;/span&gt; &lt;b&gt;&lt;code&gt;p+2&lt;/code&gt;를 배열 처음 기준으로 읽어 &lt;code&gt;4 8&lt;/code&gt;이라고 답하기 쉽습니다.&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;정답&lt;/span&gt; &lt;b&gt;&lt;code&gt;4 16&lt;/code&gt;&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;추적:&lt;/b&gt; &lt;code&gt;p&lt;/code&gt;는 &lt;code&gt;data[1]&lt;/code&gt;의 주소입니다 &amp;rarr; &lt;code&gt;*p&lt;/code&gt;는 4입니다 &amp;rarr; &lt;code&gt;p+2&lt;/code&gt;는 현재 위치에서 &lt;code&gt;int&lt;/code&gt; 두 칸 뒤인 &lt;code&gt;data[3]&lt;/code&gt;을 가리킵니다 &amp;rarr; 값은 16입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기출형 예제 2. 거짓 조건, 빈 본문, 후위 감소&lt;/h3&gt;
&lt;span class=&quot;hb-code-label&quot;&gt;C &amp;middot; 재구성 예제&lt;/span&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

int main(void) {
    int a = 3;
    int b = 99;

    if (a-- == 0);
        b = a;

    printf(&quot;%d %d\n&quot;, a, b);
    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;hb-card-grid&quot;&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;질문 형태&lt;/span&gt; &lt;b&gt;조건이 거짓일 때 &lt;code&gt;a&lt;/code&gt;와 &lt;code&gt;b&lt;/code&gt;의 최종 값을 구합니다.&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;흔한 오답&lt;/span&gt; &lt;b&gt;&lt;code&gt;b&lt;/code&gt;가 99로 남거나 &lt;code&gt;a--&lt;/code&gt;가 2를 비교한다고 보기 쉽습니다.&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;span&gt;정답&lt;/span&gt; &lt;b&gt;&lt;code&gt;2 2&lt;/code&gt;&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;추적:&lt;/b&gt; &lt;code&gt;a--&lt;/code&gt;가 비교에 내보내는 값은 3이라 조건은 거짓입니다 &amp;rarr; 저장된 &lt;code&gt;a&lt;/code&gt;는 2가 됩니다 &amp;rarr; 세미콜론이 &lt;code&gt;if&lt;/code&gt;의 빈 본문입니다 &amp;rarr; &lt;code&gt;b=a&lt;/code&gt;는 조건문 밖에서 실행되어 &lt;code&gt;b=2&lt;/code&gt;가 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시험장에서 재현할 풀이 순서&lt;/h3&gt;
&lt;div class=&quot;hb-number-list&quot; role=&quot;list&quot;&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;문장 경계 표시&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;;&lt;/code&gt;, &lt;code&gt;{&lt;/code&gt;, &lt;code&gt;}&lt;/code&gt;를 표시해 실제 실행 범위를 찾습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;이름의 조건 확인&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;표준 버전과 헤더가 이름의 의미에 영향을 주는지 확인합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;3&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;주소와 값 분리&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주소 식과 값 식을 분리하고 현재 포인터의 기준 위치를 적습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;4&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;자료형과 크기 확인&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포인터 자료형, 배열 변환 예외, &lt;code&gt;sizeof&lt;/code&gt;의 대상을 확인합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;5&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;평가 전후 값 분리&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후위 증감은 식의 결과와 다음 저장값을 따로 기록합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id=&quot;hb-memory-cards&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시험 직전 암기 카드&lt;/h2&gt;
&lt;div class=&quot;hb-card-grid&quot;&gt;
&lt;div class=&quot;hb-memory-card&quot;&gt;&lt;b&gt;카드 1 &amp;middot; &lt;code&gt;true&lt;/code&gt;&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;질문:&lt;/b&gt; C11에서 표준 &lt;code&gt;true&lt;/code&gt;를 쓰려면?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 답:&lt;/b&gt; &lt;code&gt;&amp;lt;stdbool.h&amp;gt;&lt;/code&gt; 포함 여부를 확인합니다. C23에서는 미리 정의된 상수 키워드입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-memory-card&quot;&gt;&lt;b&gt;카드 2 &amp;middot; 빈 문장&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;질문:&lt;/b&gt; &lt;code&gt;if (조건);&lt;/code&gt;의 본문은?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 답:&lt;/b&gt; 세미콜론 하나로 된 빈 문장입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-memory-card&quot;&gt;&lt;b&gt;카드 3 &amp;middot; 주소와 역참조&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;질문:&lt;/b&gt; &lt;code&gt;&amp;amp;x&lt;/code&gt;와 &lt;code&gt;*p&lt;/code&gt;는?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 답:&lt;/b&gt; &lt;code&gt;&amp;amp;x&lt;/code&gt;는 주소, &lt;code&gt;*p&lt;/code&gt;는 가리키는 객체 또는 그 값입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-memory-card&quot;&gt;&lt;b&gt;카드 4 &amp;middot; 배열 변환&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;질문:&lt;/b&gt; 대표적인 변환 예외는?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 답:&lt;/b&gt; 배열이 &lt;code&gt;sizeof&lt;/code&gt; 또는 단항 &lt;code&gt;&amp;amp;&lt;/code&gt;의 피연산자일 때입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-memory-card&quot;&gt;&lt;b&gt;카드 5 &amp;middot; 배열 첨자&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;질문:&lt;/b&gt; &lt;code&gt;a[i]&lt;/code&gt;와 같은 원리의 식은?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 답:&lt;/b&gt; &lt;code&gt;*(a + i)&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-memory-card&quot;&gt;&lt;b&gt;카드 6 &amp;middot; 포인터 보폭&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;질문:&lt;/b&gt; &lt;code&gt;p+1&lt;/code&gt;은 몇 바이트 이동하는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 답:&lt;/b&gt; 가리키는 자료형의 원소 한 칸입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-memory-card&quot;&gt;&lt;b&gt;카드 7 &amp;middot; 문자열 널&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;질문:&lt;/b&gt; &lt;code&gt;sizeof(&quot;Apple&quot;)&lt;/code&gt;은?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 답:&lt;/b&gt; 종단 널까지 포함해 6입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-memory-card&quot;&gt;&lt;b&gt;카드 8 &amp;middot; 후위 감소&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;질문:&lt;/b&gt; &lt;code&gt;int b = a--;&lt;/code&gt;에서 &lt;code&gt;b&lt;/code&gt;가 받는 값은?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 답:&lt;/b&gt; 감소 전 &lt;code&gt;a&lt;/code&gt;의 값입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id=&quot;hb-mini-quiz&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;미니 퀴즈&lt;/h2&gt;
&lt;div class=&quot;hb-number-list&quot; role=&quot;list&quot;&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;&lt;code&gt;true&lt;/code&gt;의 표준 버전&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C11에서 표준 &lt;code&gt;bool&lt;/code&gt;과 &lt;code&gt;true&lt;/code&gt;를 사용하려면 어떤 헤더가 필요한가?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;빈 문장&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;if (0); x = 1;&lt;/code&gt;에서 &lt;code&gt;x = 1;&lt;/code&gt;은 언제 실행되는가?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;3&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;주소와 역참조&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;int x = 7; int *p = &amp;amp;x;&lt;/code&gt;에서 &lt;code&gt;*&amp;amp;x&lt;/code&gt;와 &lt;code&gt;*p&lt;/code&gt;의 값은?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;4&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;배열 변환 예외&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;int a[3];&lt;/code&gt;에서 배열이 첫 원소 포인터로 변환되지 않는 대표 식 두 개는?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;5&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;배열 첨자&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;int a[] = {3, 6, 9};&lt;/code&gt;일 때 &lt;code&gt;*(a + 2)&lt;/code&gt;의 값은?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;6&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;포인터 보폭&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;int *p&lt;/code&gt;의 &lt;code&gt;p + 1&lt;/code&gt;은 무엇을 기준으로 이동하는가?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;7&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;문자열 널&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;char word[] = &quot;C&quot;;&lt;/code&gt;일 때 &lt;code&gt;sizeof(word)&lt;/code&gt;는?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;8&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;후위 감소&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;int a = 5; int b = a--;&lt;/code&gt;가 끝난 뒤 &lt;code&gt;a&lt;/code&gt;와 &lt;code&gt;b&lt;/code&gt;의 값은?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;details&gt;
&lt;summary&gt;정답과 해설 확인하기&lt;/summary&gt;
&lt;div class=&quot;hb-number-list&quot; role=&quot;list&quot;&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;&lt;code&gt;&amp;lt;stdbool.h&amp;gt;&lt;/code&gt;&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C11에서는 해당 헤더를 포함합니다. C23의 &lt;code&gt;true&lt;/code&gt;는 미리 정의된 상수 키워드입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;조건과 관계없이 실행&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;if&lt;/code&gt;의 본문은 세미콜론으로 끝난 빈 문장입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;3&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;둘 다 7&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;amp;x&lt;/code&gt;로 주소를 얻고 &lt;code&gt;*&lt;/code&gt;로 그 주소의 값을 읽습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;4&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;&lt;code&gt;sizeof(a)&lt;/code&gt;와 &lt;code&gt;&amp;amp;a&lt;/code&gt;&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 문맥에서는 배열 자체가 남습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;5&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;9&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;*(a+2)&lt;/code&gt;는 &lt;code&gt;a[2]&lt;/code&gt;와 같습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;6&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;&lt;code&gt;int&lt;/code&gt; 원소 한 칸&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 바이트 수는 구현의 &lt;code&gt;sizeof(int)&lt;/code&gt;에 달려 있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;7&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;2&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자 &lt;code&gt;C&lt;/code&gt;와 종단 널 문자 &lt;code&gt;\0&lt;/code&gt;가 들어갑니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-number-item&quot; role=&quot;listitem&quot;&gt;&lt;span class=&quot;hb-number-badge&quot;&gt;8&lt;/span&gt;
&lt;div class=&quot;hb-number-body&quot;&gt;&lt;b&gt;&lt;code&gt;a=4&lt;/code&gt;, &lt;code&gt;b=5&lt;/code&gt;&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후위 감소식은 감소 전 값을 먼저 결과로 사용합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/details&gt;&lt;/section&gt;
&lt;section id=&quot;hb-closing&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;오늘의 학습 회고&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오늘 이해한 것:&lt;/b&gt; 암기 문장보다 적용 조건을 함께 외워야 합니다. 배열 이름은 &amp;ldquo;포인터다&amp;rdquo;가 아니라 &amp;ldquo;대부분의 식에서 첫 원소 포인터로 변환된다&amp;rdquo;가 정확하고, 후위 감소도 식의 결과와 저장된 다음 값을 분리하면 흔들리지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;아직 헷갈리는 것:&lt;/b&gt; 2차원 배열에서 &lt;code&gt;int (*p)[N]&lt;/code&gt;의 보폭과 배열 포인터&amp;middot;포인터 배열의 선언 모양입니다. 이 글에서는 범위를 억지로 확장하지 않고 다음 학습으로 남깁니다.&lt;/p&gt;
&lt;p class=&quot;hb-footer-note&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다음 학습:&lt;/b&gt; 문서 3절의 오버로딩&amp;middot;오버라이딩&amp;middot;접근 제어자&amp;middot;가상 함수와 4절의 예외 처리를 별도 글로 정리합니다.&lt;/p&gt;
&lt;div class=&quot;hb-references&quot;&gt;&lt;b&gt;참고 자료&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인 학습 자료: &lt;code&gt;정처기_수제비_오답노트.docx&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;WG14 N1570 &amp;mdash; C11 committee draft&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;WG14 N3096 &amp;mdash; C23 working draft&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/article&gt;</description>
      <category>AI/정보처리기사_스터디</category>
      <category>c언어</category>
      <category>오답노트</category>
      <category>정보처리기사</category>
      <category>정보처리기사실기</category>
      <category>정처기</category>
      <category>포인터</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/117</guid>
      <comments>https://onethingflow.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%8B%A4%EA%B8%B0-C%EC%96%B8%EC%96%B4-%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8-%EC%8B%9C%ED%97%98%EC%9E%A5%EC%97%90%EC%84%9C-%ED%8B%80%EB%A6%AC%EA%B8%B0-%EC%89%AC%EC%9A%B4-8%EA%B0%80%EC%A7%80-%ED%95%A8%EC%A0%95#entry117comment</comments>
      <pubDate>Fri, 17 Jul 2026 10:01:26 +0900</pubDate>
    </item>
    <item>
      <title>정처기 4일차 수제비: 기본문법 활용 기출 4유형 풀이법</title>
      <link>https://onethingflow.tistory.com/entry/%EC%A0%95%EC%B2%98%EA%B8%B0-4%EC%9D%BC%EC%B0%A8-%EC%88%98%EC%A0%9C%EB%B9%84-%EA%B8%B0%EB%B3%B8%EB%AC%B8%EB%B2%95-%ED%99%9C%EC%9A%A9-%EA%B8%B0%EC%B6%9C-4%EC%9C%A0%ED%98%95-%ED%92%80%EC%9D%B4%EB%B2%95</link>
      <description>&lt;meta charset=&quot;utf-8&quot;&gt;

&lt;!--
티스토리 제목 추천:
정처기 4일차 수제비: 기본문법 활용 기출 4유형 풀이법

메타 설명 추천:
정보처리기사 필기 4과목 기본문법 활용 지피지기 기출문제 범위(p.4-56~p.4-78)를 초보자용으로 재구성했습니다. Java와 C의 조건식 차이, 전위와 후위 증감, switch 폴스루, 1차원과 2차원 배열 포인터를 코드 추적표와 미니 퀴즈로 정리합니다.

태그 추천:
정보처리기사, 정처기, 수제비, 프로그래밍언어활용, 기본문법, 기출문제, C언어, Java, 증감연산자, switch문, 배열, 포인터, 2차원배열
--&gt;

&lt;style&gt;
.hb-post {
  --hb-ink: #172033;
  --hb-muted: #657085;
  --hb-line: #dfe6ef;
  --hb-soft: #f5f8fc;
  --hb-blue: #315efb;
  --hb-blue-soft: #eef3ff;
  --hb-green: #17876d;
  --hb-green-soft: #edf9f5;
  --hb-amber: #a86400;
  --hb-amber-soft: #fff8e8;
  --hb-red: #b63b3b;
  --hb-red-soft: #fff3f3;
  max-width: 780px;
  margin: 0 auto;
  color: var(--hb-ink);
  font-size: 17px;
  line-height: 1.82;
  word-break: keep-all;
  overflow-wrap: break-word;
}

.hb-post,
.hb-post * {
  box-sizing: border-box;
}

.hb-post h1,
.hb-post h2,
.hb-post h3,
.hb-post p,
.hb-post figure,
.hb-post blockquote {
  margin-top: 0;
}

.hb-post h1 {
  margin-bottom: .65em;
  font-size: clamp(1.72rem, 5vw, 2.2rem);
  line-height: 1.28;
  letter-spacing: -.035em;
}

.hb-post h2 {
  margin: 2.5em 0 .85em;
  padding-bottom: .38em;
  border-bottom: 2px solid #edf1f6;
  font-size: 1.38em;
  line-height: 1.4;
  letter-spacing: -.02em;
}

.hb-post h3 {
  margin: 1.65em 0 .65em;
  font-size: 1.1em;
  line-height: 1.45;
}

.hb-post p {
  margin-bottom: 1.08em;
}

.hb-post a {
  color: #2855c7;
  text-decoration: none;
  border-bottom: 1px solid rgba(40, 85, 199, .28);
}

.hb-post code {
  padding: .08em .34em;
  border-radius: 4px;
  background: #f0f3f7;
  color: #25334d;
  font-family: Consolas, Monaco, &quot;Courier New&quot;, monospace;
  font-size: .92em;
  overflow-wrap: anywhere;
}

.hb-post pre {
  margin: 1em 0 1.25em;
  padding: 1.05em 1.1em;
  overflow-x: auto;
  border: 1px solid #263247;
  border-radius: 10px;
  background: #111827;
  color: #f5f7fb;
  font-size: .9em;
  line-height: 1.66;
  -webkit-overflow-scrolling: touch;
}

.hb-post pre code {
  padding: 0;
  background: transparent;
  color: inherit;
  font-size: 1em;
  white-space: pre;
  word-break: normal;
  overflow-wrap: normal;
}

.hb-post .hb-nowrap {
  white-space: nowrap;
}

.hb-post .hb-hero {
  margin-bottom: 1.4em;
  padding: 1.45em 1.5em;
  border: 1px solid #d9e3f2;
  border-radius: 14px;
  background:
    radial-gradient(circle at 90% 10%, rgba(49, 94, 251, .13), transparent 35%),
    linear-gradient(135deg, #f7faff 0%, #ffffff 66%, #fffaf0 100%);
}

.hb-post .hb-eyebrow {
  display: inline-block;
  margin-bottom: .75em;
  padding: .26em .72em;
  border: 1px solid #d5def0;
  border-radius: 999px;
  background: #fff;
  color: #466080;
  font-size: .82em;
  font-weight: 800;
}

.hb-post .hb-lead {
  margin-bottom: .7em;
  color: #344054;
  font-size: 1.06em;
}

.hb-post .hb-hero-foot {
  margin-bottom: 0;
  color: var(--hb-muted);
  font-size: .92em;
}

.hb-post .hb-key-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: .72em;
  margin: 1.25em 0 1.6em;
}

.hb-post .hb-key-card {
  min-width: 0;
  padding: .9em;
  border: 1px solid var(--hb-line);
  border-radius: 10px;
  background: #fff;
}

.hb-post .hb-key-label {
  display: block;
  margin-bottom: .25em;
  color: var(--hb-muted);
  font-size: .76em;
  font-weight: 700;
}

.hb-post .hb-key-value {
  display: block;
  font-size: .95em;
  line-height: 1.45;
}

.hb-post .hb-callout {
  margin: 1.3em 0;
  padding: 1em 1.08em;
  border: 1px solid #dbe4f3;
  border-left: 4px solid var(--hb-blue);
  border-radius: 9px;
  background: #f8fbff;
}

.hb-post .hb-callout strong,
.hb-post .hb-warning strong,
.hb-post .hb-correct strong,
.hb-post .hb-source-note strong {
  display: block;
  margin-bottom: .35em;
}

.hb-post .hb-callout p,
.hb-post .hb-warning p,
.hb-post .hb-correct p,
.hb-post .hb-source-note p {
  margin-bottom: 0;
}

.hb-post .hb-warning {
  margin: 1.3em 0;
  padding: 1em 1.08em;
  border: 1px solid #f0d7d7;
  border-left: 4px solid var(--hb-red);
  border-radius: 9px;
  background: var(--hb-red-soft);
}

.hb-post .hb-correct {
  margin: 1.3em 0;
  padding: 1em 1.08em;
  border: 1px solid #d4eadf;
  border-left: 4px solid var(--hb-green);
  border-radius: 9px;
  background: var(--hb-green-soft);
}

.hb-post .hb-source-note {
  margin: 1.3em 0;
  padding: .95em 1.05em;
  border: 1px solid #eadfbd;
  border-left: 4px solid #d39114;
  border-radius: 9px;
  background: var(--hb-amber-soft);
  color: #594411;
  font-size: .94em;
}

.hb-post .hb-number-list {
  display: grid;
  gap: .78em;
  margin: 1.2em 0 1.55em;
}

.hb-post .hb-number-item {
  display: grid;
  grid-template-columns: 42px minmax(0, 1fr);
  gap: .85em;
  align-items: start;
  min-width: 0;
  padding: .92em 1em;
  border: 1px solid var(--hb-line);
  border-radius: 10px;
  background: #fff;
}

.hb-post .hb-number-badge {
  display: inline-flex;
  width: 38px;
  height: 38px;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  background: var(--hb-blue);
  color: #fff;
  font-weight: 900;
  line-height: 1;
}

.hb-post .hb-number-body {
  min-width: 0;
}

.hb-post .hb-number-title {
  display: block;
  margin-bottom: .2em;
  line-height: 1.42;
}

.hb-post .hb-number-desc {
  margin: 0;
  color: #526075;
  font-size: .94em;
  line-height: 1.62;
}

.hb-post .hb-table-wrap {
  margin: 1.2em 0 1.5em;
  overflow-x: auto;
  border-radius: 9px;
  -webkit-overflow-scrolling: touch;
}

.hb-post table {
  width: 100%;
  min-width: 620px;
  border-collapse: collapse;
  border: 1px solid var(--hb-line);
  background: #fff;
  font-size: .94em;
}

.hb-post caption {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.hb-post th,
.hb-post td {
  padding: .72em .76em;
  border: 1px solid var(--hb-line);
  text-align: left;
  vertical-align: top;
}

.hb-post th {
  background: #f4f7fb;
  color: #2d3a50;
  font-weight: 800;
}

.hb-post tbody tr:nth-child(even) {
  background: #fbfcfe;
}

.hb-post .hb-formula {
  margin: 1.1em 0;
  padding: .95em 1em;
  border: 1px solid #dce4f0;
  border-radius: 9px;
  background: var(--hb-soft);
  text-align: center;
  font-size: 1.04em;
  font-weight: 800;
}

.hb-post .hb-memory-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: .6em;
  margin: 1em 0 1.35em;
}

.hb-post .hb-memory-cell {
  min-width: 0;
  padding: .78em .7em;
  border: 1px solid #cfd9e8;
  border-radius: 8px;
  background: #f8fbff;
  text-align: center;
}

.hb-post .hb-memory-index {
  display: block;
  color: var(--hb-muted);
  font-size: .78em;
  white-space: nowrap;
}

.hb-post .hb-memory-value {
  display: block;
  margin-top: .15em;
  font-size: 1.12em;
  font-weight: 900;
}

.hb-post .hb-quiz {
  display: grid;
  gap: .72em;
  margin: 1.15em 0;
}

.hb-post .hb-quiz-card {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr);
  gap: .75em;
  align-items: start;
  padding: .85em .95em;
  border: 1px solid var(--hb-line);
  border-radius: 9px;
  background: #fff;
}

.hb-post .hb-quiz-num {
  display: inline-flex;
  width: 32px;
  height: 32px;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: #eaf0ff;
  color: #294fbf;
  font-weight: 900;
  line-height: 1;
}

.hb-post .hb-quiz-card p {
  margin: 0;
}

.hb-post details {
  margin: 1.15em 0;
  padding: .9em 1em;
  border: 1px solid #d7e2f3;
  border-radius: 9px;
  background: #f8fbff;
}

.hb-post summary {
  cursor: pointer;
  font-weight: 800;
}

.hb-post .hb-answer-grid {
  display: grid;
  gap: .65em;
  margin-top: .9em;
}

.hb-post .hb-answer {
  padding: .75em .8em;
  border-radius: 8px;
  background: #fff;
}

.hb-post .hb-answer p {
  margin: 0;
}

.hb-post .hb-reference-list {
  display: grid;
  gap: .58em;
  margin: 1em 0 1.4em;
}

.hb-post .hb-reference-item {
  padding: .72em .82em;
  border: 1px solid var(--hb-line);
  border-radius: 8px;
  background: #fff;
}

.hb-post .hb-footer-note {
  margin-top: 1.7em;
  padding-top: 1.1em;
  border-top: 1px solid #e8edf3;
  color: #737d8d;
  font-size: .87em;
}

@media (max-width: 680px) {
  .hb-post {
    font-size: 16px;
    line-height: 1.76;
    word-break: normal;
  }

  .hb-post h1,
  .hb-post h2,
  .hb-post h3 {
    word-break: keep-all;
  }

  .hb-post .hb-hero {
    padding: 1.15em 1em;
  }

  .hb-post .hb-key-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .hb-post .hb-number-item {
    grid-template-columns: 36px minmax(0, 1fr);
    gap: .68em;
    padding: .82em;
  }

  .hb-post .hb-number-badge {
    width: 34px;
    height: 34px;
  }

  .hb-post .hb-memory-grid {
    grid-template-columns: repeat(3, minmax(76px, 1fr));
    overflow-x: auto;
    padding-bottom: .2em;
  }

  .hb-post .hb-quiz-card {
    grid-template-columns: 32px minmax(0, 1fr);
    padding: .78em;
  }
}
&lt;/style&gt;

&lt;article class=&quot;hb-post&quot;&gt;
  &lt;header class=&quot;hb-hero&quot;&gt;
    &lt;span class=&quot;hb-eyebrow&quot;&gt;정보처리기사 필기 4일차 · p.4-56~p.4-78&lt;/span&gt;
    &lt;h1&gt;정처기 수제비 기본문법 활용 기출 4유형 풀이법&lt;/h1&gt;
    &lt;p class=&quot;hb-lead&quot;&gt;이번 범위는 새 이론을 넓게 외우는 구간이라기보다, 지금까지 배운 문법을 코드 출력 문제에 적용하는 연습 구간입니다. 핵심은 계산을 빨리 하는 것이 아니라 &lt;strong&gt;언어, 자료형, 연산 시점, 포인터 이동 단위&lt;/strong&gt;를 순서대로 확인하는 것입니다.&lt;/p&gt;
    &lt;p class=&quot;hb-hero-foot&quot;&gt;문제 문장은 그대로 옮기지 않고, 같은 출제 원리를 확인할 수 있는 새 예제로 재구성했습니다.&lt;/p&gt;
  &lt;/header&gt;

  &lt;div class=&quot;hb-key-grid&quot;&gt;
    &lt;div class=&quot;hb-key-card&quot;&gt;
      &lt;span class=&quot;hb-key-label&quot;&gt;첫 확인&lt;/span&gt;
      &lt;strong class=&quot;hb-key-value&quot;&gt;C인지 Java인지&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-key-card&quot;&gt;
      &lt;span class=&quot;hb-key-label&quot;&gt;증감식&lt;/span&gt;
      &lt;strong class=&quot;hb-key-value&quot;&gt;식에 쓰인 값과 저장값 분리&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-key-card&quot;&gt;
      &lt;span class=&quot;hb-key-label&quot;&gt;포인터&lt;/span&gt;
      &lt;strong class=&quot;hb-key-value&quot;&gt;한 칸의 자료형부터 확인&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-key-card&quot;&gt;
      &lt;span class=&quot;hb-key-label&quot;&gt;마지막&lt;/span&gt;
      &lt;strong class=&quot;hb-key-value&quot;&gt;출력 형식까지 검산&lt;/strong&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class=&quot;hb-source-note&quot;&gt;
    &lt;strong&gt;이 글의 정리 기준&lt;/strong&gt;
    &lt;p&gt;첨부 자료는 기출문제 원문보다 해설 메모에 가까웠습니다. 따라서 확인할 수 없는 선택지나 원문 표현은 복원하지 않고, C와 Java의 공식 문서와 대조해 정확한 개념만 남겼습니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2&gt;오늘 잡을 네 가지 기출 유형&lt;/h2&gt;

  &lt;div class=&quot;hb-number-list&quot;&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
      &lt;div class=&quot;hb-number-body&quot;&gt;
        &lt;strong class=&quot;hb-number-title&quot;&gt;언어별 조건식과 컴파일 가능 여부&lt;/strong&gt;
        &lt;p class=&quot;hb-number-desc&quot;&gt;C의 0과 0이 아닌 값 판정과 Java의 &lt;code&gt;boolean&lt;/code&gt; 조건을 구분합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
      &lt;div class=&quot;hb-number-body&quot;&gt;
        &lt;strong class=&quot;hb-number-title&quot;&gt;전위와 후위 증감 연산자&lt;/strong&gt;
        &lt;p class=&quot;hb-number-desc&quot;&gt;변수의 최종값과 주변 식에 제공되는 값을 따로 추적합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;3&lt;/span&gt;
      &lt;div class=&quot;hb-number-body&quot;&gt;
        &lt;strong class=&quot;hb-number-title&quot;&gt;&lt;code&gt;switch&lt;/code&gt;의 폴스루&lt;/strong&gt;
        &lt;p class=&quot;hb-number-desc&quot;&gt;&lt;code&gt;break&lt;/code&gt;가 없는 경우 다음 &lt;code&gt;case&lt;/code&gt;까지 실행되는 흐름을 읽습니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;4&lt;/span&gt;
      &lt;div class=&quot;hb-number-body&quot;&gt;
        &lt;strong class=&quot;hb-number-title&quot;&gt;1차원과 2차원 배열 및 포인터&lt;/strong&gt;
        &lt;p class=&quot;hb-number-desc&quot;&gt;주소 이동과 역참조를 배열 첨자식으로 바꾸어 계산합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;h2&gt;1. 값을 계산하기 전에 언어부터 확인한다&lt;/h2&gt;

  &lt;p&gt;비슷해 보이는 코드도 C와 Java에서 결과가 다를 수 있습니다. 특히 반복문의 조건식은 가장 먼저 확인해야 합니다.&lt;/p&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;C와 Java의 반복문 조건식 비교&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;언어&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;조건식 규칙&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;&lt;code&gt;while (count--)&lt;/code&gt;&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;C&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;0은 거짓, 0이 아니면 참으로 판단&lt;/td&gt;
          &lt;td&gt;정수형 &lt;code&gt;count&lt;/code&gt;라면 문법상 가능&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Java&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;boolean&lt;/code&gt; 또는 &lt;code&gt;Boolean&lt;/code&gt; 식만 허용&lt;/td&gt;
          &lt;td&gt;정수 결과이므로 컴파일 오류&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h3&gt;Java에서는 정수를 조건으로 쓸 수 없다&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;int count = 3;

while (count--) {       // 컴파일 오류
    System.out.println(count);
}&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;count--&lt;/code&gt;의 식 결과는 정수입니다. Java의 &lt;code&gt;while&lt;/code&gt;은 참·거짓 값만 요구하므로 이 코드는 실행 결과를 계산하기 전에 컴파일 오류로 판정해야 합니다.&lt;/p&gt;

  &lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;int count = 3;
int hits = 0;

while (count-- != 0) {  // boolean 식으로 수정
    hits++;
}

System.out.println(hits + &quot;, &quot; + count);
// 출력: 3, -1&lt;/code&gt;&lt;/pre&gt;

  &lt;div class=&quot;hb-correct&quot;&gt;
    &lt;strong&gt;본문은 3회, 조건 검사는 4회&lt;/strong&gt;
    &lt;p&gt;마지막 검사에서는 감소 전 값 0이 조건에 사용되어 본문에 들어가지 않습니다. 하지만 후위 감소식 자체는 평가되므로 &lt;code&gt;count&lt;/code&gt;의 최종값은 -1이 됩니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3&gt;같은 형태를 C에서 실행하면&lt;/h3&gt;

  &lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;#include &amp;lt;stdio.h&amp;gt;

int main(void) {
    int count = 3;
    int hits = 0;

    while (count--) {
        hits++;
    }

    printf(&quot;%d, %d\n&quot;, hits, count);
    return 0;
}
// 출력: 3, -1&lt;/code&gt;&lt;/pre&gt;

  &lt;div class=&quot;hb-callout&quot;&gt;
    &lt;strong&gt;시험 풀이 순서&lt;/strong&gt;
    &lt;p&gt;&lt;strong&gt;언어 확인 → 컴파일 가능 여부 → 값 추적&lt;/strong&gt; 순서로 풉니다. 컴파일되지 않는 Java 코드를 C 규칙으로 손계산하면 안 됩니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2&gt;2. 전위와 후위 증감은 두 값을 따로 본다&lt;/h2&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;전위와 후위 증감 연산자 비교&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;표현&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;식에 제공되는 값&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;변수에 저장되는 값&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;++x&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;1 증가한 새 값&lt;/td&gt;
          &lt;td&gt;새 값&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;x++&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;증가하기 전 값&lt;/td&gt;
          &lt;td&gt;1 증가한 값&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--x&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;1 감소한 새 값&lt;/td&gt;
          &lt;td&gt;새 값&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;x--&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;감소하기 전 값&lt;/td&gt;
          &lt;td&gt;1 감소한 값&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;#include &amp;lt;stdio.h&amp;gt;

int main(void) {
    int a = 4;
    int b = 6;
    int result = a++ + ++b;

    printf(&quot;%d, %d, %d\n&quot;, a, b, result);
    return 0;
}
// 출력: 5, 7, 11&lt;/code&gt;&lt;/pre&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;증감식 추적표&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;순서&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;해석&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;식에 쓰인 값&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;연산 후 저장값&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;1&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;a++&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;4&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;a = 5&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;2&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;++b&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;7&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;b = 7&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;3&lt;/td&gt;
          &lt;td&gt;덧셈과 대입&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;4 + 7&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;result = 11&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;div class=&quot;hb-warning&quot;&gt;
    &lt;strong&gt;C에서 같은 변수를 한 식에서 여러 번 바꾸지 말자&lt;/strong&gt;
    &lt;p&gt;&lt;code&gt;a++ + ++a&lt;/code&gt;처럼 같은 객체를 한 식에서 여러 번 수정하는 표현은 C에서 정의되지 않은 동작이 될 수 있습니다. 이런 코드는 특정 출력값을 외우지 말고 잘못된 코드로 구분하는 편이 안전합니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2&gt;3. &lt;code&gt;switch&lt;/code&gt;는 일치 지점부터 아래로 흐른다&lt;/h2&gt;

  &lt;p&gt;&lt;code&gt;switch&lt;/code&gt;는 일치하는 &lt;code&gt;case&lt;/code&gt;로 이동한 뒤, &lt;code&gt;break&lt;/code&gt;, &lt;code&gt;return&lt;/code&gt; 또는 블록의 끝을 만날 때까지 아래 문장을 계속 실행합니다. 다음 &lt;code&gt;case&lt;/code&gt;의 조건을 다시 검사하지 않습니다.&lt;/p&gt;

  &lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;#include &amp;lt;stdio.h&amp;gt;

int main(void) {
    int level = 2;

    switch (level) {
        case 1:
            printf(&quot;L&quot;);
        case 2:
            printf(&quot;M&quot;);
        case 3:
            printf(&quot;H&quot;);
            break;
        default:
            printf(&quot;?&quot;);
    }

    return 0;
}
// 출력: MH&lt;/code&gt;&lt;/pre&gt;

  &lt;div class=&quot;hb-number-list&quot;&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
      &lt;div class=&quot;hb-number-body&quot;&gt;
        &lt;strong class=&quot;hb-number-title&quot;&gt;&lt;code&gt;level&lt;/code&gt;은 2&lt;/strong&gt;
        &lt;p class=&quot;hb-number-desc&quot;&gt;&lt;code&gt;case 2&lt;/code&gt;로 바로 이동해 &lt;code&gt;M&lt;/code&gt;을 출력합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
      &lt;div class=&quot;hb-number-body&quot;&gt;
        &lt;strong class=&quot;hb-number-title&quot;&gt;&lt;code&gt;case 2&lt;/code&gt; 뒤에 &lt;code&gt;break&lt;/code&gt;가 없음&lt;/strong&gt;
        &lt;p class=&quot;hb-number-desc&quot;&gt;다음 라벨을 검사하지 않고 &lt;code&gt;case 3&lt;/code&gt;의 &lt;code&gt;H&lt;/code&gt;까지 출력합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;3&lt;/span&gt;
      &lt;div class=&quot;hb-number-body&quot;&gt;
        &lt;strong class=&quot;hb-number-title&quot;&gt;&lt;code&gt;case 3&lt;/code&gt;의 &lt;code&gt;break&lt;/code&gt;에서 종료&lt;/strong&gt;
        &lt;p class=&quot;hb-number-desc&quot;&gt;따라서 최종 출력은 &lt;code&gt;MH&lt;/code&gt;입니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class=&quot;hb-callout&quot;&gt;
    &lt;strong&gt;폴스루는 항상 실수일까?&lt;/strong&gt;
    &lt;p&gt;의도적으로 여러 &lt;code&gt;case&lt;/code&gt;를 묶을 때도 사용합니다. 다만 의도한 폴스루라면 주석으로 명확히 표시하는 것이 좋습니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2&gt;4. 1차원 배열은 주소와 값을 분리해서 본다&lt;/h2&gt;

  &lt;h3&gt;시험용 주소 계산 공식&lt;/h3&gt;

  &lt;div class=&quot;hb-formula&quot;&gt;원소 주소 = 시작 주소 + 인덱스 × 원소 크기&lt;/div&gt;

  &lt;p&gt;예를 들어 &lt;code&gt;int values[4]&lt;/code&gt;의 시작 주소가 1000이고, 문제에서 &lt;code&gt;int&lt;/code&gt; 크기를 4바이트라고 가정하면 &lt;code&gt;&amp;amp;values[3]&lt;/code&gt;의 주소는 &lt;code&gt;1000 + 3 × 4 = 1012&lt;/code&gt;입니다.&lt;/p&gt;

  &lt;div class=&quot;hb-memory-grid&quot;&gt;
    &lt;div class=&quot;hb-memory-cell&quot;&gt;
      &lt;span class=&quot;hb-memory-index&quot;&gt;&lt;code&gt;values[0]&lt;/code&gt;&lt;br&gt;주소 1000&lt;/span&gt;
      &lt;span class=&quot;hb-memory-value&quot;&gt;5&lt;/span&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-memory-cell&quot;&gt;
      &lt;span class=&quot;hb-memory-index&quot;&gt;&lt;code&gt;values[1]&lt;/code&gt;&lt;br&gt;주소 1004&lt;/span&gt;
      &lt;span class=&quot;hb-memory-value&quot;&gt;8&lt;/span&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-memory-cell&quot;&gt;
      &lt;span class=&quot;hb-memory-index&quot;&gt;&lt;code&gt;values[2]&lt;/code&gt;&lt;br&gt;주소 1008&lt;/span&gt;
      &lt;span class=&quot;hb-memory-value&quot;&gt;13&lt;/span&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class=&quot;hb-warning&quot;&gt;
    &lt;strong&gt;가상 주소와 실제 포인터 출력은 다르다&lt;/strong&gt;
    &lt;p&gt;숫자 주소를 직접 계산하는 것은 시험의 가정입니다. 실제 C 코드에서 포인터를 출력할 때는 &lt;code&gt;%u&lt;/code&gt;가 아니라 &lt;code&gt;%p&lt;/code&gt;를 사용하고, 인수는 &lt;code&gt;void *&lt;/code&gt;로 변환합니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;#include &amp;lt;stdio.h&amp;gt;

int main(void) {
    int values[4] = {5, 8, 13, 21};

    printf(&quot;%p\n&quot;, (void *)values);
    printf(&quot;%p\n&quot;, (void *)&amp;amp;values[3]);
    return 0;
}&lt;/code&gt;&lt;/pre&gt;

  &lt;h3&gt;배열 첨자는 포인터 연산으로 정의된다&lt;/h3&gt;

  &lt;div class=&quot;hb-formula&quot;&gt;&lt;code&gt;a[i]&lt;/code&gt; ⇔ &lt;code&gt;*(a + i)&lt;/code&gt;&lt;/div&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;1차원 배열의 주소식과 값식&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;표현&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;의미&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;종류&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;a + 2&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;세 번째 원소의 주소&lt;/td&gt;
          &lt;td&gt;포인터&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;*(a + 2)&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;세 번째 원소의 값&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;a[2]&lt;/code&gt;와 동치&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;&amp;amp;a[2]&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;세 번째 원소의 주소&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;a + 2&lt;/code&gt;와 동치&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;&amp;amp;a&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;배열 전체의 주소&lt;/td&gt;
          &lt;td&gt;포인터 형식과 이동 단위가 다름&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h3&gt;“배열 이름은 포인터다”는 절반만 맞다&lt;/h3&gt;

  &lt;p&gt;배열식 &lt;code&gt;a&lt;/code&gt;는 대부분의 식에서 첫 원소를 가리키는 &lt;code&gt;&amp;amp;a[0]&lt;/code&gt;로 자동 변환됩니다. 하지만 배열 객체와 포인터 변수는 같은 것이 아닙니다.&lt;/p&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;배열과 포인터 변수의 차이&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;구분&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;배열 &lt;code&gt;int a[4]&lt;/code&gt;&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;포인터 &lt;code&gt;int *p&lt;/code&gt;&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;정체&lt;/td&gt;
          &lt;td&gt;정수 4개를 담은 배열 객체&lt;/td&gt;
          &lt;td&gt;정수의 주소를 담는 변수&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;다른 주소 대입&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;a = other&lt;/code&gt; 불가&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;p = other&lt;/code&gt; 가능&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;sizeof&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;sizeof a&lt;/code&gt;는 배열 전체 크기&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;sizeof p&lt;/code&gt;는 포인터 자체 크기&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;div class=&quot;hb-correct&quot;&gt;
    &lt;strong&gt;부분 초기화는 나머지를 0으로 채운다&lt;/strong&gt;
    &lt;p&gt;&lt;code&gt;int a[4] = {5, 8};&lt;/code&gt;처럼 초기화 목록을 사용하면 나머지 &lt;code&gt;a[2]&lt;/code&gt;와 &lt;code&gt;a[3]&lt;/code&gt;은 0이 됩니다. 반대로 초기화하지 않은 지역 자동 배열의 값은 정해져 있지 않습니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2&gt;5. 2차원 배열 포인터는 행과 열을 나눠 읽는다&lt;/h2&gt;

  &lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;#include &amp;lt;stdio.h&amp;gt;

int main(void) {
    int grid[2][3] = {
        {7, 8, 9},
        {10, 11, 12}
    };
    int (*row)[3] = grid;

    int answer = *(row[0] + 1)
               + *(*(row + 1) + 2);

    printf(&quot;%d\n&quot;, answer);
    return 0;
}
// 출력: 20&lt;/code&gt;&lt;/pre&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;2차원 배열 grid의 행과 열&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;행&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;0열&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;1열&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;2열&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;grid[0]&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;7&lt;/td&gt;
          &lt;td&gt;8&lt;/td&gt;
          &lt;td&gt;9&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;grid[1]&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;10&lt;/td&gt;
          &lt;td&gt;11&lt;/td&gt;
          &lt;td&gt;12&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;div class=&quot;hb-formula&quot;&gt;&lt;code&gt;row[i][j]&lt;/code&gt; ⇔ &lt;code&gt;*(*(row + i) + j)&lt;/code&gt;&lt;/div&gt;

  &lt;div class=&quot;hb-number-list&quot;&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
      &lt;div class=&quot;hb-number-body&quot;&gt;
        &lt;strong class=&quot;hb-number-title&quot;&gt;&lt;code&gt;*(row[0] + 1)&lt;/code&gt;&lt;/strong&gt;
        &lt;p class=&quot;hb-number-desc&quot;&gt;0행의 시작에서 정수 한 칸 이동해 &lt;code&gt;grid[0][1]&lt;/code&gt;, 즉 8을 꺼냅니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
      &lt;div class=&quot;hb-number-body&quot;&gt;
        &lt;strong class=&quot;hb-number-title&quot;&gt;&lt;code&gt;*(*(row + 1) + 2)&lt;/code&gt;&lt;/strong&gt;
        &lt;p class=&quot;hb-number-desc&quot;&gt;1행으로 이동한 뒤 정수 두 칸 이동해 &lt;code&gt;grid[1][2]&lt;/code&gt;, 즉 12를 꺼냅니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;3&lt;/span&gt;
      &lt;div class=&quot;hb-number-body&quot;&gt;
        &lt;strong class=&quot;hb-number-title&quot;&gt;최종 계산&lt;/strong&gt;
        &lt;p class=&quot;hb-number-desc&quot;&gt;&lt;code&gt;8 + 12&lt;/code&gt;이므로 출력은 20입니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class=&quot;hb-callout&quot;&gt;
    &lt;strong&gt;이동 단위가 핵심&lt;/strong&gt;
    &lt;p&gt;&lt;code&gt;row + 1&lt;/code&gt;은 정수 한 칸이 아니라 &lt;strong&gt;한 행, 즉 정수 3개&lt;/strong&gt;만큼 이동합니다. 반면 &lt;code&gt;row[i] + 1&lt;/code&gt;은 선택한 행 안에서 정수 한 칸 이동합니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3&gt;괄호 하나로 완전히 달라지는 선언&lt;/h3&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;행 포인터와 포인터 배열 선언 비교&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;선언&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;읽는 방법&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;정체&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;int (*row)[3]&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;*row&lt;/code&gt;가 먼저 묶임&lt;/td&gt;
          &lt;td&gt;정수 3개짜리 배열을 가리키는 포인터&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;int *row[3]&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;row[3]&lt;/code&gt;이 먼저 묶임&lt;/td&gt;
          &lt;td&gt;정수 포인터 3개를 담는 배열&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;6. 출력 문제는 이 다섯 단계로 푼다&lt;/h2&gt;

  &lt;div class=&quot;hb-number-list&quot;&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
      &lt;div class=&quot;hb-number-body&quot;&gt;
        &lt;strong class=&quot;hb-number-title&quot;&gt;언어와 컴파일 가능 여부 표시&lt;/strong&gt;
        &lt;p class=&quot;hb-number-desc&quot;&gt;Java 조건식, C의 정의되지 않은 동작처럼 계산 전에 탈락할 코드를 먼저 찾습니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
      &lt;div class=&quot;hb-number-body&quot;&gt;
        &lt;strong class=&quot;hb-number-title&quot;&gt;자료형과 초기값 표 작성&lt;/strong&gt;
        &lt;p class=&quot;hb-number-desc&quot;&gt;배열의 빈 원소, 변수의 시작값, 포인터가 가리키는 대상을 적습니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;3&lt;/span&gt;
      &lt;div class=&quot;hb-number-body&quot;&gt;
        &lt;strong class=&quot;hb-number-title&quot;&gt;연산 우선순위와 증감 시점 확인&lt;/strong&gt;
        &lt;p class=&quot;hb-number-desc&quot;&gt;괄호 안쪽부터 풀고, 식에 사용된 값과 변수에 남은 값을 분리합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;4&lt;/span&gt;
      &lt;div class=&quot;hb-number-body&quot;&gt;
        &lt;strong class=&quot;hb-number-title&quot;&gt;포인터 한 칸의 크기 표시&lt;/strong&gt;
        &lt;p class=&quot;hb-number-desc&quot;&gt;&lt;code&gt;int *&lt;/code&gt;는 정수 한 칸, &lt;code&gt;int (*)[3]&lt;/code&gt;은 한 행씩 이동합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;5&lt;/span&gt;
      &lt;div class=&quot;hb-number-body&quot;&gt;
        &lt;strong class=&quot;hb-number-title&quot;&gt;출력 형식과 구분자 검산&lt;/strong&gt;
        &lt;p class=&quot;hb-number-desc&quot;&gt;값이 맞아도 공백, 쉼표, 줄바꿈이 다르면 최종 출력 문자열이 달라집니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;C printf에서 자주 사용하는 출력 형식&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;출력 대상&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;형식 지정자&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;예시&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;int&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;%d&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;printf(&quot;%d&quot;, value);&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;unsigned int&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;%u&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;printf(&quot;%u&quot;, value);&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;포인터&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;%p&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;printf(&quot;%p&quot;, (void *)ptr);&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;size_t&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;%zu&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;printf(&quot;%zu&quot;, sizeof value);&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;7. 시험 직전 암기 카드&lt;/h2&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;기본문법 활용 기출 핵심 암기표&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;주제&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;한 줄 암기&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Java 조건식&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;while&lt;/code&gt;에는 &lt;code&gt;boolean&lt;/code&gt; 식만 들어간다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;후위 증감&lt;/td&gt;
          &lt;td&gt;식에는 이전 값을 내놓고, 변수에는 바뀐 값이 남는다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;switch&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;일치 지점부터 &lt;code&gt;break&lt;/code&gt;까지 아래로 실행한다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;1차원 배열&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;a[i]&lt;/code&gt;는 &lt;code&gt;*(a + i)&lt;/code&gt;와 같다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;2차원 배열&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;p[i][j]&lt;/code&gt;는 &lt;code&gt;*(*(p + i) + j)&lt;/code&gt;와 같다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;행 포인터&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;p + 1&lt;/code&gt;은 한 행, &lt;code&gt;p[i] + 1&lt;/code&gt;은 행 안의 한 칸이다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;포인터 출력&lt;/td&gt;
          &lt;td&gt;실제 C 코드에서는 &lt;code&gt;%p&lt;/code&gt;와 &lt;code&gt;void *&lt;/code&gt;를 사용한다.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;8. 미니 퀴즈&lt;/h2&gt;

  &lt;div class=&quot;hb-quiz&quot;&gt;
    &lt;div class=&quot;hb-quiz-card&quot;&gt;
      &lt;span class=&quot;hb-quiz-num&quot;&gt;1&lt;/span&gt;
      &lt;p&gt;Java에서 정수형 변수 &lt;code&gt;n&lt;/code&gt;을 사용한 &lt;code&gt;while (n--)&lt;/code&gt;은 실행될까?&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-quiz-card&quot;&gt;
      &lt;span class=&quot;hb-quiz-num&quot;&gt;2&lt;/span&gt;
      &lt;p&gt;C에서 &lt;code&gt;x = 2&lt;/code&gt;, &lt;code&gt;y = 4&lt;/code&gt;일 때 &lt;code&gt;z = x++ + --y&lt;/code&gt; 이후 세 변수의 값은?&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-quiz-card&quot;&gt;
      &lt;span class=&quot;hb-quiz-num&quot;&gt;3&lt;/span&gt;
      &lt;p&gt;&lt;code&gt;switch&lt;/code&gt;에서 일치한 &lt;code&gt;case&lt;/code&gt; 뒤에 &lt;code&gt;break&lt;/code&gt;가 없으면 어떻게 될까?&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-quiz-card&quot;&gt;
      &lt;span class=&quot;hb-quiz-num&quot;&gt;4&lt;/span&gt;
      &lt;p&gt;&lt;code&gt;int a[5] = {7, 9};&lt;/code&gt;로 초기화했을 때 &lt;code&gt;a[4]&lt;/code&gt;의 값은?&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-quiz-card&quot;&gt;
      &lt;span class=&quot;hb-quiz-num&quot;&gt;5&lt;/span&gt;
      &lt;p&gt;&lt;code&gt;int m[2][2] = {{1, 4}, {7, 9}};&lt;/code&gt;, &lt;code&gt;int (*p)[2] = m;&lt;/code&gt;일 때 &lt;code&gt;*(*(p + 1) + 0)&lt;/code&gt;의 값은?&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;details&gt;
    &lt;summary&gt;정답과 해설 확인하기&lt;/summary&gt;
    &lt;div class=&quot;hb-answer-grid&quot;&gt;
      &lt;div class=&quot;hb-answer&quot;&gt;
        &lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; 실행되지 않습니다. &lt;code&gt;n--&lt;/code&gt;은 정수식이므로 Java의 &lt;code&gt;while&lt;/code&gt; 조건에 사용할 수 없어 컴파일 오류가 발생합니다.&lt;/p&gt;
      &lt;/div&gt;
      &lt;div class=&quot;hb-answer&quot;&gt;
        &lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; &lt;code&gt;x = 3&lt;/code&gt;, &lt;code&gt;y = 3&lt;/code&gt;, &lt;code&gt;z = 5&lt;/code&gt;입니다. 식에는 감소 전 &lt;code&gt;x&lt;/code&gt; 값 2와 감소 후 &lt;code&gt;y&lt;/code&gt; 값 3이 참여합니다.&lt;/p&gt;
      &lt;/div&gt;
      &lt;div class=&quot;hb-answer&quot;&gt;
        &lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; 다음 &lt;code&gt;case&lt;/code&gt;의 문장으로 이어서 실행합니다. 이를 폴스루라고 합니다.&lt;/p&gt;
      &lt;/div&gt;
      &lt;div class=&quot;hb-answer&quot;&gt;
        &lt;p&gt;&lt;strong&gt;4.&lt;/strong&gt; 0입니다. 초기화 목록에서 생략된 나머지 원소는 0으로 초기화됩니다.&lt;/p&gt;
      &lt;/div&gt;
      &lt;div class=&quot;hb-answer&quot;&gt;
        &lt;p&gt;&lt;strong&gt;5.&lt;/strong&gt; 7입니다. 식을 &lt;code&gt;p[1][0]&lt;/code&gt;으로 바꾸면 바로 확인할 수 있습니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/details&gt;

  &lt;h2&gt;9. 공식 문서 참고 자료&lt;/h2&gt;

  &lt;div class=&quot;hb-reference-list&quot;&gt;
    &lt;div class=&quot;hb-reference-item&quot;&gt;
      &lt;a href=&quot;https://docs.oracle.com/en/java/javase/26/docs/specs/jls/jls-14.html#jls-14.12&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Java Language Specification: while Statement&lt;/a&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-reference-item&quot;&gt;
      &lt;a href=&quot;https://docs.oracle.com/en/java/javase/26/docs/specs/jls/jls-15.html#jls-15.14.2&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Java Language Specification: Postfix Increment&lt;/a&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-reference-item&quot;&gt;
      &lt;a href=&quot;https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Increment_002fDecrement.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GNU C Language Manual: Increment/Decrement&lt;/a&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-reference-item&quot;&gt;
      &lt;a href=&quot;https://www.gnu.org/software/c-intro-and-ref/manual/html_node/switch-Statement.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GNU C Language Manual: switch Statement&lt;/a&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-reference-item&quot;&gt;
      &lt;a href=&quot;https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Pointers-and-Arrays.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GNU C Language Manual: Pointers and Arrays&lt;/a&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-reference-item&quot;&gt;
      &lt;a href=&quot;https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Multidimensional-Arrays.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GNU C Language Manual: Multidimensional Arrays&lt;/a&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-reference-item&quot;&gt;
      &lt;a href=&quot;https://www.gnu.org/software/libc/manual/html_node/Other-Output-Conversions.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GNU C Library: Pointer Output Conversion&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;h2&gt;마무리&lt;/h2&gt;

  &lt;p&gt;이 범위의 출력 문제는 기호가 많아 보여도 풀이 순서는 일정합니다. 언어를 확인하고, 초깃값을 표로 적고, 증감 시점과 포인터 이동 단위를 표시한 뒤, 마지막에 출력 형식을 확인하면 됩니다.&lt;/p&gt;

  &lt;p&gt;특히 &lt;strong&gt;Java 정수 조건식은 컴파일 오류&lt;/strong&gt;, &lt;strong&gt;후위 연산은 이전 값을 식에 제공&lt;/strong&gt;, &lt;strong&gt;행 포인터의 한 칸은 한 행&lt;/strong&gt;이라는 세 문장을 확실히 기억해 두세요. 배열 포인터 식은 괄호 안쪽부터 첨자식으로 바꾸면 훨씬 단순해집니다.&lt;/p&gt;

  &lt;p class=&quot;hb-footer-note&quot;&gt;이 글은 정보처리기사 학습 범위를 바탕으로 문제 원문을 전재하지 않고 개념과 예제를 새로 구성한 개인 공부 기록입니다. 세부 출제 표현과 정답은 최신 교재와 공식 출제 자료를 함께 확인해 주세요.&lt;/p&gt;
&lt;/article&gt;</description>
      <category>AI/정보처리기사_스터디</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/116</guid>
      <comments>https://onethingflow.tistory.com/entry/%EC%A0%95%EC%B2%98%EA%B8%B0-4%EC%9D%BC%EC%B0%A8-%EC%88%98%EC%A0%9C%EB%B9%84-%EA%B8%B0%EB%B3%B8%EB%AC%B8%EB%B2%95-%ED%99%9C%EC%9A%A9-%EA%B8%B0%EC%B6%9C-4%EC%9C%A0%ED%98%95-%ED%92%80%EC%9D%B4%EB%B2%95#entry116comment</comments>
      <pubDate>Thu, 16 Jul 2026 09:15:41 +0900</pubDate>
    </item>
    <item>
      <title>Day 10)프로그래머스 파이썬 풀이: 과일 장수, 소수 만들기, 오픈채팅방, 개미 군단, 컨트롤 제트</title>
      <link>https://onethingflow.tistory.com/entry/Day-10%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%ED%92%80%EC%9D%B4-%EA%B3%BC%EC%9D%BC-%EC%9E%A5%EC%88%98-%EC%86%8C%EC%88%98-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EC%98%A4%ED%94%88%EC%B1%84%ED%8C%85%EB%B0%A9-%EA%B0%9C%EB%AF%B8-%EA%B5%B0%EB%8B%A8-%EC%BB%A8%ED%8A%B8%EB%A1%A4-%EC%A0%9C%ED%8A%B8</link>
      <description>&lt;!--
티스토리 제목 추천:
프로그래머스 파이썬 풀이: 과일 장수, 소수 만들기, 오픈채팅방, 개미 군단, 컨트롤 제트

메타 설명 추천:
Google 문서에 정리한 프로그래머스 과일 장수, 소수 만들기, 오픈채팅방, 개미 군단, 컨트롤 제트 풀이를 파이썬 기준으로 정리했습니다. 그리디, 조합, 소수 판별, 딕셔너리, 스택, split, map의 한계까지 초보자 눈높이로 설명합니다.

태그 추천:
프로그래머스, 코딩테스트, 파이썬, 과일장수, 소수만들기, 오픈채팅방, 개미군단, 컨트롤제트, 그리디, 조합, 딕셔너리, 스택
--&gt;

&lt;article class=&quot;hb-post hb-coding-note&quot;&gt;
  &lt;style&gt;
    .hb-post {
      --hb-ink: #1f2933;
      --hb-muted: #64748b;
      --hb-line: #dbe5f1;
      --hb-soft: #f8fbff;
      --hb-warm: #fff8e8;
      --hb-accent: #2459d6;
      max-width: 780px;
      margin: 0 auto;
      color: var(--hb-ink);
      font-size: 17px;
      line-height: 1.86;
      word-break: keep-all;
    }
    .hb-post * {
      box-sizing: border-box;
    }
    .hb-post h1,
    .hb-post h2,
    .hb-post h3,
    .hb-post p {
      margin-top: 0;
    }
    .hb-post h1 {
      margin-bottom: .72em;
      font-size: 2em;
      line-height: 1.28;
      font-weight: 800;
      color: #111827;
      letter-spacing: 0;
    }
    .hb-post h2 {
      margin: 2.45em 0 .78em;
      padding-bottom: .38em;
      border-bottom: 2px solid #edf0f4;
      font-size: 1.34em;
      line-height: 1.42;
      font-weight: 800;
      color: #111827;
      letter-spacing: 0;
    }
    .hb-post h3 {
      margin: 1.35em 0 .52em;
      font-size: 1.08em;
      line-height: 1.45;
      font-weight: 800;
      color: #172033;
    }
    .hb-post p {
      margin-bottom: 1.12em;
    }
    .hb-post a {
      color: var(--hb-accent);
      text-decoration: none;
      border-bottom: 1px solid rgba(36, 89, 214, .25);
    }
    .hb-post code {
      overflow-wrap: anywhere;
      padding: .05em .22em;
      border-radius: 4px;
      background: #eef4ff;
      color: #17315f;
      font-size: .92em;
    }
    .hb-post pre {
      margin: 1em 0 1.2em;
      padding: 1.05em 1.1em;
      overflow-x: auto;
      border-radius: 8px;
      background: #101418;
      color: #f6f8fb;
      font-size: .92em;
      line-height: 1.68;
    }
    .hb-post pre code {
      display: block;
      padding: 0;
      background: transparent;
      color: inherit;
      font-size: inherit;
      white-space: pre;
      overflow-wrap: normal;
    }
    .hb-post .hb-hero {
      margin: 0 0 1.5em;
      padding: 1.35em 1.4em;
      border: 1px solid #dde6f2;
      border-radius: 8px;
      background: linear-gradient(135deg, #f7fbff 0%, #fff 62%, #fff7ed 100%);
    }
    .hb-post .hb-label {
      display: inline-block;
      margin: 0 0 .8em;
      padding: .25em .7em;
      border: 1px solid #d9e4f2;
      border-radius: 999px;
      background: #fff;
      color: #385174;
      font-size: .84em;
      font-weight: 700;
    }
    .hb-post .hb-card-grid {
      display: grid;
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: .85em;
      margin: 1.35em 0;
    }
    .hb-post .hb-card {
      padding: 1em;
      border: 1px solid #e3e8ef;
      border-radius: 8px;
      background: #fff;
    }
    .hb-post .hb-card span {
      display: block;
      margin-bottom: .25em;
      color: var(--hb-muted);
      font-size: .82em;
    }
    .hb-post .hb-card strong {
      display: block;
      color: #101418;
      font-size: 1.04em;
      line-height: 1.36;
    }
    .hb-post .hb-quote {
      margin: 1.55em 0;
      padding: .95em 1.15em;
      border-left: 4px solid #f2b705;
      border-radius: 8px;
      background: var(--hb-warm);
      color: #584500;
      font-size: 1.06em;
      font-weight: 800;
    }
    .hb-post .hb-note {
      margin: 1.35em 0;
      padding: 1em 1.1em;
      border: 1px solid #dbe5f5;
      border-radius: 8px;
      background: var(--hb-soft);
    }
    .hb-post .hb-warning {
      border-color: #f1d7d7;
      background: #fffafa;
    }
    .hb-post .hb-note strong {
      display: block;
      margin-bottom: .45em;
      color: #172033;
    }
    .hb-post .hb-number-list {
      display: grid;
      gap: .72em;
      margin: 1em 0 1.3em;
    }
    .hb-post .hb-number-item {
      display: grid;
      grid-template-columns: 2.1em minmax(0, 1fr);
      gap: .75em;
      align-items: start;
    }
    .hb-post .hb-number-badge {
      display: inline-flex;
      width: 2.1em;
      height: 2.1em;
      align-items: center;
      justify-content: center;
      border-radius: 999px;
      background: #e8f0ff;
      color: #244fba;
      font-weight: 800;
      line-height: 1;
    }
    .hb-post .hb-number-content strong {
      display: block;
      margin-bottom: .15em;
      color: #172033;
    }
    .hb-post .hb-number-content p {
      margin-bottom: 0;
      color: #344054;
    }
    .hb-post .hb-table-wrap {
      overflow-x: auto;
      margin: 1.25em 0 1.55em;
    }
    .hb-post table {
      width: 100%;
      min-width: 640px;
      border-collapse: collapse;
      border: 1px solid #e2e8f0;
      background: #fff;
      font-size: .96em;
    }
    .hb-post caption {
      position: absolute;
      width: 1px;
      height: 1px;
      overflow: hidden;
      clip: rect(0, 0, 0, 0);
    }
    .hb-post th,
    .hb-post td {
      padding: .75em;
      border: 1px solid #e2e8f0;
      text-align: left;
      vertical-align: top;
    }
    .hb-post th {
      background: #f6f8fb;
      color: #283244;
      font-weight: 800;
    }
    .hb-post .hb-pill-row {
      display: flex;
      flex-wrap: wrap;
      gap: .45em;
      margin: .7em 0 1.2em;
    }
    .hb-post .hb-pill {
      display: inline-flex;
      align-items: center;
      padding: .22em .62em;
      border: 1px solid #dbe5f1;
      border-radius: 999px;
      background: #fff;
      color: #475569;
      font-size: .9em;
    }
    @media (max-width: 640px) {
      .hb-post {
        font-size: 16px;
      }
      .hb-post h1 {
        font-size: 1.55em;
      }
      .hb-post .hb-card-grid {
        grid-template-columns: 1fr;
      }
      .hb-post .hb-number-item {
        grid-template-columns: 1.85em minmax(0, 1fr);
        gap: .6em;
      }
      .hb-post .hb-number-badge {
        width: 1.85em;
        height: 1.85em;
      }
    }
  &lt;/style&gt;

  &lt;section class=&quot;hb-hero&quot;&gt;
    &lt;p class=&quot;hb-label&quot;&gt;프로그래머스 파이썬 풀이 노트&lt;/p&gt;
    &lt;h1&gt;과일 장수, 소수 만들기, 오픈채팅방, 개미 군단, 컨트롤 제트 풀이 정리&lt;/h1&gt;
    &lt;p&gt;이번 글은 Google 문서에 정리해 둔 문제 풀이 기록을 블로그용으로 다시 다듬은 글입니다. 한 가지 주제만 다루는 Day 글은 아니고, 그리디, 조합, 해시, 스택을 한 번에 복습하는 문제 묶음입니다.&lt;/p&gt;
    &lt;p&gt;원문 흐름을 빠뜨리지 않기 위해 처음 떠올린 생각, 실수한 코드, 왜 틀렸는지, 수정 풀이, 더 짧은 풀이, 초보자용 설명까지 함께 정리했습니다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;div class=&quot;hb-card-grid&quot;&gt;
    &lt;div class=&quot;hb-card&quot;&gt;
      &lt;span&gt;핵심 1&lt;/span&gt;
      &lt;strong&gt;그리디와 정렬&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-card&quot;&gt;
      &lt;span&gt;핵심 2&lt;/span&gt;
      &lt;strong&gt;조합과 소수 판별&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-card&quot;&gt;
      &lt;span&gt;핵심 3&lt;/span&gt;
      &lt;strong&gt;딕셔너리와 스택&lt;/strong&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class=&quot;hb-quote&quot;&gt;이번 문서의 공통 주제는 “문제 조건을 파이썬 자료구조로 정확히 옮기는 연습”이었습니다.&lt;/div&gt;

  &lt;section class=&quot;hb-note&quot;&gt;
    &lt;strong&gt;글의 정리 순서&lt;/strong&gt;
    &lt;div class=&quot;hb-number-list&quot;&gt;
      &lt;div class=&quot;hb-number-item&quot;&gt;
        &lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
        &lt;div class=&quot;hb-number-content&quot;&gt;
          &lt;strong&gt;문제 및 공식 링크&lt;/strong&gt;
          &lt;p&gt;문서에서 다룬 프로그래머스 문제를 먼저 표로 정리합니다.&lt;/p&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class=&quot;hb-number-item&quot;&gt;
        &lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
        &lt;div class=&quot;hb-number-content&quot;&gt;
          &lt;strong&gt;처음 코드와 실수&lt;/strong&gt;
          &lt;p&gt;사용자가 작성한 코드의 의도와 틀린 지점을 함께 봅니다.&lt;/p&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class=&quot;hb-number-item&quot;&gt;
        &lt;span class=&quot;hb-number-badge&quot;&gt;3&lt;/span&gt;
        &lt;div class=&quot;hb-number-content&quot;&gt;
          &lt;strong&gt;수정 풀이와 빠른 풀이&lt;/strong&gt;
          &lt;p&gt;기본 풀이를 먼저 이해한 뒤, 실전에서 쓸 수 있는 짧은 풀이까지 정리합니다.&lt;/p&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class=&quot;hb-number-item&quot;&gt;
        &lt;span class=&quot;hb-number-badge&quot;&gt;4&lt;/span&gt;
        &lt;div class=&quot;hb-number-content&quot;&gt;
          &lt;strong&gt;검산과 체크리스트&lt;/strong&gt;
          &lt;p&gt;예제 결과와 실수 방지 포인트를 마지막에 모아 봅니다.&lt;/p&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;h2&gt;1. 문제 및 프로그래머스 공식 링크&lt;/h2&gt;
  &lt;p&gt;문서에서 다룬 문제는 총 5개입니다. 난이도와 주제는 섞여 있지만, 각각 코딩테스트에서 자주 만나는 핵심 도구를 하나씩 연습하게 해 줍니다.&lt;/p&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;문서에서 다룬 프로그래머스 문제와 핵심 개념&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;문제&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;공식 링크&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;핵심 개념&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;과일 장수&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/135808&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;그리디, 정렬, 슬라이싱, 나머지&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;소수 만들기&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/12977&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;조합, 소수 판별&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;오픈채팅방&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42888&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;해시, 딕셔너리, 투 패스&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;개미 군단&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/120837&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;그리디, 몫과 나머지, divmod&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;컨트롤 제트&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/120853&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;split, 스택, append, pop&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;2. 과일 장수: 비싼 사과부터 묶고 최저 점수만 계산하기&lt;/h2&gt;

  &lt;h3&gt;문제 요약&lt;/h3&gt;
  &lt;p&gt;사과 점수 배열 &lt;code&gt;score&lt;/code&gt;가 주어지고, 한 상자에 &lt;code&gt;m&lt;/code&gt;개씩 담아 팔아야 합니다. 한 상자의 가격은 그 상자 안에서 가장 낮은 점수 &lt;code&gt;p&lt;/code&gt;에 &lt;code&gt;m&lt;/code&gt;을 곱한 값입니다. 남는 사과는 팔 수 없고 버립니다.&lt;/p&gt;

  &lt;h3&gt;처음 떠올린 힌트&lt;/h3&gt;
  &lt;div class=&quot;hb-number-list&quot;&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;비싼 사과부터 포장한다&lt;/strong&gt;
        &lt;p&gt;최대 이익을 내려면 점수가 높은 사과끼리 먼저 묶는 것이 유리합니다. 그래서 &lt;code&gt;sorted(score, reverse=True)&lt;/code&gt;로 내림차순 정렬합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;각 상자의 마지막 사과가 최저 점수다&lt;/strong&gt;
        &lt;p&gt;내림차순으로 정렬한 뒤 &lt;code&gt;m&lt;/code&gt;개씩 묶으면, 각 묶음의 마지막 위치가 그 상자의 가격을 결정하는 최저 점수입니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;h3&gt;처음 작성한 코드&lt;/h3&gt;
  &lt;pre&gt;&lt;code&gt;def solution(k, m, score):
    answer = 0
    new_score = sorted(score, reverse=True)

    for i in range(0, len(score) + 1, m):
        answer += i * m

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3&gt;잘못된 점&lt;/h3&gt;
  &lt;div class=&quot;hb-number-list&quot;&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;&lt;code&gt;i&lt;/code&gt;는 사과 점수가 아니라 인덱스다&lt;/strong&gt;
        &lt;p&gt;&lt;code&gt;range(0, len(score) + 1, m)&lt;/code&gt;에서 &lt;code&gt;i&lt;/code&gt;는 0, &lt;code&gt;m&lt;/code&gt;, &lt;code&gt;2m&lt;/code&gt;처럼 위치 번호입니다. 실제 사과 점수를 꺼내려면 &lt;code&gt;new_score[i]&lt;/code&gt;처럼 배열에 접근해야 합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;상자의 최저 점수는 &lt;code&gt;new_score[i + m - 1]&lt;/code&gt;이다&lt;/strong&gt;
        &lt;p&gt;&lt;code&gt;i&lt;/code&gt;는 상자의 시작 위치입니다. 가격을 결정하는 사과는 상자의 마지막 사과이므로 &lt;code&gt;i + m - 1&lt;/code&gt; 위치를 봐야 합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;3&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;남는 사과는 버린다&lt;/strong&gt;
        &lt;p&gt;&lt;code&gt;len(score) + 1&lt;/code&gt;까지 반복하면 상자를 채우지 못하는 사과까지 보려고 하다가 인덱스 에러가 날 수 있습니다. 온전한 상자만 만들려면 &lt;code&gt;range(0, len(score) - m + 1, m)&lt;/code&gt;이 안전합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;h3&gt;기본 수정 풀이&lt;/h3&gt;
  &lt;pre&gt;&lt;code&gt;def solution(k, m, score):
    answer = 0
    new_score = sorted(score, reverse=True)

    for i in range(0, len(score) - m + 1, m):
        lowest_apple = new_score[i + m - 1]
        answer += lowest_apple * m

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3&gt;내림차순 슬라이싱 풀이&lt;/h3&gt;
  &lt;pre&gt;&lt;code&gt;def solution(k, m, score):
    return sum(sorted(score, reverse=True)[m-1::m]) * m&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;sorted(score, reverse=True)&lt;/code&gt;로 비싼 사과부터 줄 세운 뒤, &lt;code&gt;[m-1::m]&lt;/code&gt;으로 첫 번째 상자의 마지막 사과, 두 번째 상자의 마지막 사과를 차례로 뽑습니다. 이 값들이 각 상자의 최저 점수입니다.&lt;/p&gt;

  &lt;h3&gt;문서에 나온 빠른 풀이: 오름차순과 나머지 활용&lt;/h3&gt;
  &lt;pre&gt;&lt;code&gt;def solution(k, m, score):
    return sum(sorted(score)[len(score) % m::m]) * m&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;이 풀이는 오름차순으로 정렬합니다. 가장 싼 사과가 앞에 오기 때문에 &lt;code&gt;len(score) % m&lt;/code&gt;개만큼 앞에서 건너뛰면, 상자를 채우지 못하고 버려야 할 가장 싼 사과들을 먼저 제외할 수 있습니다. 그다음 &lt;code&gt;::m&lt;/code&gt;으로 각 상자의 첫 번째 사과만 뽑는데, 오름차순 묶음에서는 이 첫 번째 사과가 그 상자의 최저 점수입니다.&lt;/p&gt;

  &lt;div class=&quot;hb-note&quot;&gt;
    &lt;strong&gt;초보자용으로 다시 풀어보면&lt;/strong&gt;
    &lt;p&gt;&lt;code&gt;sorted(score)&lt;/code&gt;는 싼 사과부터 줄 세우기, &lt;code&gt;len(score) % m&lt;/code&gt;은 버릴 사과 개수 찾기, &lt;code&gt;[시작점::m]&lt;/code&gt;은 각 상자의 최저 점수만 건너뛰며 뽑기, &lt;code&gt;sum(...) * m&lt;/code&gt;은 총 이익 계산입니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2&gt;3. 소수 만들기: 3개씩 고르고 합이 소수인지 확인하기&lt;/h2&gt;

  &lt;h3&gt;문제 요약&lt;/h3&gt;
  &lt;p&gt;&lt;code&gt;nums&lt;/code&gt;에서 서로 다른 숫자 3개를 고른 뒤, 그 합이 소수인 경우의 개수를 구합니다. 문서에서 짚은 것처럼 핵심은 “3개씩 묶기”와 “소수 정의로 판별하기”입니다.&lt;/p&gt;

  &lt;h3&gt;풀이 방향&lt;/h3&gt;
  &lt;div class=&quot;hb-number-list&quot;&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;서로 다른 3개를 고른다&lt;/strong&gt;
        &lt;p&gt;직접 3중 반복문을 써도 되지만, 파이썬에서는 &lt;code&gt;itertools.combinations(nums, 3)&lt;/code&gt;가 더 명확합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;합이 소수인지 확인한다&lt;/strong&gt;
        &lt;p&gt;소수는 1과 자기 자신만으로 나누어떨어지는 수입니다. 2부터 제곱근까지 나누어 보며 확인하면 충분합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;h3&gt;기본 풀이&lt;/h3&gt;
  &lt;pre&gt;&lt;code&gt;from itertools import combinations

def is_prime(n):
    if n &amp;lt; 2:
        return False

    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False

    return True

def solution(nums):
    answer = 0

    for selected in combinations(nums, 3):
        if is_prime(sum(selected)):
            answer += 1

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3&gt;더 짧게 쓰기&lt;/h3&gt;
  &lt;pre&gt;&lt;code&gt;from itertools import combinations

def is_prime(n):
    return n &amp;gt; 1 and all(n % i != 0 for i in range(2, int(n ** 0.5) + 1))

def solution(nums):
    return sum(1 for selected in combinations(nums, 3) if is_prime(sum(selected)))&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;문서의 질문처럼 이 문제는 “3개씩 묶고, 소수 정의로 확인하면 되는 문제”가 맞습니다. 다만 모든 3개 조합을 빠짐없이 만들어야 하므로 조합 도구를 쓰는 것이 실수를 줄여 줍니다.&lt;/p&gt;

  &lt;h2&gt;4. 오픈채팅방: 최종 닉네임 장부를 먼저 만든다&lt;/h2&gt;

  &lt;h3&gt;문제 요약&lt;/h3&gt;
  &lt;p&gt;&lt;code&gt;record&lt;/code&gt;에는 입장, 퇴장, 닉네임 변경 기록이 들어 있습니다. 최종 출력 메시지에는 과거 메시지에도 최신 닉네임이 반영되어야 합니다. 그래서 한 번에 메시지를 만들지 말고, 먼저 아이디별 최종 닉네임 장부를 만든 뒤 메시지를 찍어내야 합니다.&lt;/p&gt;

  &lt;h3&gt;핵심 아이디어: 투 패스&lt;/h3&gt;
  &lt;div class=&quot;hb-number-list&quot;&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;첫 번째 순회&lt;/strong&gt;
        &lt;p&gt;&lt;code&gt;Enter&lt;/code&gt;와 &lt;code&gt;Change&lt;/code&gt; 기록을 보며 &lt;code&gt;uid → 최신 닉네임&lt;/code&gt; 딕셔너리를 완성합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;두 번째 순회&lt;/strong&gt;
        &lt;p&gt;&lt;code&gt;Enter&lt;/code&gt;와 &lt;code&gt;Leave&lt;/code&gt; 기록만 메시지로 바꾸고, 닉네임은 첫 번째 순회에서 만든 장부에서 꺼냅니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;h3&gt;실수한 코드&lt;/h3&gt;
  &lt;pre&gt;&lt;code&gt;def solution(record):
    answer = []
    namespace = {}
    printer = {'Enter': '님이 들어왔습니다.', 'Leave': '님이 나갔습니다.'}

    for r in record:
        rr = r.split(' ')
        if rr[0] in ['Enter', 'Change']:
            namespace[rr[1]] == rr[2]

    for r in record:
        rr = r.split(' ')
        action = rr[0]
        uid = rr[1]

        if action != &quot;Change&quot;:
            answer.append(namespace[uid] + printer[action])

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3&gt;잘못된 점: &lt;code&gt;==&lt;/code&gt;와 &lt;code&gt;=&lt;/code&gt;&lt;/h3&gt;
  &lt;p&gt;&lt;code&gt;namespace[rr[1]] == rr[2]&lt;/code&gt;는 “둘이 같니?”라고 비교만 하는 코드입니다. 딕셔너리에 값을 저장하려면 &lt;code&gt;namespace[rr[1]] = rr[2]&lt;/code&gt;처럼 대입 연산자 &lt;code&gt;=&lt;/code&gt;를 써야 합니다. 이 한 글자 때문에 장부가 비어 있고, 두 번째 반복문에서 &lt;code&gt;KeyError&lt;/code&gt;가 날 수 있습니다.&lt;/p&gt;

  &lt;h3&gt;수정한 최종 코드&lt;/h3&gt;
  &lt;pre&gt;&lt;code&gt;def solution(record):
    answer = []
    namespace = {}
    printer = {'Enter': '님이 들어왔습니다.', 'Leave': '님이 나갔습니다.'}

    for r in record:
        rr = r.split(' ')
        if rr[0] in ['Enter', 'Change']:
            namespace[rr[1]] = rr[2]

    for r in record:
        rr = r.split(' ')
        action = rr[0]
        uid = rr[1]

        if action != 'Change':
            answer.append(namespace[uid] + printer[action])

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;div class=&quot;hb-note&quot;&gt;
    &lt;strong&gt;파이썬에서 중괄호 &lt;code&gt;{}&lt;/code&gt;는 가능할까?&lt;/strong&gt;
    &lt;p&gt;가능합니다. &lt;code&gt;{}&lt;/code&gt;는 빈 딕셔너리를 만들 때 쓰고, &lt;code&gt;{1, 2, 3}&lt;/code&gt;처럼 값을 넣으면 집합이 됩니다. 문자열 앞에 &lt;code&gt;f&lt;/code&gt;를 붙인 f-string에서는 &lt;code&gt;f&quot;{name}&quot;&lt;/code&gt;처럼 변수 값을 문자열 안에 넣을 때도 중괄호를 씁니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3&gt;문서에 나온 최적화 포인트&lt;/h3&gt;
  &lt;p&gt;두 번째 반복문에서 &lt;code&gt;r.split(' ')&lt;/code&gt;을 여러 번 반복해서 쓰면 매번 문자열을 새로 쪼개야 합니다. 그래서 문서에서처럼 &lt;code&gt;rr = r.split(' ')&lt;/code&gt;로 한 번만 쪼개고 &lt;code&gt;action&lt;/code&gt;, &lt;code&gt;uid&lt;/code&gt; 변수에 담아 재사용하는 편이 좋습니다.&lt;/p&gt;

  &lt;h2&gt;5. 개미 군단: 가장 강한 개미부터 최대한 쓰기&lt;/h2&gt;

  &lt;h3&gt;문제 요약&lt;/h3&gt;
  &lt;p&gt;장군개미는 공격력 5, 병정개미는 공격력 3, 일개미는 공격력 1입니다. 사냥감의 체력 &lt;code&gt;hp&lt;/code&gt;를 맞추기 위해 필요한 최소 개미 수를 구합니다.&lt;/p&gt;

  &lt;h3&gt;내 풀이&lt;/h3&gt;
  &lt;pre&gt;&lt;code&gt;def solution(hp):
    return hp // 5 + (hp % 5 // 3) + ((hp % 5) % 3)&lt;/code&gt;&lt;/pre&gt;

  &lt;h3&gt;초보자용 3단계 설명&lt;/h3&gt;
  &lt;div class=&quot;hb-number-list&quot;&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;&lt;code&gt;hp // 5&lt;/code&gt;&lt;/strong&gt;
        &lt;p&gt;가장 강한 장군개미를 몇 마리 쓸 수 있는지 먼저 구합니다. &lt;code&gt;//&lt;/code&gt;는 몫입니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;&lt;code&gt;(hp % 5) // 3&lt;/code&gt;&lt;/strong&gt;
        &lt;p&gt;장군개미가 처리하고 남은 체력을 병정개미로 얼마나 처리할 수 있는지 구합니다. &lt;code&gt;%&lt;/code&gt;는 나머지입니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;3&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;&lt;code&gt;(hp % 5) % 3&lt;/code&gt;&lt;/strong&gt;
        &lt;p&gt;장군개미와 병정개미를 쓰고도 남은 체력은 일개미가 처리합니다. 일개미 공격력은 1이므로 남은 체력 자체가 필요한 일개미 수입니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;h3&gt;&lt;code&gt;divmod()&lt;/code&gt;를 활용한 풀이&lt;/h3&gt;
  &lt;pre&gt;&lt;code&gt;def solution(hp):
    general, hp = divmod(hp, 5)
    soldier, hp = divmod(hp, 3)
    return general + soldier + hp&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;code&gt;divmod(a, b)&lt;/code&gt;는 &lt;code&gt;a&lt;/code&gt;를 &lt;code&gt;b&lt;/code&gt;로 나눈 몫과 나머지를 한 번에 반환합니다. 그래서 몫은 개미 수로, 나머지는 다음 단계의 남은 체력으로 이어서 사용할 수 있습니다.&lt;/p&gt;

  &lt;h2&gt;6. 컨트롤 제트: 방금 더한 값을 취소하려면 스택&lt;/h2&gt;

  &lt;h3&gt;문제 요약&lt;/h3&gt;
  &lt;p&gt;문자열 &lt;code&gt;s&lt;/code&gt;에는 숫자와 &lt;code&gt;&quot;Z&quot;&lt;/code&gt;가 공백으로 구분되어 있습니다. 숫자는 더하고, &lt;code&gt;&quot;Z&quot;&lt;/code&gt;가 나오면 바로 전에 더했던 숫자를 취소합니다.&lt;/p&gt;

  &lt;h3&gt;처음 작성한 코드&lt;/h3&gt;
  &lt;pre&gt;&lt;code&gt;def solution(s):
    answer = 0

    for i in s:
        if i == is_int:
            answer += i
        else:
            answer -= s[i-1]

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3&gt;힌트와 문제점&lt;/h3&gt;
  &lt;div class=&quot;hb-number-list&quot;&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;&lt;code&gt;s.split()&lt;/code&gt;이 먼저다&lt;/strong&gt;
        &lt;p&gt;&lt;code&gt;for i in s&lt;/code&gt;를 쓰면 공백까지 포함해서 한 글자씩 순회합니다. &lt;code&gt;&quot;10 20 Z&quot;&lt;/code&gt;를 제대로 다루려면 &lt;code&gt;s.split()&lt;/code&gt;으로 &lt;code&gt;[&quot;10&quot;, &quot;20&quot;, &quot;Z&quot;]&lt;/code&gt;처럼 나눠야 합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;&lt;code&gt;is_int&lt;/code&gt;라는 내장 명령어는 없다&lt;/strong&gt;
        &lt;p&gt;이 문제는 숫자인지 판별하기보다 &lt;code&gt;i == &quot;Z&quot;&lt;/code&gt;인지 먼저 확인하는 쪽이 더 쉽습니다. 숫자를 더할 때는 &lt;code&gt;int(i)&lt;/code&gt;로 바꿔야 합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;3&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;&lt;code&gt;s[i-1]&lt;/code&gt;로는 취소를 안정적으로 처리하기 어렵다&lt;/strong&gt;
        &lt;p&gt;&lt;code&gt;i&lt;/code&gt;가 인덱스가 아니라 값이면 &lt;code&gt;s[i-1]&lt;/code&gt; 자체가 불가능하고, 설령 인덱스로 바꿔도 이전 값이 &lt;code&gt;&quot;Z&quot;&lt;/code&gt;일 수 있습니다. 이런 “방금 한 일을 취소”하는 문제는 스택이 맞습니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;h3&gt;인덱스로 다시 시도한 코드&lt;/h3&gt;
  &lt;pre&gt;&lt;code&gt;def solution(s):
    answer = 0

    for i in range(len(s)):
        if s[i] != &quot;Z&quot;:
            answer += s[i]
        else:
            answer -= s[i-1]

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;이 코드도 그대로는 틀립니다. &lt;code&gt;s&lt;/code&gt;를 글자 단위로 돌기 때문에 &lt;code&gt;&quot;10&quot;&lt;/code&gt;이 &lt;code&gt;&quot;1&quot;&lt;/code&gt;과 &lt;code&gt;&quot;0&quot;&lt;/code&gt;으로 쪼개지고, &lt;code&gt;answer&lt;/code&gt;는 숫자인데 &lt;code&gt;s[i]&lt;/code&gt;는 문자열이라 더할 수 없습니다. 또한 &lt;code&gt;&quot;Z&quot;&lt;/code&gt;가 나오면 직전에 실제로 더한 숫자를 취소해야 하므로 스택이 더 안정적입니다.&lt;/p&gt;

  &lt;h3&gt;정석 풀이: 스택&lt;/h3&gt;
  &lt;pre&gt;&lt;code&gt;def solution(s):
    stack = []

    for i in s.split():
        if i != 'Z':
            stack.append(int(i))
        else:
            stack.pop()

    return sum(stack)&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;숫자면 &lt;code&gt;append()&lt;/code&gt;로 넣고, &lt;code&gt;&quot;Z&quot;&lt;/code&gt;면 &lt;code&gt;pop()&lt;/code&gt;으로 가장 최근에 넣은 숫자를 꺼내 버립니다. 이 흐름이 바로 스택입니다.&lt;/p&gt;

  &lt;h3&gt;&lt;code&gt;map&lt;/code&gt;은 왜 안 될까?&lt;/h3&gt;
  &lt;p&gt;&lt;code&gt;sum(map(int, s.split()))&lt;/code&gt;처럼 쓰고 싶을 수 있지만, 이 문제에서는 적합하지 않습니다. 첫째, &lt;code&gt;&quot;Z&quot;&lt;/code&gt;는 &lt;code&gt;int(&quot;Z&quot;)&lt;/code&gt;로 바꿀 수 없어 에러가 납니다. 둘째, &lt;code&gt;map&lt;/code&gt;은 각 값을 독립적으로 변환할 뿐, 직전에 넣은 값을 기억했다가 취소하는 기능이 없습니다. 이 문제처럼 과거 기록을 지워야 할 때는 스택을 써야 합니다.&lt;/p&gt;

  &lt;h2&gt;7. 입출력 예로 빠르게 검산하기&lt;/h2&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;문서 기반 문제별 빠른 검산 예시&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;문제&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;예시 입력&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;기대 결과&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;과일 장수&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;k=3, m=4, score=[1,2,3,1,2,3,1]&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;8&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;소수 만들기&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;nums=[1,2,7,6,4]&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;4&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;오픈채팅방&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;[&quot;Enter uid1234 Muzi&quot;, &quot;Enter uid4567 Prodo&quot;, ...]&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;[&quot;Prodo님이 들어왔습니다.&quot;, &quot;Ryan님이 들어왔습니다.&quot;, ...]&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;개미 군단&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;hp=23&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;5&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;컨트롤 제트&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;&quot;1 2 Z 3&quot;&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;4&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;8. 실수 방지 체크리스트&lt;/h2&gt;

  &lt;div class=&quot;hb-number-list&quot;&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;1&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;인덱스와 실제 값을 구분한다&lt;/strong&gt;
        &lt;p&gt;&lt;code&gt;i&lt;/code&gt;는 위치 번호입니다. 배열 안의 값을 쓰려면 &lt;code&gt;arr[i]&lt;/code&gt;처럼 접근해야 합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;2&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;남는 데이터는 문제 조건대로 처리한다&lt;/strong&gt;
        &lt;p&gt;과일 장수에서는 상자를 채우지 못한 사과를 버립니다. 반복 범위를 넉넉하게 잡으면 오답이나 에러가 날 수 있습니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;3&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;&lt;code&gt;=&lt;/code&gt;와 &lt;code&gt;==&lt;/code&gt;를 구분한다&lt;/strong&gt;
        &lt;p&gt;딕셔너리에 값을 저장할 때는 대입 연산자 &lt;code&gt;=&lt;/code&gt;를 써야 합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;4&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;문자열은 먼저 &lt;code&gt;split()&lt;/code&gt;할지 확인한다&lt;/strong&gt;
        &lt;p&gt;공백으로 구분된 숫자 문자열은 글자 단위가 아니라 토큰 단위로 다뤄야 합니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-number-item&quot;&gt;
      &lt;span class=&quot;hb-number-badge&quot;&gt;5&lt;/span&gt;
      &lt;div class=&quot;hb-number-content&quot;&gt;
        &lt;strong&gt;취소, 되돌리기, 최근 값 제거는 스택을 떠올린다&lt;/strong&gt;
        &lt;p&gt;&lt;code&gt;append()&lt;/code&gt;로 넣고 &lt;code&gt;pop()&lt;/code&gt;으로 빼는 패턴은 컨트롤 제트 같은 문제에 잘 맞습니다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;h2&gt;9. 같이 보면 좋은 글&lt;/h2&gt;
  &lt;div class=&quot;hb-pill-row&quot;&gt;
    &lt;span class=&quot;hb-pill&quot;&gt;파이썬 정렬과 슬라이싱&lt;/span&gt;
    &lt;span class=&quot;hb-pill&quot;&gt;itertools.combinations&lt;/span&gt;
    &lt;span class=&quot;hb-pill&quot;&gt;딕셔너리와 해시&lt;/span&gt;
    &lt;span class=&quot;hb-pill&quot;&gt;스택 append/pop&lt;/span&gt;
    &lt;span class=&quot;hb-pill&quot;&gt;몫과 나머지 divmod&lt;/span&gt;
  &lt;/div&gt;

  &lt;h2&gt;마무리&lt;/h2&gt;
  &lt;p&gt;이번 문서는 한 가지 문법만 반복하는 글이 아니라, 여러 문제를 통해 자료구조 선택을 연습하는 기록이었습니다. 과일 장수와 개미 군단은 그리디, 소수 만들기는 조합과 소수 판별, 오픈채팅방은 딕셔너리, 컨트롤 제트는 스택이 핵심이었습니다.&lt;/p&gt;
  &lt;p&gt;특히 “내가 지금 다루는 값이 인덱스인지 실제 값인지”, “방금 처리한 기록을 나중에 다시 취소해야 하는지”, “최종 상태를 먼저 만들어야 하는지”를 구분하는 감각이 중요했습니다. 이 감각이 쌓이면 문제를 봤을 때 어떤 도구를 꺼내야 할지 훨씬 빠르게 보입니다.&lt;/p&gt;
&lt;/article&gt;</description>
      <category>AI/Coding_Test</category>
      <category>개미군단</category>
      <category>과일장수</category>
      <category>그리디</category>
      <category>소수만들기</category>
      <category>오픈채팅방</category>
      <category>조합</category>
      <category>컨트롤제트</category>
      <category>코딩테스트</category>
      <category>파이썬</category>
      <category>프로그래머스</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/115</guid>
      <comments>https://onethingflow.tistory.com/entry/Day-10%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%ED%92%80%EC%9D%B4-%EA%B3%BC%EC%9D%BC-%EC%9E%A5%EC%88%98-%EC%86%8C%EC%88%98-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EC%98%A4%ED%94%88%EC%B1%84%ED%8C%85%EB%B0%A9-%EA%B0%9C%EB%AF%B8-%EA%B5%B0%EB%8B%A8-%EC%BB%A8%ED%8A%B8%EB%A1%A4-%EC%A0%9C%ED%8A%B8#entry115comment</comments>
      <pubDate>Wed, 15 Jul 2026 22:49:25 +0900</pubDate>
    </item>
    <item>
      <title>CLAUDE.md 구축 실습</title>
      <link>https://onethingflow.tistory.com/entry/CLAUDEmd-%EA%B5%AC%EC%B6%95-%EC%8B%A4%EC%8A%B5</link>
      <description>&lt;!-- 티스토리 제목: 프롬프트를 다듬는 대신 운영체계를 만들었다: HeoBrain CLAUDE.md 구축기 --&gt;
&lt;div&gt;
&lt;style&gt;
.hb-post{max-width:760px;margin:0 auto;line-height:1.85;font-size:17px;color:#222;word-break:keep-all;}
.hb-post h2{margin:2.4em 0 .7em;font-size:1.32em;line-height:1.4;font-weight:700;padding-bottom:.35em;border-bottom:2px solid #eee;}
.hb-post h3{margin:1.8em 0 .5em;font-size:1.1em;font-weight:700;}
.hb-post p{margin:0 0 1.15em;}
.hb-post code{background:#f4f5f7;border:1px solid #e6e8eb;border-radius:4px;padding:.08em .4em;font-size:.92em;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;color:#b4234d;word-break:normal;}
.hb-post pre{background:#1f2430;color:#eef2ff;border-radius:8px;padding:1.1em 1.2em;overflow-x:auto;line-height:1.65;font-size:.88em;margin:1.4em 0;}
.hb-post pre code{background:transparent;border:0;color:inherit;padding:0;font-size:1em;}
.hb-post .hb-lead{font-size:1.07em;color:#333;}
.hb-post .hb-note-box{background:#f7f9fc;border:1px solid #e3e9f2;border-left:4px solid #4a7dff;border-radius:8px;padding:1.1em 1.3em;margin:1.6em 0;}
.hb-post .hb-note-box p{margin:0 0 .6em;}
.hb-post .hb-note-box p:last-child{margin-bottom:0;}
.hb-post .hb-answer{background:#fbfbfb;border:1px solid #ededed;border-radius:8px;padding:1.1em 1.3em;margin:1.5em 0;}
.hb-post .hb-answer p:last-child{margin-bottom:0;}
.hb-post blockquote.hb-pull{margin:1.6em 0;padding:.9em 1.2em;background:#fff8e6;border-left:4px solid #f5b301;border-radius:6px;font-size:1.08em;font-weight:600;color:#5a4500;}
.hb-post ul,.hb-post ol{margin:0 0 1.2em;padding-left:1.4em;}
.hb-post ul li{list-style:disc;}
.hb-post ol li{list-style:decimal;}
.hb-post li{margin:.42em 0;}
.hb-post .hb-table-wrap{overflow-x:auto;margin:1.6em 0;-webkit-overflow-scrolling:touch;}
.hb-post table{border-collapse:collapse;width:100%;font-size:.94em;min-width:640px;}
.hb-post th,.hb-post td{border:1px solid #e2e5e9;padding:.72em .82em;text-align:left;vertical-align:top;}
.hb-post thead th{background:#f2f4f7;font-weight:700;}
.hb-post tbody tr:nth-child(even){background:#fafbfc;}
.hb-post caption{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);}
.hb-post .hb-references{margin-top:2.6em;padding-top:1.2em;border-top:1px solid #eee;font-size:.94em;color:#555;}
.hb-post .hb-disclaimer{margin-top:1.5em;font-size:.88em;color:#777;}
@media (max-width:640px){.hb-post{font-size:16px;}.hb-post table{min-width:580px;}.hb-post th,.hb-post td{padding:.65em .7em;}}
&lt;/style&gt;
&lt;/div&gt;
&lt;article class=&quot;hb-post&quot;&gt;
&lt;p class=&quot;hb-lead&quot; data-ke-size=&quot;size16&quot;&gt;새 Claude 세션을 열 때마다 나는 같은 설명부터 반복했다. &amp;ldquo;이 프로젝트는 G: 드라이브에 있어서 여기서 npm을 실행하면 안 됩니다.&amp;rdquo; &amp;ldquo;지금 NHN KCP 실결제 심사 중입니다.&amp;rdquo; &amp;ldquo;가격과 결제 로직은 내 승인 없이 바꾸면 안 됩니다.&amp;rdquo; AI가 코드를 쓰는 시간보다 프로젝트의 사정을 다시 인수인계하는 시간이 더 아깝게 느껴졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그릿 모먼츠 Task 7의 표면적인 과제는 나에게 맞춘 &lt;code&gt;CLAUDE.md&lt;/code&gt; 초안 한 개를 만드는 것이었다. 하지만 관련 책을 읽고 나니 이 파일은 자기소개서도, 긴 만능 프롬프트도 아니었다. 세션이 바뀌어도 일을 이어가고, 위험한 행동을 멈추고, 완료 여부를 같은 기준으로 판단하게 만드는 작은 운영체계에 가까웠다.&lt;/p&gt;
&lt;div class=&quot;hb-note-box&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이번 과제에서 실제로 만든 것&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글로벌&amp;middot;프로젝트 &lt;code&gt;CLAUDE.md&lt;/code&gt;, 상태와 결정을 분리한 기억 파일, 시작&amp;middot;검토&amp;middot;배포용 명령을 HeoBrain에 적용했다. 새 세션에서 &lt;code&gt;/작업시작&lt;/code&gt;을 실행해 어제의 맥락이 이어지는지도 스트레스 테스트했다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 책에서 가져온 것은 문장이 아니라 구조였다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;『팀이 필요하다. 사람 말고.』에서 가장 크게 남은 생각은 지식이 대화 세션이 아니라 파일에 살아야 한다는 것이었다. 프롬프트는 요청할 때마다 다시 입력하지만, 프로토콜은 한 번 만들어 두면 새 세션이 먼저 읽고 같은 순서로 움직인다. 『하네스 엔지니어링 실전 플레이북』도 고성능 모델 하나보다 모델을 둘러싼 역할 분리, 검증 계약, 파일 기반 인계, 낡은 규칙 점검이 프로덕션 품질을 만든다고 설명한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 이 내용을 세 가지 원칙으로 번역해 HeoBrain에 적용했다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;책의 원칙과 HeoBrain 적용 내용&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;책에서 얻은 원칙&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;내가 적용한 방식&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;해결하려던 문제&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;대화보다 파일에 남긴다&lt;/td&gt;
&lt;td&gt;&lt;code&gt;progress.md&lt;/code&gt;, &lt;code&gt;MEMORY.md&lt;/code&gt;, &lt;code&gt;decisions.md&lt;/code&gt;, &lt;code&gt;FAILURES.md&lt;/code&gt;로 정보를 분리했다.&lt;/td&gt;
&lt;td&gt;세션이 바뀔 때마다 현재 상태와 과거 결정을 다시 설명하는 문제&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;생성과 평가를 분리한다&lt;/td&gt;
&lt;td&gt;Gen/Eval 분리의 v0로, 구현 세션이 스스로 PASS를 선언하지 않고 별도 세션의 &lt;code&gt;/검토&lt;/code&gt; 또는 &lt;code&gt;/code-review&lt;/code&gt;가 검사하게 했다.&lt;/td&gt;
&lt;td&gt;자기가 만든 결과를 자기가 후하게 채점하는 문제&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;완료 조건을 먼저 계약한다&lt;/td&gt;
&lt;td&gt;타입체크, 시크릿 스캔, C:\TEMP 클론 빌드, 돈 로직 시나리오, 라이브 확인을 게이트로 적었다.&lt;/td&gt;
&lt;td&gt;코드만 수정하고 &amp;ldquo;완료&amp;rdquo;라고 말하는 문제&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;규칙도 노후화된다고 본다&lt;/td&gt;
&lt;td&gt;PG사&amp;middot;FAQ&amp;middot;명령어&amp;middot;경로를 분기마다 확인하는 신선도 점검을 넣었다.&lt;/td&gt;
&lt;td&gt;코드는 정상인데 안내 문구와 운영 지식이 오래되는 문제&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;blockquote class=&quot;hb-pull&quot; data-ke-style=&quot;style1&quot;&gt;좋은 AI를 기다리는 것보다, 지금의 AI가 실수하기 어렵고 일을 이어가기 쉬운 환경을 만드는 편이 내 문제에 더 직접적인 해법이었다.&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 왜 HeoBrain에는 일반 템플릿이 통하지 않았나&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HeoBrain은 오픽&amp;middot;영단어&amp;middot;영문법&amp;middot;AWS 학습 자료를 판매하는 실제 서비스다. Next.js 16, TypeScript, Supabase, PortOne V2와 NHN KCP를 사용하고 있으며, 지금은 실결제 심사를 진행하고 있다. 이 프로젝트에서 AI가 놓치면 안 되는 맥락은 &amp;ldquo;깔끔한 코드를 작성하라&amp;rdquo; 같은 추상적인 문장이 아니었다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Google Drive가 마운트된 G: 리포지토리에서는 파일 잠금 문제 때문에 npm 빌드를 실행하지 않는다. 검증용 코드는 &lt;code&gt;C:\TEMP&lt;/code&gt;로 복사한다.&lt;/li&gt;
&lt;li&gt;결제 검증, 환불, 가격, 사업자 정보, 개인정보, 사용자 데이터 삭제, &lt;code&gt;.env&lt;/code&gt; 수정은 사람이 결정하는 L4 작업이다.&lt;/li&gt;
&lt;li&gt;가격이 0원이면 결제창을 띄우지 않고 무료 수령 흐름으로 보내야 한다.&lt;/li&gt;
&lt;li&gt;같은 &lt;code&gt;payment_id&lt;/code&gt;의 중복 처리 차단과 서버의 결제 금액 검증을 완화하면 안 된다.&lt;/li&gt;
&lt;li&gt;push하면 Vercel이 자동 배포되므로, push 자체가 프로덕션 변경에 해당한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 규칙은 인터넷에서 복사한 &lt;code&gt;CLAUDE.md&lt;/code&gt; 템플릿으로는 나올 수 없다. 내가 운영하면서 겪은 제약, 지금 진행 중인 심사, 돈이 움직이는 경계가 들어가야 비로소 &amp;ldquo;허태웅이라는 엔지니어의 파일&amp;rdquo;이 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 한 파일에 다 넣지 않고 기억을 계층으로 나눴다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 초안에서 가장 먼저 발견한 문제는 &lt;code&gt;progress.md&lt;/code&gt;와 &lt;code&gt;MEMORY.md&lt;/code&gt;가 빠져 있었다는 점이다. &lt;code&gt;CLAUDE.md&lt;/code&gt;만 길게 만들면 모든 정보가 한 파일에 섞이고, 오늘의 상태가 내일의 상수처럼 남는다. 그래서 정보의 수명과 역할에 따라 파일을 분리했다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;HeoBrain 기억 계층&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;파일&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;담는 내용&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;실제 예시&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;글로벌 &lt;code&gt;CLAUDE.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;잘 바뀌지 않는 정체성&amp;middot;목표&amp;middot;공통 원칙&lt;/td&gt;
&lt;td&gt;AI를 팀처럼 지휘하는 1인 개발팀, 한국어 소통, 검증 증거 우선&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;프로젝트 &lt;code&gt;CLAUDE.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;HeoBrain의 기술&amp;middot;도메인&amp;middot;권한&amp;middot;완료 기준&lt;/td&gt;
&lt;td&gt;KCP 결제, G: 빌드 제약, L1~L4, 돈 로직 시나리오 5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;progress.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;지금 하는 일, 막힌 일, 다음 세션의 첫 행동&lt;/td&gt;
&lt;td&gt;Resend 인증, KCP 심사 항목, 900원 실결제 준비&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MEMORY.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;최근 결정 요약, 기술 부채, 환경 정보&lt;/td&gt;
&lt;td&gt;비회원 구매 도입, 주문 메일 미발송 부채, 레거시 문서&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docs/decisions.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;배경&amp;middot;선택지&amp;middot;결정&amp;middot;근거&amp;middot;결과를 남기는 ADR&lt;/td&gt;
&lt;td&gt;LangChain 대신 얇은 SDK 직결 선택, 비회원 구매 도입 근거&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docs/FAILURES.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;장애의 증상&amp;middot;원인&amp;middot;조치&amp;middot;교훈&lt;/td&gt;
&lt;td&gt;latest 의존성 빌드 붕괴, 뉴스레터 가짜 성공, 환불 API 인증 누락&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조에서 &lt;code&gt;CLAUDE.md&lt;/code&gt;는 모든 지식을 담는 창고가 아니다. 무엇을 먼저 읽고, 어느 파일을 진실의 원천으로 삼고, 어떤 기준으로 행동할지를 알려 주는 입구다. 현재 상태는 &lt;code&gt;progress.md&lt;/code&gt;, 오래 남길 결정은 ADR, 실패에서 얻은 교훈은 &lt;code&gt;FAILURES.md&lt;/code&gt;에 둔다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. AI 초안을 그대로 받지 않고 내가 바꾼 것&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 과제의 중요한 부분은 AI가 작성한 문서를 저장한 일이 아니라, 내가 운영자로서 틀린 부분을 찾아 경계를 다시 정한 일이었다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;&amp;nbsp; 빠진 기억 계층을 복구했다.&lt;/b&gt; 첫 초안에 없던 &lt;code&gt;progress.md&lt;/code&gt;와 &lt;code&gt;MEMORY.md&lt;/code&gt;를 추가하고, 상세 결정과 실패 로그까지 연결했다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&amp;nbsp; 스택을 유행 목록이 아니라 의사결정으로 바꿨다.&lt;/b&gt; 후보를 나열하고 끝내지 말고 프로젝트 규모와 디버깅 비용의 trade-off를 설명한 뒤 추천 하나를 고르게 했다. AI 서비스 기본 방향은 두꺼운 LangChain 추상화보다 Vercel AI SDK와 Claude Agent SDK의 직접 연결로 정했다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&amp;nbsp; TypeScript 프로젝트의 네이밍을 바로잡았다.&lt;/b&gt; 함수 이름을 Python식 snake_case가 아니라 기존 코드와 같은 camelCase로 확정했다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&amp;nbsp; 자율성보다 승인선을 먼저 그었다.&lt;/b&gt; L3는 계획을 먼저 보고하고 승인 후 착수, L4는 결제&amp;middot;환불&amp;middot;가격&amp;middot;개인정보&amp;middot;프로덕션 DB&amp;middot;&lt;code&gt;.env&lt;/code&gt;처럼 사람이 반드시 결정하도록 바꿨다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp;생성과 검토를 나누는 v0를 시작했다.&lt;/b&gt; 구현한 세션은 자기 코드를 통과 판정하지 못한다. 결제&amp;middot;인증&amp;middot;DB처럼 위험한 변경은 별도 세션의 독립 검토와 실제 시나리오 검증을 모두 거치게 했다. 전용 평가 에이전트와 고정 루브릭은 다음 단계다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&amp;nbsp; 도구의 실제 제약도 확인했다.&lt;/b&gt; 새로 만든 슬래시 명령은 작성 중인 세션이 아니라 새 세션부터 인식된다는 점을 스트레스 테스트 과정에서 확인했다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 배운 역할 분담은 분명했다. AI는 초안을 빠르게 만들고 누락 가능성을 넓게 탐색한다. 나는 실제 코드베이스와 사업 맥락에 비춰 사실을 확인하고, 무엇을 자동화하면 안 되는지 결정한다. 1인 개발팀에서 사람의 핵심 업무는 타이핑이 아니라 설계&amp;middot;검증&amp;middot;운영 판단이었다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 새 세션 스트레스 테스트: 한마디로 어제 일을 이어갈 수 있나&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 만든 뒤에는 같은 세션에서 &amp;ldquo;잘 됐다&amp;rdquo;고 평가하지 않았다. 새 세션을 열고 &lt;code&gt;/작업시작&lt;/code&gt;만 입력했다. 이 명령은 &lt;code&gt;progress.md &amp;rarr; MEMORY.md &amp;rarr; decisions.md &amp;rarr; FAILURES.md &amp;rarr; 최근 커밋&lt;/code&gt; 순서로 읽고, 이어서 할 일&amp;middot;사람의 액션이 필요한 막힘&amp;middot;오늘의 제안을 구분해 보고하도록 설계했다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;스트레스 테스트 전후 비교&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;확인 항목&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;파일이 없을 때&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;&lt;code&gt;/작업시작&lt;/code&gt; 실행 후&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;현재 작업&lt;/td&gt;
&lt;td&gt;내가 KCP 심사와 실결제 준비를 다시 설명해야 한다.&lt;/td&gt;
&lt;td&gt;Task 7 마무리와 900원 실결제&amp;middot;비회원 결제 준비를 이어서 제시했다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;막힌 일&lt;/td&gt;
&lt;td&gt;AI가 할 일과 내가 처리할 일이 한 목록에 섞인다.&lt;/td&gt;
&lt;td&gt;Resend 인증과 KCP 심사 항목을 &amp;lsquo;사장님 액션 대기&amp;rsquo;로 분리했다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;최근 맥락&lt;/td&gt;
&lt;td&gt;지난 작업의 변경 흐름을 내가 요약해야 한다.&lt;/td&gt;
&lt;td&gt;최근 5개 커밋과 라이브 확인 상태를 먼저 요약했다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;권한 경계&lt;/td&gt;
&lt;td&gt;push나 결제 변경을 바로 시도할 위험이 있다.&lt;/td&gt;
&lt;td&gt;push는 자동 배포이므로 내 실행 항목으로 남기고, AI는 다음 작업을 제안하는 데서 멈췄다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-answer&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;회고 &amp;mdash; 이 파일이 없었으면?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI는 &amp;ldquo;무엇을 도와드릴까요?&amp;rdquo;로 시작했을 것이고, 나는 G: 드라이브에서 npm이 안 된다는 것과 KCP 심사 중이라는 맥락을 또 설명했을 것이다. 실제로는 &lt;code&gt;/작업시작&lt;/code&gt; 한마디에 Resend 미설정, 심사 대기, 다음 실결제 준비가 이어졌다. 특히 막힌 일이 내 액션 대기 항목으로 분리되면서 AI가 할 일과 내가 할 일이 바로 구분됐다. 프롬프트를 다듬는 것보다 프로토콜 파일이 세션 사이의 기억을 잇는 효과가 더 컸다.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 한 번의 테스트가 이 하네스의 안전성을 증명하는 것은 아니다. 다만 목표였던 &amp;ldquo;새 세션에서 맥락을 이어받고, 사람과 AI의 다음 행동을 구분하는가&amp;rdquo;에는 성공했다. 이것은 막연한 생산성 수치보다 내가 직접 확인한 변화다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 현재는 v1이다: 적어 둔 규칙과 강제 장치는 다르다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 구현을 다섯 계층의 완성형이라고 부르면 과장이다. 지식&amp;middot;기억 계층은 파일로 갖췄고, 역할&amp;middot;방어 규칙도 문서에 넣었지만, 실제 전용 에이전트와 자동 차단 장치는 아직 일부만 존재한다. &lt;code&gt;CLAUDE.md&lt;/code&gt;에 &amp;ldquo;하지 말라&amp;rdquo;고 쓰는 것은 행동 지침이지 물리적인 보안 장치가 아니다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;현재 하네스와 다음 단계&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;계층&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;현재 v1&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;다음 단계&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;지식&lt;/td&gt;
&lt;td&gt;글로벌&amp;middot;프로젝트 &lt;code&gt;CLAUDE.md&lt;/code&gt;, ADR&lt;/td&gt;
&lt;td&gt;규칙이 길어지면 경로별 파일로 분리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;기억&lt;/td&gt;
&lt;td&gt;&lt;code&gt;progress.md&lt;/code&gt;, &lt;code&gt;MEMORY.md&lt;/code&gt;, &lt;code&gt;FAILURES.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;장애가 반복되면 교훈을 자동 검사 또는 금지 규칙으로 승격&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;역할&lt;/td&gt;
&lt;td&gt;단일 구현 세션과 별도 검토 세션으로 Gen/Eval 분리의 v0 시작&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.claude/agents/&lt;/code&gt;에 code-reviewer&amp;middot;qa 역할 추가&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;방어&lt;/td&gt;
&lt;td&gt;타입체크&amp;middot;시크릿 스캔&amp;middot;클론 빌드&amp;middot;돈 로직 시나리오&lt;/td&gt;
&lt;td&gt;pre-commit 훅으로 시크릿과 타입 오류를 자동 차단&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;자율&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/헬스체크&lt;/code&gt; 수동 실행, L4는 사람 승인&lt;/td&gt;
&lt;td&gt;일일 헬스체크와 PG 결제 대사 크론, 이상 등급별 알림&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 자율화의 목표는 AI에게 무조건 많은 권한을 주는 것이 아니다. 정상일 때는 조용히 점검하고, 실패하면 기록에서 재개하며, 돈과 개인정보가 걸린 경계에서는 반드시 사람을 호출하는 구조가 목표다. 또한 분기마다 끝난 심사 상태, 죽은 명령어, 바뀐 PG사와 안내 문구를 걷어 내야 이 파일이 살아 있는 운영 문서로 남는다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 이번 과제의 결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 &lt;code&gt;CLAUDE.md&lt;/code&gt;를 &amp;ldquo;AI에게 나를 설명하는 파일&amp;rdquo; 정도로 생각했다. 과제를 끝낸 뒤에는 정의가 달라졌다. 이 파일은 내가 반복해서 내리는 판단을 프로젝트가 기억하게 만드는 운영 계약의 입구다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1인 개발팀은 AI 창을 여러 개 띄우는 것으로 완성되지 않는다. 누가 만들고 누가 검토하는지, 어떤 상태를 어디에 남기는지, 무엇을 통과해야 완료인지, 어느 순간 사람이 결정권을 가져오는지가 분명해야 한다. 이번 Task 7에서 만든 것은 그 구조의 v1이다.&lt;/p&gt;
&lt;blockquote class=&quot;hb-pull&quot; data-ke-style=&quot;style1&quot;&gt;프롬프트는 한 번의 답을 바꾸지만, 프로토콜은 다음 세션의 출발점을 바꾼다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 과제는 더 긴 지침을 쓰는 일이 아니다. 역할 에이전트를 실제로 분리하고, 중요한 규칙을 훅과 테스트로 강제하며, 실패할 때마다 교훈을 구조에 누적하는 일이다. 그렇게 해야 AI를 &amp;ldquo;잘 쓰는 사람&amp;rdquo;을 넘어, AI가 일할 수 있는 팀을 설계하는 엔지니어에 가까워질 수 있다.&lt;/p&gt;
&lt;div class=&quot;hb-references&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;읽고 적용한 자료&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Team Grit, 『팀이 필요하다. 사람 말고.』 &amp;mdash; 프로토콜과 프롬프트, 다섯 계층, &lt;code&gt;progress.md&lt;/code&gt;, Gen/Val 분리(PDF pp.13~32, 37~40)&lt;/li&gt;
&lt;li&gt;Team Grit, 『하네스 엔지니어링 실전 플레이북』 &amp;mdash; Generator/Evaluator 분리, 검증 계약, 파일 기반 인계, 신선도 감사(PDF pp.10~14, 22~24, 39~46, 72~80)&lt;/li&gt;
&lt;li&gt;『Claude Code로 1인 개발팀 만들기』 &amp;mdash; 글로벌&amp;middot;프로젝트 &lt;code&gt;CLAUDE.md&lt;/code&gt;, 역할&amp;middot;권한&amp;middot;검증&amp;middot;실패의 규칙화(PDF pp.21~23, 43~55, 97~124, 147~162)&lt;/li&gt;
&lt;li&gt;『링크드인 온보딩 가이드』 &amp;mdash; 실제 경험 하나를 훅&amp;middot;상황&amp;middot;시도&amp;middot;깨달음&amp;middot;질문으로 정리하는 글쓰기 구조(PDF pp.38~42)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p class=&quot;hb-disclaimer&quot; data-ke-size=&quot;size16&quot;&gt;이 글은 책의 일반론을 요약한 글이 아니라, 2026년 7월 HeoBrain 프로젝트에 Task 7을 직접 적용하고 새 세션에서 검증한 경험을 바탕으로 작성했다. 책 속 사례 수치는 보편적 성과로 일반화하지 않고, 내 프로젝트에서 확인한 결과만 서술했다.&lt;/p&gt;
&lt;/article&gt;</description>
      <category>AI</category>
      <category>Claude</category>
      <category>CLAUDE.md</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/114</guid>
      <comments>https://onethingflow.tistory.com/entry/CLAUDEmd-%EA%B5%AC%EC%B6%95-%EC%8B%A4%EC%8A%B5#entry114comment</comments>
      <pubDate>Wed, 15 Jul 2026 14:48:11 +0900</pubDate>
    </item>
    <item>
      <title>AI 코딩 에이전트에게 프로젝트 규칙을 기억시키는 법(AGENTS.md와 CLAUDE.md)</title>
      <link>https://onethingflow.tistory.com/entry/AI-%EC%BD%94%EB%94%A9-%EC%97%90%EC%9D%B4%EC%A0%84%ED%8A%B8%EC%97%90%EA%B2%8C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EA%B7%9C%EC%B9%99%EC%9D%84-%EA%B8%B0%EC%96%B5%EC%8B%9C%ED%82%A4%EB%8A%94-%EB%B2%95AGENTSmd%EC%99%80-CLAUDEmd</link>
      <description>&lt;!--
제목: AGENTS.md와 CLAUDE.md의 차이: AI 코딩 에이전트에게 프로젝트 규칙을 기억시키는 법
메타 설명: AGENTS.md와 CLAUDE.md가 각각 어떤 도구에서 어떻게 읽히는지, 로딩 범위와 우선순위, 멀티에이전트용 권장 구조, 실전 작성 예시까지 정리했습니다.
추천 태그: AGENTS.md, CLAUDE.md, Claude Code, OpenAI Codex, AI 에이전트, AI 코딩, 개발 생산성, 프롬프트 엔지니어링
업데이트: 2026-07-15
발행 메모: 이 주석의 제목·메타 설명·태그는 티스토리에 자동 반영되지 않습니다. 발행 화면에서 각각 입력하고, 아래 style과 article을 HTML 모드 본문에 붙여 넣으세요.
--&gt;

&lt;style&gt;
.hb-post{max-width:760px;margin:0 auto;line-height:1.85;font-size:17px;color:#222;word-break:keep-all;}
.hb-post h2{margin:2.45em 0 .75em;font-size:1.34em;line-height:1.4;font-weight:750;padding-bottom:.38em;border-bottom:2px solid #e9edf3;}
.hb-post h3{margin:1.8em 0 .55em;font-size:1.1em;line-height:1.5;font-weight:750;}
.hb-post p{margin:0 0 1.15em;}
.hb-post a{color:#245fd6;text-decoration:none;}
.hb-post a:hover{text-decoration:underline;}
.hb-post code{background:#f4f5f7;border:1px solid #e4e7eb;border-radius:4px;padding:.08em .4em;font-size:.91em;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;color:#b42355;word-break:normal;}
.hb-post pre{background:#1f2430;color:#eef2ff;border-radius:10px;padding:1.15em 1.25em;overflow-x:auto;line-height:1.62;font-size:.86em;margin:1.35em 0;white-space:pre;}
.hb-post pre code{background:transparent;border:0;color:inherit;padding:0;font-size:1em;}
.hb-post ul,.hb-post ol{margin:0 0 1.25em;padding-left:1.45em;}
.hb-post li{margin:.45em 0;}
.hb-post .hb-kicker{display:inline-block;margin:0 0 1em;padding:.35em .7em;border-radius:999px;background:#edf4ff;color:#2856a6;font-size:.82em;font-weight:700;}
.hb-post .hb-lead{font-size:1.08em;color:#30343b;}
.hb-post .hb-note-box{background:#f7f9fc;border:1px solid #e1e7f0;border-left:4px solid #4a7dff;border-radius:9px;padding:1.15em 1.3em;margin:1.6em 0;}
.hb-post .hb-note-box p{margin:0 0 .65em;}
.hb-post .hb-note-box p:last-child{margin-bottom:0;}
.hb-post blockquote.hb-pull{margin:1.7em 0;padding:1em 1.2em;background:#fff8e6;border-left:4px solid #f2b400;border-radius:7px;font-size:1.08em;font-weight:700;color:#584400;}
.hb-post .hb-table-wrap{overflow-x:auto;margin:1.6em 0;-webkit-overflow-scrolling:touch;}
.hb-post table{border-collapse:collapse;width:100%;min-width:690px;font-size:.93em;}
.hb-post th,.hb-post td{border:1px solid #dfe4ea;padding:.72em .8em;text-align:left;vertical-align:top;}
.hb-post thead th{background:#f1f4f8;font-weight:750;}
.hb-post tbody tr:nth-child(even){background:#fafbfd;}
.hb-post caption{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);}
.hb-post .hb-card-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1em;margin:1.4em 0;}
.hb-post .hb-card{border:1px solid #e1e5eb;border-radius:10px;padding:1.05em 1.15em;background:#fff;}
.hb-post .hb-card h3{margin:0 0 .45em;font-size:1em;color:#244a91;}
.hb-post .hb-card p{margin:0;font-size:.95em;}
.hb-post .hb-warning{background:#fff7f2;border:1px solid #ffd9c7;border-left:4px solid #f06b3a;border-radius:9px;padding:1.05em 1.25em;margin:1.5em 0;}
.hb-post .hb-warning p{margin:0;}
.hb-post .hb-checklist{background:#fbfbfc;border:1px solid #e7e8eb;border-radius:10px;padding:1.15em 1.3em;margin:1.5em 0;}
.hb-post .hb-checklist li{margin:.55em 0;}
.hb-post .hb-references{margin-top:2.7em;padding-top:1.2em;border-top:1px solid #e8eaed;font-size:.94em;}
.hb-post .hb-references h2{margin-top:0;}
.hb-post .hb-disclaimer{margin-top:1.7em;font-size:.88em;color:#777;}
@media (max-width:640px){
  .hb-post{font-size:16px;line-height:1.78;}
  .hb-post .hb-card-grid{grid-template-columns:1fr;}
  .hb-post pre{font-size:.8em;padding:1em;}
}
&lt;/style&gt;

&lt;article class=&quot;hb-post&quot;&gt;
  &lt;p class=&quot;hb-kicker&quot;&gt;AI 에이전트 운영 파일 가이드 · 2026년 7월 기준&lt;/p&gt;

  &lt;p class=&quot;hb-lead&quot;&gt;AI에게 매번 “이 프로젝트는 &lt;code&gt;pnpm&lt;/code&gt;을 쓰고, 생성 파일은 직접 수정하지 말고, 작업이 끝나면 테스트를 실행해”라고 설명하고 있다면 문제는 모델 성능보다 &lt;strong&gt;프로젝트의 암묵지가 저장소에 없다는 것&lt;/strong&gt;일 수 있다.&lt;/p&gt;

  &lt;p&gt;대화창의 지시는 세션이 바뀌면 사라지기 쉽다. 반면 &lt;code&gt;AGENTS.md&lt;/code&gt;와 &lt;code&gt;CLAUDE.md&lt;/code&gt;는 빌드 명령, 코드 규칙, 금지사항, 완료 기준을 프로젝트와 함께 버전 관리할 수 있게 해준다. 다만 두 파일은 이름만 다른 같은 기능이 아니다. 자동으로 읽는 도구와 탐색 방식이 다르며, 이 차이를 무시하면 “분명 파일에 적었는데 왜 안 지키지?”라는 문제가 생긴다.&lt;/p&gt;

  &lt;div class=&quot;hb-note-box&quot;&gt;
    &lt;p&gt;&lt;strong&gt;먼저 보는 핵심 결론&lt;/strong&gt;&lt;/p&gt;
    &lt;p&gt;① &lt;code&gt;AGENTS.md&lt;/code&gt;는 여러 AI 코딩 도구가 채택하는 개방형 프로젝트 지침 포맷이며, OpenAI Codex가 기본적으로 읽는다.&lt;/p&gt;
    &lt;p&gt;② &lt;code&gt;CLAUDE.md&lt;/code&gt;는 Claude Code가 기본적으로 읽는 지속 지침 파일이다. Claude Code는 &lt;code&gt;AGENTS.md&lt;/code&gt;를 자동으로 읽지 않는다.&lt;/p&gt;
    &lt;p&gt;③ 여러 에이전트를 함께 쓴다면 &lt;code&gt;AGENTS.md&lt;/code&gt;를 공용 원본으로 두고, &lt;code&gt;CLAUDE.md&lt;/code&gt;에서 &lt;code&gt;@AGENTS.md&lt;/code&gt;를 불러온 뒤 Claude 전용 규칙만 덧붙이는 구성이 실용적이다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2&gt;1. 공유된 Claude Cowork 사례에서 배울 점&lt;/h2&gt;

  &lt;p&gt;공유 자료의 Claude Cowork 구성은 프로젝트 루트의 &lt;code&gt;CLAUDE.md&lt;/code&gt;에 사람, 용어, 공통 작업 방식처럼 전체에 걸친 기억을 두고, &lt;code&gt;investments/&lt;/code&gt;나 &lt;code&gt;personal/&lt;/code&gt; 같은 업무 폴더의 &lt;code&gt;CLAUDE.md&lt;/code&gt;에는 그 영역의 역할과 말투를 두는 구조를 제안한다. 공통 원칙과 업무별 맥락을 계층으로 나눈다는 점이 핵심이다.&lt;/p&gt;

  &lt;p&gt;이 설계 원리는 좋은 출발점이다. 모든 규칙을 거대한 하나의 프롬프트에 넣는 대신, 루트에는 공통 규칙을 두고 가까운 폴더에는 그 작업에만 필요한 규칙을 둔다. 그러면 투자 분석을 할 때의 신중한 기준과 콘텐츠를 쓸 때의 문체를 서로 섞지 않을 수 있다.&lt;/p&gt;

  &lt;blockquote class=&quot;hb-pull&quot;&gt;좋은 지침 파일은 AI를 더 똑똑하게 만드는 마법의 프롬프트가 아니다. 해당 저장소에서 “무엇을 알고, 어떻게 일하고, 무엇으로 완료를 증명해야 하는지”를 적은 운영 계약이다.&lt;/blockquote&gt;

  &lt;p&gt;단, Claude 중심의 폴더 구조를 Codex나 다른 에이전트가 그대로 읽을 것이라고 가정하면 안 된다. 공통·하위 규칙을 나눈다는 설계 원리는 공유할 수 있지만, 실제 파일명과 로딩 범위는 각 제품의 공식 동작에 맞춰야 한다.&lt;/p&gt;

  &lt;h2&gt;2. AGENTS.md와 CLAUDE.md는 무엇이 다른가&lt;/h2&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;AGENTS.md와 CLAUDE.md 비교&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;구분&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;AGENTS.md&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;CLAUDE.md&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;성격&lt;/td&gt;
          &lt;td&gt;여러 코딩 에이전트를 위한 개방형 Markdown 지침 포맷&lt;/td&gt;
          &lt;td&gt;Claude Code 전용 지속 지침·프로젝트 컨텍스트&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;기본 인식&lt;/td&gt;
          &lt;td&gt;OpenAI Codex가 기본 지원한다. 다른 도구의 지원과 탐색 규칙은 각 문서를 확인해야 한다.&lt;/td&gt;
          &lt;td&gt;Claude Code가 기본 지원한다. Claude Code는 AGENTS.md를 직접 자동 인식하지 않는다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;대표 범위&lt;/td&gt;
          &lt;td&gt;Codex 기준 글로벌 설정, 프로젝트 루트, 현재 작업 디렉터리까지의 하위 계층&lt;/td&gt;
          &lt;td&gt;조직 정책, 사용자, 프로젝트, 개인용 로컬 파일, 하위 폴더&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;결합 방식&lt;/td&gt;
          &lt;td&gt;Codex는 루트에서 현재 작업 디렉터리 순으로 합치며, 가까운 지침이 뒤에 와 앞선 지침을 덮는 방식으로 취급한다.&lt;/td&gt;
          &lt;td&gt;발견한 파일을 모두 이어 붙인다. 가까운 파일이 뒤에 오지만 충돌 시 확정적 덮어쓰기를 보장하지 않으므로 모순을 없애야 한다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;하위 폴더&lt;/td&gt;
          &lt;td&gt;Codex의 시작 체인은 현재 작업 디렉터리에서 끝난다. 특정 하위 규칙은 해당 디렉터리에서 시작해 확인하는 편이 안전하다.&lt;/td&gt;
          &lt;td&gt;현재 위치 아래의 CLAUDE.md는 관련 하위 파일을 읽을 때 필요에 따라 로드된다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;모듈화&lt;/td&gt;
          &lt;td&gt;중첩 AGENTS.md, Codex의 AGENTS.override.md와 대체 파일명 설정&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;@path&lt;/code&gt; 가져오기, &lt;code&gt;.claude/rules/&lt;/code&gt;, 경로별 규칙, CLAUDE.local.md&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;길이 기준&lt;/td&gt;
          &lt;td&gt;Codex는 합산 크기를 기본 32KiB까지 읽는다.&lt;/td&gt;
          &lt;td&gt;Anthropic은 파일당 200줄 미만을 목표로 권장한다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;강제성&lt;/td&gt;
          &lt;td colspan=&quot;2&quot;&gt;둘 다 기본적으로 모델에 주는 지침이다. CI에서 lint·test를 실행하고 branch protection으로 통과를 강제하며, 위험 동작은 permissions·sandbox·차단 훅·승인 절차로 통제해야 한다.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;p&gt;&lt;a href=&quot;https://agents.md/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;AGENTS.md 공식 사이트&lt;/a&gt;는 이를 “에이전트를 위한 README”에 비유한다. 사람용 README를 길게 만들지 않으면서 설치 방법, 테스트 명령, 코드 스타일, 보안 주의사항처럼 에이전트가 작업할 때 필요한 정보를 예측 가능한 위치에 제공하자는 취지다. 필수 필드가 정해진 설정 파일이 아니라 일반 Markdown이므로, 프로젝트에 맞는 섹션을 직접 구성하면 된다.&lt;/p&gt;

  &lt;h2&gt;3. 실제로 어떤 파일이 로드되는가&lt;/h2&gt;

  &lt;h3&gt;Codex: 프로젝트 루트에서 현재 작업 디렉터리까지&lt;/h3&gt;

  &lt;p&gt;&lt;a href=&quot;https://learn.chatgpt.com/docs/agent-configuration/agents-md&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenAI 공식 AGENTS.md 가이드&lt;/a&gt;에 따르면 Codex는 실행 또는 세션 시작 시 지침 체인을 구성한다. 먼저 Codex 홈 디렉터리에서 &lt;code&gt;AGENTS.override.md&lt;/code&gt;를 찾고, 없으면 &lt;code&gt;AGENTS.md&lt;/code&gt;를 읽는다. 프로젝트에서는 보통 Git 루트부터 현재 작업 디렉터리까지 내려오며 각 디렉터리에서 하나의 지침 파일을 선택한다.&lt;/p&gt;

  &lt;ol&gt;
    &lt;li&gt;글로벌 범위: &lt;code&gt;AGENTS.override.md&lt;/code&gt;가 있으면 우선하고, 없으면 &lt;code&gt;AGENTS.md&lt;/code&gt;를 사용한다.&lt;/li&gt;
    &lt;li&gt;프로젝트 범위: 각 디렉터리에서 &lt;code&gt;AGENTS.override.md&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt;, 설정된 대체 파일명 순으로 확인한다.&lt;/li&gt;
    &lt;li&gt;병합 순서: 루트에서 현재 디렉터리 순으로 합치므로, 더 가까운 지침이 뒤에 놓인다.&lt;/li&gt;
    &lt;li&gt;용량: 비어 있는 파일은 건너뛰고 합산 크기가 &lt;a href=&quot;https://learn.chatgpt.com/docs/agent-configuration/agents-md&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;기본 32KiB&lt;/a&gt;에 도달하면 추가 로딩을 멈춘다.&lt;/li&gt;
  &lt;/ol&gt;

  &lt;p&gt;여기서 놓치기 쉬운 점은 “저장소 어딘가에 AGENTS.md가 있으면 항상 전부 읽는다”가 아니라는 사실이다. 예를 들어 루트에서 Codex를 시작했다면 더 아래의 특정 패키지 규칙이 시작 체인에 들어오지 않을 수 있다. 중요한 하위 규칙은 &lt;code&gt;--cd&lt;/code&gt; 등으로 그 디렉터리에서 시작해 활성 지침을 확인하는 습관이 필요하다.&lt;/p&gt;

  &lt;h3&gt;Claude Code: CLAUDE.md를 읽고 하위 파일은 필요할 때 로드&lt;/h3&gt;

  &lt;p&gt;Claude Code는 사용자 범위의 &lt;code&gt;~/.claude/CLAUDE.md&lt;/code&gt;, 프로젝트의 &lt;code&gt;./CLAUDE.md&lt;/code&gt; 또는 &lt;code&gt;./.claude/CLAUDE.md&lt;/code&gt;, 개인 프로젝트 설정인 &lt;code&gt;./CLAUDE.local.md&lt;/code&gt; 등을 지원한다. 현재 작업 디렉터리에서 상위로 올라가며 파일을 찾은 뒤, 파일시스템 루트에서 현재 디렉터리 순으로 컨텍스트에 이어 붙인다.&lt;/p&gt;

  &lt;p&gt;현재 위치보다 아래에 있는 &lt;code&gt;CLAUDE.md&lt;/code&gt;는 시작할 때 모두 넣지 않는다. Claude가 해당 하위 디렉터리의 파일을 읽을 때 관련 지침이 로드된다. 공유 자료에서 업무 폴더마다 역할과 말투를 분리한 구조가 Claude Code의 동작과 잘 맞는 이유다.&lt;/p&gt;

  &lt;div class=&quot;hb-warning&quot;&gt;
    &lt;p&gt;&lt;strong&gt;중요:&lt;/strong&gt; &lt;a href=&quot;https://code.claude.com/docs/en/memory#agentsmd&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Anthropic 공식 문서&lt;/a&gt;는 Claude Code가 &lt;code&gt;CLAUDE.md&lt;/code&gt;를 읽으며 &lt;code&gt;AGENTS.md&lt;/code&gt;는 직접 읽지 않는다고 명시한다. 두 파일을 같은 내용으로 복사해 두면 언젠가 서로 달라질 가능성이 크다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2&gt;4. 멀티에이전트라면 ‘공용 원본 + 얇은 어댑터’&lt;/h2&gt;

  &lt;p&gt;Codex와 Claude Code를 같은 저장소에서 쓴다면 가장 단순한 구성은 &lt;code&gt;AGENTS.md&lt;/code&gt;를 도구 중립적인 공용 규칙의 단일 원본으로 두는 것이다. 루트 &lt;code&gt;CLAUDE.md&lt;/code&gt;에서는 이를 가져오고 Claude에만 필요한 내용만 추가한다.&lt;/p&gt;

  &lt;pre&gt;&lt;code&gt;project/
├── AGENTS.md                 # 공용 프로젝트 운영 규칙
├── CLAUDE.md                 # @AGENTS.md + Claude 전용 규칙
├── apps/
│   └── web/
│       ├── AGENTS.md         # 웹 앱 전용 공용 규칙
│       └── CLAUDE.md         # 같은 폴더의 @AGENTS.md 가져오기
└── .claude/
    └── rules/                # Claude용 경로별 세부 규칙&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;루트의 &lt;code&gt;CLAUDE.md&lt;/code&gt;는 다음처럼 짧게 유지할 수 있다.&lt;/p&gt;

  &lt;pre&gt;&lt;code&gt;# Shared project instructions
@AGENTS.md

## Claude Code only
- src/billing/ 아래에서 3개 이상의 파일을 바꾸기 전에는
  먼저 계획과 위험 요소를 보여준다.
- 긴 반복 절차는 이 파일에 복사하지 말고 관련 skill을 사용한다.&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;모노레포에서는 한 단계가 더 필요하다. 루트 &lt;code&gt;CLAUDE.md&lt;/code&gt;가 루트 &lt;code&gt;AGENTS.md&lt;/code&gt;를 가져온다고 해서 Claude Code가 &lt;code&gt;apps/web/AGENTS.md&lt;/code&gt;까지 자동으로 찾는 것은 아니다. Claude가 자동 발견하는 하위 파일은 &lt;code&gt;CLAUDE.md&lt;/code&gt;이기 때문이다. 따라서 각 하위 프로젝트에 얇은 &lt;code&gt;CLAUDE.md&lt;/code&gt;를 두고 같은 폴더의 &lt;code&gt;@AGENTS.md&lt;/code&gt;를 가져오거나, &lt;code&gt;.claude/rules/&lt;/code&gt;의 경로별 규칙으로 연결해야 한다.&lt;/p&gt;

  &lt;p&gt;심볼릭 링크로 &lt;code&gt;CLAUDE.md&lt;/code&gt;를 &lt;code&gt;AGENTS.md&lt;/code&gt;에 연결하는 방법도 있지만, Claude 전용 내용을 추가하기 어렵고 Windows에서는 관리자 권한이나 Developer Mode가 필요할 수 있다. 수정하기 쉽고 의도가 보이는 &lt;code&gt;@AGENTS.md&lt;/code&gt; 방식이 대체로 관리하기 편하다.&lt;/p&gt;

  &lt;h2&gt;5. 좋은 지침은 ‘조건 + 행동 + 검증 + 예외 보고’로 쓴다&lt;/h2&gt;

  &lt;p&gt;“깔끔하게 작성한다”, “테스트를 철저히 한다”는 문장은 좋은 의도만 있을 뿐 완료 여부를 확인할 수 없다. AI가 안정적으로 따르기 쉬운 지침은 적용 조건, 구체적인 행동, 정확한 명령, 완료 기준이 함께 있다.&lt;/p&gt;

  &lt;div class=&quot;hb-card-grid&quot;&gt;
    &lt;div class=&quot;hb-card&quot;&gt;
      &lt;h3&gt;모호한 지침&lt;/h3&gt;
      &lt;p&gt;테스트를 철저히 한다.&lt;br&gt;코드를 깔끔하게 작성한다.&lt;br&gt;보안에 주의한다.&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class=&quot;hb-card&quot;&gt;
      &lt;h3&gt;검증 가능한 지침&lt;/h3&gt;
      &lt;p&gt;웹 컴포넌트를 수정하면 지정한 lint와 test를 실행한다. 실행하지 못하면 이유와 미검증 범위를 최종 보고에 적는다.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;pre&gt;&lt;code&gt;## Web application changes

- apps/web/**/*.tsx를 수정하면 완료 전에
  pnpm --filter web lint
  pnpm --filter web test
  를 실행한다.

- generated/ 아래 파일은 직접 수정하지 않는다.
  소스를 바꾼 뒤 pnpm generate로 재생성한다.

- 검사를 실행할 수 없으면 성공했다고 표현하지 않는다.
  이유와 미검증 범위를 최종 보고에 적는다.

- 새 운영 의존성을 추가하기 전에는
  기존 패키지로 해결할 수 없는 이유와 대안을 먼저 제시한다.&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;지침 파일에 넣기 좋은 내용은 다음과 같다.&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;정확한 빌드·테스트 명령:&lt;/strong&gt; 패키지 관리자, 워크스페이스 필터, 필요한 환경 조건&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;아키텍처 경계:&lt;/strong&gt; 직접 수정하면 안 되는 생성 파일, 계층 간 의존 규칙, 소스 오브 트루스&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;코드 규칙:&lt;/strong&gt; 추상적인 “클린 코드”가 아니라 이 저장소만의 구체적 관례&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;검증 기준:&lt;/strong&gt; 무엇을 실행하고 어떤 결과를 보고해야 완료인지&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;안전 규칙:&lt;/strong&gt; 삭제, 배포, 외부 메시지, 운영 데이터 변경 전에 확인이 필요한 조건&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h2&gt;6. 지침 파일에 넣지 말아야 할 것&lt;/h2&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;정보 유형별 권장 위치&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;정보&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;권장 위치&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;이유&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;항상 적용할 빌드·코드·검증 규칙&lt;/td&gt;
          &lt;td&gt;AGENTS.md 또는 CLAUDE.md&lt;/td&gt;
          &lt;td&gt;매 작업에 필요한 지속 컨텍스트다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;특정 상황의 긴 다단계 절차&lt;/td&gt;
          &lt;td&gt;Skill, runbook, 별도 문서&lt;/td&gt;
          &lt;td&gt;항상 로드하면 컨텍스트만 차지하고 핵심 지침의 준수도가 떨어진다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;반드시 막아야 하는 명령·경로&lt;/td&gt;
          &lt;td&gt;Permissions, hooks, sandbox&lt;/td&gt;
          &lt;td&gt;Markdown 지침은 행동을 유도하지만 기술적으로 차단하지는 않는다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;반드시 통과해야 하는 품질 기준&lt;/td&gt;
          &lt;td&gt;CI, lint, test, branch protection&lt;/td&gt;
          &lt;td&gt;실행 결과로 강제하고 기록할 수 있다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;API 키, 비밀번호, 개인 정보&lt;/td&gt;
          &lt;td&gt;Secret manager, 환경 변수&lt;/td&gt;
          &lt;td&gt;지침 파일은 저장소에 커밋될 수 있으므로 비밀 저장소가 아니다.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;p&gt;코드에서 바로 알 수 있는 전체 디렉터리 목록이나 패키지 설명을 길게 복사하는 것도 피하는 편이 좋다. Anthropic은 &lt;a href=&quot;https://code.claude.com/docs/en/memory#write-effective-instructions&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt;를 파일당 200줄 미만&lt;/a&gt;으로 유지하도록 권장한다. Codex도 프로젝트 지침의 합산 크기에 기본 제한이 있다. 길이가 품질을 보장하는 것이 아니라, 자주 필요한데 코드만 보고는 알기 어려운 규칙을 얼마나 선명하게 남겼는지가 중요하다.&lt;/p&gt;

  &lt;h2&gt;7. 이 티스토리 프로젝트에 적용한 방식&lt;/h2&gt;

  &lt;p&gt;실제로 이 블로그 프로젝트도 루트 &lt;code&gt;AGENTS.md&lt;/code&gt;에는 모든 글에 공통으로 적용되는 원칙만 두고, 주제별 규칙은 하위 폴더에 나눠 두고 있다.&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;&lt;code&gt;posts/coding-test/AGENTS.md&lt;/code&gt;에는 기본 풀이 언어, 글의 고정 순서, 요청하지 않은 언어를 추가하지 않는 금지사항, 발행 전 검색 항목이 있다.&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;posts/buying-guide/AGENTS.md&lt;/code&gt;에는 가격 기준일, 공식 근거와 작성자 판단의 분리, 과장 표현 금지, 표·외부 링크·출처 검수 기준이 있다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;p&gt;이렇게 나누면 구매 가이드의 가격·재고 검증 규칙이 코딩테스트 풀이에 끼어들지 않고, 코딩테스트의 Python 전용 규칙이 일반 AI 글에 적용되지 않는다. 동시에 반복되는 출력 구조와 금지사항을 매 프롬프트마다 다시 설명할 필요가 줄어든다. 이번 글 역시 “공통 규칙은 루트, 주제 규칙은 하위 폴더”라는 구조를 실제 사례로 삼아 작성했다.&lt;/p&gt;

  &lt;h2&gt;8. 만들고 끝내지 말고 실제 로딩을 검증한다&lt;/h2&gt;

  &lt;p&gt;지침 파일의 가장 흔한 실패는 내용이 나쁜 것이 아니라 아예 로드되지 않은 경우다. 파일을 추가하거나 위치를 바꾼 뒤에는 도구가 무엇을 읽었는지 확인해야 한다.&lt;/p&gt;

  &lt;div class=&quot;hb-checklist&quot;&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Codex:&lt;/strong&gt; 대상 디렉터리에서 새 세션을 시작하고 활성 지침의 출처와 내용을 요약하게 한다. 하위 프로젝트는 그 디렉터리에서 별도로 확인한다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Claude Code:&lt;/strong&gt; &lt;code&gt;/memory&lt;/code&gt;로 현재 로드된 CLAUDE.md, CLAUDE.local.md, rules 파일을 확인한다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;충돌 검사:&lt;/strong&gt; 루트와 하위 파일이 같은 항목에 반대되는 지시를 하지 않는지 검색한다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;실행 검사:&lt;/strong&gt; 단순히 “규칙을 이해했니?”라고 묻는 데서 끝내지 말고 작은 수정 후 실제 lint·test·보고 형식을 확인한다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;세션 갱신:&lt;/strong&gt; Codex 지침을 수정했다면 새 실행에서 체인이 다시 구성되는지 확인한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;

  &lt;h2&gt;9. 시작할 때 필요한 최소 템플릿&lt;/h2&gt;

  &lt;p&gt;처음부터 완벽한 운영 매뉴얼을 만들 필요는 없다. 매번 반복하는 지시 세 개, AI가 두 번 이상 틀린 관례, 작업 완료 전에 꼭 확인해야 할 명령부터 적으면 된다.&lt;/p&gt;

  &lt;pre&gt;&lt;code&gt;# Project instructions

## Scope
- 이 파일은 저장소 전체에 적용한다.
- 더 가까운 폴더의 지침이 있으면 그 영역의 세부 규칙을 함께 따른다.

## Before editing
- 변경 대상과 관련된 기존 구현, 테스트, 문서를 먼저 확인한다.
- 새 운영 의존성을 추가하기 전에는 대안과 영향 범위를 설명한다.

## Implementation
- generated/ 아래 파일은 직접 수정하지 않는다.
- 기존 공개 API를 바꾸면 마이그레이션 영향을 함께 기록한다.

## Verification
- 코드 변경 후 프로젝트의 lint와 test 명령을 실행한다.
- 실행하지 못한 검사는 이유와 미검증 범위를 최종 보고에 적는다.

## Safety
- 삭제, 배포, 운영 데이터 변경은 실행 전에 확인을 받는다.
- 비밀값을 코드, 로그, 지침 파일에 기록하지 않는다.&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;이 템플릿을 그대로 오래 유지하기보다 실제 실패를 관찰하며 다듬는 것이 중요하다. 에이전트가 같은 실수를 반복하면 더 구체적인 조건과 명령으로 바꾸고, 더 이상 필요 없는 규칙은 삭제한다. 지침 파일도 코드처럼 리뷰하고 버전 관리해야 한다.&lt;/p&gt;

  &lt;h2&gt;10. 최종 정리&lt;/h2&gt;

  &lt;p&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;와 &lt;code&gt;CLAUDE.md&lt;/code&gt; 중 하나가 무조건 더 좋은 것은 아니다. 핵심은 사용하는 도구가 실제로 읽는 파일을 선택하고, 공통 규칙과 도구 전용 규칙의 경계를 명확히 하는 것이다.&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;여러 에이전트가 공유할 규칙은 &lt;code&gt;AGENTS.md&lt;/code&gt;에 둔다.&lt;/li&gt;
    &lt;li&gt;Claude Code에서는 &lt;code&gt;CLAUDE.md&lt;/code&gt;가 &lt;code&gt;@AGENTS.md&lt;/code&gt;를 가져오게 하고 Claude 전용 내용만 추가한다.&lt;/li&gt;
    &lt;li&gt;하위 프로젝트에는 그 범위에 필요한 지침만 두고, 각 도구의 실제 탐색 방식을 확인한다.&lt;/li&gt;
    &lt;li&gt;지침은 짧고 구체적이며 검증 가능하게 쓴다.&lt;/li&gt;
    &lt;li&gt;품질 기준은 CI와 branch protection으로, 위험 동작은 permissions·sandbox·차단 훅·승인 절차로 강제한다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;blockquote class=&quot;hb-pull&quot;&gt;대화창에서 반복하는 지시가 세 개를 넘었다면, 더 긴 프롬프트를 쓰기 전에 저장소에 에이전트용 운영설명서를 만들 때다.&lt;/blockquote&gt;

  &lt;div class=&quot;hb-references&quot;&gt;
    &lt;h2&gt;참고 자료&lt;/h2&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://resource.lonelyoctopus.com/doc/e3953a01-ae1b-4a16-b0c7-5ac520d14660/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;My Full Claude Cowork Setup: How to Build Your Personal AI System From Scratch&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://learn.chatgpt.com/docs/agent-configuration/agents-md&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenAI Codex: Custom instructions with AGENTS.md&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://code.claude.com/docs/en/memory&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Anthropic Claude Code: How Claude remembers your project&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://agents.md/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;AGENTS.md: An open format for guiding coding agents&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://openai.com/index/agentic-ai-foundation/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OpenAI: The Agentic AI Foundation&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;

  &lt;p class=&quot;hb-disclaimer&quot;&gt;이 글은 2026년 7월 15일 기준 공식 문서를 바탕으로 정리했습니다. AI 도구의 지침 탐색 방식과 지원 파일은 버전에 따라 바뀔 수 있으므로 실제 적용 전 최신 공식 문서를 다시 확인하세요.&lt;/p&gt;
&lt;/article&gt;</description>
      <category>AI</category>
      <category>AGENTS.md</category>
      <category>AI 에이전트</category>
      <category>AI 코딩</category>
      <category>claude code</category>
      <category>CLAUDE.md</category>
      <category>openai codex</category>
      <category>개발 생산성</category>
      <category>프롬프트 엔지니어링</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/113</guid>
      <comments>https://onethingflow.tistory.com/entry/AI-%EC%BD%94%EB%94%A9-%EC%97%90%EC%9D%B4%EC%A0%84%ED%8A%B8%EC%97%90%EA%B2%8C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EA%B7%9C%EC%B9%99%EC%9D%84-%EA%B8%B0%EC%96%B5%EC%8B%9C%ED%82%A4%EB%8A%94-%EB%B2%95AGENTSmd%EC%99%80-CLAUDEmd#entry113comment</comments>
      <pubDate>Wed, 15 Jul 2026 14:14:35 +0900</pubDate>
    </item>
    <item>
      <title>정처기 3일차 수제비: 명령문&amp;middot;사용자 정의 함수&amp;middot;구조체&amp;middot;클래스 총정리</title>
      <link>https://onethingflow.tistory.com/entry/%EC%A0%95%EC%B2%98%EA%B8%B0-3%EC%9D%BC%EC%B0%A8-%EC%88%98%EC%A0%9C%EB%B9%84-%EB%AA%85%EB%A0%B9%EB%AC%B8%C2%B7%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%A0%95%EC%9D%98-%ED%95%A8%EC%88%98%C2%B7%EA%B5%AC%EC%A1%B0%EC%B2%B4%C2%B7%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%B4%9D%EC%A0%95%EB%A6%AC</link>
      <description>&lt;!--
티스토리 제목 추천:
정처기 3일차 수제비: 명령문·사용자 정의 함수·구조체·클래스 총정리

메타 설명 추천:
정보처리기사 필기 3일차 수제비 범위(p.4-38~p.4-55)의 명령문, 사용자 정의 함수, C 구조체와 포인터, 클래스·객체·생성자를 초보자용 예제와 시험 포인트로 정리했습니다.

태그 추천:
정보처리기사, 정처기, 수제비, C언어, 명령문, 조건문, 반복문, 사용자정의함수, 구조체, 구조체포인터, 클래스, 객체지향, 생성자, 자바, 파이썬
--&gt;

&lt;article style=&quot;max-width:780px;margin:0 auto;line-height:1.86;font-size:17px;color:#222;word-break:keep-all;&quot;&gt;
  &lt;section style=&quot;margin:0 0 1.5em;padding:1.35em 1.4em;border:1px solid #dde6f2;border-radius:8px;background:linear-gradient(135deg,#f7fbff 0%,#fff 62%,#fff7ed 100%);&quot;&gt;
    &lt;p style=&quot;margin:0 0 .8em;display:inline-block;padding:.25em .7em;border:1px solid #d9e4f2;border-radius:999px;background:#fff;font-size:.84em;font-weight:700;color:#385174;&quot;&gt;정보처리기사 필기 공부 기록 · 3일차 · p.4-38~p.4-55&lt;/p&gt;
    &lt;h1 style=&quot;margin:.1em 0 .72em;font-size:2em;line-height:1.28;font-weight:800;color:#111;&quot;&gt;정처기 3일차 수제비: 명령문·함수·구조체·클래스 총정리&lt;/h1&gt;
    &lt;p style=&quot;margin:0 0 1em;font-size:1.08em;color:#343b46;&quot;&gt;3일차 범위는 &lt;strong&gt;명령문, 사용자 정의 함수, 구조체, 클래스&lt;/strong&gt;입니다. 조건과 반복으로 실행 흐름을 만들고, 반복되는 로직은 함수로 묶으며, 관련 데이터는 구조체로, 상태와 동작은 클래스로 설계하는 순서로 이어집니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;시험에서는 반복문의 실행 결과, &lt;code&gt;break&lt;/code&gt;와 &lt;code&gt;continue&lt;/code&gt;, 함수의 값 전달, &lt;code&gt;s1.age&lt;/code&gt;와 &lt;code&gt;p-&amp;gt;age&lt;/code&gt;, 생성자 문법이 자주 헷갈립니다. 이 글에서는 코드가 실행되는 순서를 초보자 눈높이에서 하나씩 따라가 보겠습니다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;div style=&quot;display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:.85em;margin:1.35em 0;&quot;&gt;
    &lt;div style=&quot;border:1px solid #e3e8ef;border-radius:8px;background:#fff;padding:1em;&quot;&gt;
      &lt;span style=&quot;display:block;font-size:.82em;color:#687182;margin-bottom:.25em;&quot;&gt;핵심 1&lt;/span&gt;
      &lt;strong style=&quot;display:block;font-size:1.04em;color:#101418;line-height:1.36;&quot;&gt;명령문은 실행 흐름을 결정한다&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div style=&quot;border:1px solid #e3e8ef;border-radius:8px;background:#fff;padding:1em;&quot;&gt;
      &lt;span style=&quot;display:block;font-size:.82em;color:#687182;margin-bottom:.25em;&quot;&gt;핵심 2&lt;/span&gt;
      &lt;strong style=&quot;display:block;font-size:1.04em;color:#101418;line-height:1.36;&quot;&gt;함수는 반복 로직을 이름으로 묶는다&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div style=&quot;border:1px solid #e3e8ef;border-radius:8px;background:#fff;padding:1em;&quot;&gt;
      &lt;span style=&quot;display:block;font-size:.82em;color:#687182;margin-bottom:.25em;&quot;&gt;핵심 3&lt;/span&gt;
      &lt;strong style=&quot;display:block;font-size:1.04em;color:#101418;line-height:1.36;&quot;&gt;&lt;code&gt;.&lt;/code&gt;은 변수, &lt;code&gt;-&amp;gt;&lt;/code&gt;는 포인터&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div style=&quot;border:1px solid #e3e8ef;border-radius:8px;background:#fff;padding:1em;&quot;&gt;
      &lt;span style=&quot;display:block;font-size:.82em;color:#687182;margin-bottom:.25em;&quot;&gt;핵심 4&lt;/span&gt;
      &lt;strong style=&quot;display:block;font-size:1.04em;color:#101418;line-height:1.36;&quot;&gt;클래스는 상태와 동작의 설계도&lt;/strong&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;blockquote style=&quot;margin:1.55em 0;padding:.95em 1.15em;background:#fff9e8;border-left:4px solid #f2b705;border-radius:8px;font-size:1.06em;font-weight:800;color:#584500;&quot;&gt;
    오늘의 한 줄 지도: 명령문은 흐름, 함수는 재사용, 구조체는 데이터 묶음, 클래스는 상태와 동작의 설계도다.
  &lt;/blockquote&gt;

  &lt;section style=&quot;margin:1.6em 0;padding:1em 1.1em;border:1px solid #e2e8f0;border-radius:8px;background:#fbfdff;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 .65em;font-size:1.18em;line-height:1.45;font-weight:800;color:#111;&quot;&gt;3일차 학습 순서&lt;/h2&gt;
    &lt;ol style=&quot;margin:0 0 0 1.15em;padding:0;&quot;&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;조건문·반복문과 흐름 제어&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;사용자 정의 함수·값 전달·재귀 함수&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;배열과 구조체의 차이&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;구조체 선언과 구조체 포인터&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;클래스·객체·인스턴스의 관계&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;Java와 Python의 클래스 및 생성자&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;&lt;code&gt;this&lt;/code&gt;와 &lt;code&gt;self&lt;/code&gt; 비교&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;절차지향과 객체지향 비교&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/section&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;1. 명령문: 프로그램의 실행 흐름 만들기&lt;/h2&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;명령문은 컴퓨터에 “무엇을 실행하라”고 지시하는 문장입니다. 프로그램은 기본적으로 위에서 아래로 실행되지만, 조건문을 만나면 실행할 길을 선택하고 반복문을 만나면 같은 작업을 여러 번 수행합니다.&lt;/p&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;-webkit-overflow-scrolling:touch;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:650px;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;명령문의 종류와 역할&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;종류&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;대표 문법&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;역할&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;순차문&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;대입문·함수 호출문&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;작성된 순서대로 실행&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfd;&quot;&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;선택문&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;if&lt;/code&gt;, &lt;code&gt;if-else&lt;/code&gt;, &lt;code&gt;switch&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;조건에 따라 실행할 문장을 선택&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;반복문&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;for&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt;, &lt;code&gt;do-while&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;조건을 만족하는 동안 같은 작업을 반복&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfd;&quot;&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;흐름 제어문&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;break&lt;/code&gt;, &lt;code&gt;continue&lt;/code&gt;, &lt;code&gt;return&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;반복·선택·함수의 흐름을 중간에 변경&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;조건문: 조건이 참인지 판단하기&lt;/h3&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;int score = 85;

if (score &amp;gt;= 90) {
    printf(&quot;A&quot;);
} else if (score &amp;gt;= 80) {
    printf(&quot;B&quot;);
} else {
    printf(&quot;C&quot;);
}
// 출력: B&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;if&lt;/code&gt;의 조건이 거짓이면 다음 &lt;code&gt;else if&lt;/code&gt;를 검사합니다. 여러 조건이 참이더라도 위에서 처음 만난 참인 블록 하나만 실행합니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;&lt;code&gt;switch&lt;/code&gt;와 &lt;code&gt;break&lt;/code&gt; 함정&lt;/h3&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;int n = 2;

switch (n) {
    case 1: printf(&quot;A&quot;); break;
    case 2: printf(&quot;B&quot;);
    case 3: printf(&quot;C&quot;); break;
    default: printf(&quot;D&quot;);
}
// 출력: BC&lt;/code&gt;&lt;/pre&gt;

  &lt;div style=&quot;margin:1.35em 0;padding:1em 1.1em;border:1px solid #f4dfb7;border-left:4px solid #e5a800;border-radius:8px;background:#fffaf0;&quot;&gt;
    &lt;strong style=&quot;display:block;margin:0 0 .45em;color:#6a5000;&quot;&gt;왜 B만 출력되지 않을까?&lt;/strong&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;code&gt;case 2&lt;/code&gt; 뒤에 &lt;code&gt;break&lt;/code&gt;가 없기 때문에 다음 &lt;code&gt;case 3&lt;/code&gt;의 문장까지 이어서 실행합니다. 이를 폴스루(fall-through)라고 합니다. 시험에서는 각 &lt;code&gt;case&lt;/code&gt;의 끝에 &lt;code&gt;break&lt;/code&gt;가 있는지 먼저 표시해 두면 실수를 줄일 수 있습니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;반복문 세 가지 비교&lt;/h3&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;-webkit-overflow-scrolling:touch;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:650px;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;for while do-while 반복문 비교&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;반복문&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;조건 검사&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;핵심 특징&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;&lt;code&gt;for&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;실행 전&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;반복 횟수가 비교적 분명할 때 편리&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfd;&quot;&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;&lt;code&gt;while&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;실행 전&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;처음부터 조건이 거짓이면 한 번도 실행하지 않음&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;&lt;code&gt;do-while&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;실행 후&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;조건이 거짓이어도 본문을 최소 한 번 실행&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;int sum = 0;

for (int i = 1; i &amp;lt;= 5; i++) {
    if (i == 3) continue;
    if (i == 5) break;
    sum += i;
}

printf(&quot;%d&quot;, sum);  // 1 + 2 + 4 = 7&lt;/code&gt;&lt;/pre&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;-webkit-overflow-scrolling:touch;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:650px;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;break continue return 차이&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;문장&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;무엇을 끝내거나 건너뛰나?&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;&lt;code&gt;break&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;가장 가까운 반복문 또는 &lt;code&gt;switch&lt;/code&gt;를 즉시 종료&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfd;&quot;&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;&lt;code&gt;continue&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;현재 반복의 남은 문장만 건너뛰고 다음 반복으로 이동&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;&lt;code&gt;return&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;현재 함수 자체를 끝내고 호출한 곳으로 복귀&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;div style=&quot;margin:1.35em 0;padding:1em 1.1em;border:1px solid #dbe5f5;border-left:4px solid #3f75ff;border-radius:8px;background:#f8fbff;&quot;&gt;
    &lt;strong style=&quot;display:block;margin:0 0 .45em;color:#172033;&quot;&gt;Python &lt;code&gt;range()&lt;/code&gt;의 끝값은 포함하지 않는다&lt;/strong&gt;
    &lt;p style=&quot;margin:0 0 .75em;&quot;&gt;&lt;code&gt;range(1, 5)&lt;/code&gt;는 1부터 4까지 만듭니다. 시험에서 반복 횟수를 셀 때 마지막 값 5를 포함하지 않는다는 점을 기억하세요.&lt;/p&gt;
    &lt;pre style=&quot;margin:0;padding:.9em 1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.9em;line-height:1.65;&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;for i in range(1, 5):
    print(i, end=&quot; &quot;)
# 출력: 1 2 3 4&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;C에는 지정한 레이블로 바로 이동하는 &lt;code&gt;goto&lt;/code&gt;문도 있습니다. 문법 문제에서는 알아두되, 실행 흐름을 따라가기 어려워질 수 있으므로 일반적인 코드에서는 신중하게 사용합니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;2. 사용자 정의 함수: 반복 작업에 이름 붙이기&lt;/h2&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;함수는 특정 작업을 수행하는 코드 묶음입니다. &lt;code&gt;printf()&lt;/code&gt;처럼 언어와 라이브러리가 제공하는 함수도 있지만, 필요한 기능을 직접 만든 것을 &lt;strong&gt;사용자 정의 함수&lt;/strong&gt;라고 합니다. 함수를 사용하면 같은 코드를 반복해서 쓰지 않아도 되고, 프로그램을 작은 역할 단위로 나눌 수 있습니다.&lt;/p&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;-webkit-overflow-scrolling:touch;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:650px;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;C 함수의 구성 요소&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;구성 요소&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;예시&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;의미&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;반환형&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;int&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;함수가 돌려주는 값의 자료형&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfd;&quot;&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;함수명&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;add&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;함수를 호출할 때 사용하는 이름&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;매개변수&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;int a, int b&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;호출할 때 전달된 값을 받는 변수&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfd;&quot;&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;함수 본문&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;{ return a + b; }&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;실제로 수행할 문장과 반환값&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;함수 원형 선언 → 호출 → 정의&lt;/h3&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;#include &amp;lt;stdio.h&amp;gt;

int add(int a, int b);  // 1. 함수 원형 선언

int main(void) {
    int result = add(3, 5);  // 2. 함수 호출
    printf(&quot;%d\n&quot;, result); // 출력: 8
    return 0;
}

int add(int a, int b) {     // 3. 함수 정의
    return a + b;
}&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;함수 원형은 컴파일러에게 “이런 이름과 형태의 함수가 뒤에 나온다”고 미리 알려 줍니다. 함수를 &lt;code&gt;main()&lt;/code&gt;보다 앞에서 정의했다면 별도의 원형 선언을 생략할 수 있습니다.&lt;/p&gt;

  &lt;div style=&quot;margin:1.35em 0;padding:1em 1.1em;border:1px solid #dbe5f5;border-left:4px solid #3f75ff;border-radius:8px;background:#f8fbff;&quot;&gt;
    &lt;strong style=&quot;display:block;margin:0 0 .45em;color:#172033;&quot;&gt;인수와 매개변수는 위치가 다르다&lt;/strong&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;code&gt;add(3, 5)&lt;/code&gt;의 3과 5는 호출하는 쪽에서 보내는 &lt;strong&gt;인수&lt;/strong&gt;이고, &lt;code&gt;int add(int a, int b)&lt;/code&gt;의 &lt;code&gt;a&lt;/code&gt;와 &lt;code&gt;b&lt;/code&gt;는 함수가 값을 받는 &lt;strong&gt;매개변수&lt;/strong&gt;입니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;매개변수와 반환값의 네 가지 형태&lt;/h3&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;-webkit-overflow-scrolling:touch;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:650px;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;매개변수와 반환값에 따른 함수 형태&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;매개변수&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;반환값&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;C 함수 예시&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;없음&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;없음&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;void show(void)&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfd;&quot;&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;있음&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;없음&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;void print_sum(int a, int b)&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;없음&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;있음&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;int get_number(void)&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfd;&quot;&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;있음&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;있음&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;int add(int a, int b)&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;C의 값 전달과 포인터 전달&lt;/h3&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;#include &amp;lt;stdio.h&amp;gt;

void change_value(int n) {
    n = 99;
}

void change_address(int *n) {
    *n = 99;
}

int main(void) {
    int a = 10;
    int b = 10;

    change_value(a);
    change_address(&amp;amp;b);

    printf(&quot;%d %d\n&quot;, a, b);  // 10 99
    return 0;
}&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;change_value(a)&lt;/code&gt;는 &lt;code&gt;a&lt;/code&gt;의 값 10을 복사해서 보내므로 함수 안에서 &lt;code&gt;n&lt;/code&gt;을 바꿔도 원본 &lt;code&gt;a&lt;/code&gt;는 그대로입니다. 반면 &lt;code&gt;change_address(&amp;amp;b)&lt;/code&gt;는 &lt;code&gt;b&lt;/code&gt;의 주소를 보내고 &lt;code&gt;*n&lt;/code&gt;으로 그 주소의 값을 바꾸므로 원본 &lt;code&gt;b&lt;/code&gt;가 99가 됩니다.&lt;/p&gt;

  &lt;div style=&quot;margin:1.35em 0;padding:1em 1.1em;border:1px solid #f1d7d7;border-left:4px solid #e76f51;border-radius:8px;background:#fffafa;&quot;&gt;
    &lt;strong style=&quot;display:block;margin:0 0 .45em;color:#6b1d1d;&quot;&gt;정확히 말하면 C는 항상 값을 전달한다&lt;/strong&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;포인터를 매개변수로 넘길 때도 함수가 받는 것은 주소값의 복사본입니다. 다만 그 주소를 역참조하면 호출한 쪽의 실제 데이터에 접근할 수 있어, 교재에서는 이를 주소에 의한 호출 또는 참조 효과라고 설명하기도 합니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;재귀 함수는 종료 조건부터 확인하기&lt;/h3&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;재귀 함수는 자기 자신을 다시 호출하는 함수입니다. 반복문처럼 문제를 되풀이해 해결하지만, 호출을 멈추는 종료 조건이 반드시 필요합니다.&lt;/p&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;int factorial(int n) {
    if (n &amp;lt;= 1) return 1;       // 종료 조건
    return n * factorial(n - 1); // 자기 자신 호출
}

// factorial(4)
// = 4 * 3 * 2 * 1
// = 24&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;종료 조건이 없거나 종료 조건에 도달하지 못하면 호출이 계속 쌓여 스택 공간을 소진할 수 있습니다. 재귀 코드 문제에서는 &lt;strong&gt;종료 조건 → 호출 시 전달값 → 되돌아오며 계산되는 값&lt;/strong&gt; 순서로 추적하세요.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;Python의 사용자 정의 함수&lt;/h3&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;def add(a, b):
    return a + b


result = add(3, 5)
print(result)  # 8&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;Python은 &lt;code&gt;def&lt;/code&gt;로 함수를 정의합니다. C처럼 반환형을 함수 이름 앞에 적지 않으며, 들여쓰기로 함수 본문의 범위를 구분합니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;3. 구조체란 무엇일까?&lt;/h2&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;구조체(&lt;code&gt;struct&lt;/code&gt;)는 &lt;strong&gt;서로 관련된 여러 데이터를 하나의 단위로 묶는 사용자 정의 자료형&lt;/strong&gt;입니다. 학생 한 명을 저장한다고 생각해 보겠습니다. 학생에게는 이름, 나이, 시력처럼 자료형이 서로 다른 정보가 필요합니다. 이 값들을 따로 관리하는 대신 &lt;code&gt;Student&lt;/code&gt;라는 하나의 구조로 묶는 것입니다.&lt;/p&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;-webkit-overflow-scrolling:touch;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:590px;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;배열과 구조체의 차이&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;구분&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;배열&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;구조체&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;담을 수 있는 자료형&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;같은 자료형의 원소&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;서로 다른 자료형의 멤버&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfd;&quot;&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;접근 방법&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;arr[0]&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;student.age&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;예시&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;시험 점수 5개&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;학생의 이름·나이·시력&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;구조체 설계도 만들기&lt;/h3&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;struct Student {
    char name[20];
    int age;
    double vision;
};&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;이 코드는 아직 학생 한 명을 만든 것이 아닙니다. &lt;code&gt;Student&lt;/code&gt;라는 구조체가 이름, 나이, 시력을 어떤 형태로 저장할지 &lt;strong&gt;자료형의 설계도&lt;/strong&gt;를 만든 것입니다. 실제 값을 저장하려면 구조체 변수를 따로 선언해야 합니다.&lt;/p&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;struct Student s1;

s1.age = 25;
s1.vision = 1.2;&lt;/code&gt;&lt;/pre&gt;

  &lt;div style=&quot;margin:1.35em 0;padding:1em 1.1em;border:1px solid #dbe5f5;border-left:4px solid #3f75ff;border-radius:8px;background:#f8fbff;&quot;&gt;
    &lt;strong style=&quot;display:block;margin:0 0 .45em;color:#172033;&quot;&gt;왜 &lt;code&gt;struct Student s1;&lt;/code&gt;이라고 쓸까?&lt;/strong&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;위 예제는 &lt;code&gt;typedef&lt;/code&gt;를 사용하지 않았기 때문에 C에서는 구조체 태그 앞에 &lt;code&gt;struct&lt;/code&gt;를 붙여야 합니다. &lt;code&gt;typedef&lt;/code&gt;로 별칭을 만들면 더 짧게 쓸 수 있지만, 처음에는 기본 형태부터 익히는 편이 좋습니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;점 연산자로 멤버에 접근하기&lt;/h3&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;구조체 변수 안의 멤버를 읽거나 바꿀 때는 점(&lt;code&gt;.&lt;/code&gt;) 연산자를 사용합니다. &lt;code&gt;s1.age&lt;/code&gt;는 “&lt;code&gt;s1&lt;/code&gt;이라는 학생 구조체 안의 &lt;code&gt;age&lt;/code&gt; 멤버”라는 뜻입니다.&lt;/p&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

struct Student {
    char name[20];
    int age;
    double vision;
};

int main(void) {
    struct Student s1;

    strcpy(s1.name, &quot;민수&quot;);
    s1.age = 25;
    s1.vision = 1.2;

    printf(&quot;%s, %d세, 시력 %.1f\n&quot;, s1.name, s1.age, s1.vision);
    return 0;
}&lt;/code&gt;&lt;/pre&gt;

  &lt;div style=&quot;margin:1.35em 0;padding:1em 1.1em;border:1px solid #f1d7d7;border-left:4px solid #e76f51;border-radius:8px;background:#fffafa;&quot;&gt;
    &lt;strong style=&quot;display:block;margin:0 0 .45em;color:#6b1d1d;&quot;&gt;초보자 함정: 문자 배열은 &lt;code&gt;=&lt;/code&gt;로 다시 대입할 수 없다&lt;/strong&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;code&gt;s1.name&lt;/code&gt;은 문자 배열이므로 선언이 끝난 뒤 &lt;code&gt;s1.name = &quot;민수&quot;;&lt;/code&gt;처럼 대입하면 안 됩니다. 위 예제처럼 &lt;code&gt;strcpy()&lt;/code&gt;를 사용하거나, 구조체 변수를 만들 때 처음부터 초기화해야 합니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;4. 구조체와 포인터가 만나면?&lt;/h2&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;구조체 변수도 메모리에 저장되므로 주소를 가지고 있습니다. 이 주소를 포인터에 저장하면 포인터를 통해 구조체의 멤버를 읽고 바꿀 수 있습니다.&lt;/p&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;struct Student s1;
struct Student *p = &amp;amp;s1;

s1.age = 20;
p-&amp;gt;age = 25;&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;p&lt;/code&gt;에는 &lt;code&gt;s1&lt;/code&gt;의 주소가 들어 있습니다. 따라서 &lt;code&gt;p-&amp;gt;age = 25;&lt;/code&gt;는 “&lt;code&gt;p&lt;/code&gt;가 가리키는 구조체로 찾아가서 &lt;code&gt;age&lt;/code&gt;를 25로 바꿔라”라는 뜻입니다. 실제로 바뀌는 것은 &lt;code&gt;s1.age&lt;/code&gt;입니다.&lt;/p&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;-webkit-overflow-scrolling:touch;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:610px;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;구조체 변수와 구조체 포인터의 멤버 접근 방법&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;대상&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;표현&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;읽는 방법&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;일반 구조체 변수&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;s1.age&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;s1&lt;/code&gt;의 &lt;code&gt;age&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfd;&quot;&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;구조체 포인터&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;p-&amp;gt;age&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;p&lt;/code&gt;가 가리키는 구조체의 &lt;code&gt;age&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;역참조 후 점 사용&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;(*p).age&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;p-&amp;gt;age&lt;/code&gt;와 같은 뜻&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;blockquote style=&quot;margin:1.55em 0;padding:.95em 1.15em;background:#eefbf7;border-left:4px solid #2a9d8f;border-radius:8px;font-size:1.06em;font-weight:800;color:#165c50;&quot;&gt;
    시험 핵심 등식: &lt;code&gt;p-&amp;gt;age == (*p).age&lt;/code&gt;
  &lt;/blockquote&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;왜 &lt;code&gt;(*p).age&lt;/code&gt;에는 괄호가 필요할까?&lt;/h3&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;점(&lt;code&gt;.&lt;/code&gt;) 연산자는 역참조(&lt;code&gt;*&lt;/code&gt;)보다 우선순위가 높습니다. 괄호 없이 &lt;code&gt;*p.age&lt;/code&gt;라고 쓰면 컴퓨터는 이를 &lt;code&gt;*(p.age)&lt;/code&gt;처럼 해석하려고 합니다. 하지만 &lt;code&gt;p&lt;/code&gt;는 구조체 값이 아니라 구조체를 가리키는 포인터이므로 &lt;code&gt;p.age&lt;/code&gt;부터 성립하지 않습니다.&lt;/p&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#fff5f5;color:#7f1d1d;border:1px solid #fecaca;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;*p.age      // 잘못된 표현: *(p.age)처럼 해석됨&lt;/code&gt;&lt;/pre&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;(*p).age    // 먼저 *p로 구조체를 얻고 age에 접근
p-&amp;gt;age      // 위 표현을 간단하게 쓴 화살표 연산자&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;실행 결과까지 확인하기&lt;/h3&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;#include &amp;lt;stdio.h&amp;gt;

struct Student {
    int age;
};

int main(void) {
    struct Student s1 = {20};
    struct Student *p = &amp;amp;s1;

    (*p).age = 25;
    printf(&quot;%d\n&quot;, s1.age);   // 25

    p-&amp;gt;age = 30;
    printf(&quot;%d\n&quot;, s1.age);   // 30

    return 0;
}&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;s1.age&lt;/code&gt;, &lt;code&gt;(*p).age&lt;/code&gt;, &lt;code&gt;p-&amp;gt;age&lt;/code&gt;는 표현만 다를 뿐 같은 메모리 공간을 가리킵니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;5. 클래스·객체·인스턴스는 어떻게 다를까?&lt;/h2&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;클래스는 객체지향 프로그래밍에서 객체를 만들기 위한 설계도입니다. 흔히 &lt;strong&gt;클래스는 붕어빵 틀&lt;/strong&gt;, &lt;strong&gt;객체는 그 틀로 만든 붕어빵&lt;/strong&gt;에 비유합니다.&lt;/p&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;-webkit-overflow-scrolling:touch;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:620px;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;클래스, 객체, 인스턴스의 차이&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;용어&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;의미&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;비유&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;클래스&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;객체의 속성과 동작을 정의한 설계도&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;붕어빵 틀&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfd;&quot;&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;객체&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;상태와 동작을 가지는 실제 소프트웨어 실체&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;만들어진 붕어빵&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;인스턴스&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;특정 클래스로부터 생성된 객체임을 강조하는 표현&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;Taiyaki&lt;/code&gt; 틀로 만든 팥 붕어빵&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;실무에서는 객체와 인스턴스를 비슷한 뜻으로 섞어 쓰기도 합니다. 시험에서는 “클래스는 설계도, 객체는 실체, 인스턴스는 특정 클래스에서 생성된 객체”라고 구분하면 안전합니다. 클래스를 바탕으로 실제 객체를 만드는 과정을 &lt;strong&gt;인스턴스화&lt;/strong&gt;라고 합니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;속성과 메서드&lt;/h3&gt;

  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;속성·필드&lt;/strong&gt;: 객체가 가진 상태나 특징. 예: 맛, 가격, 색상&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;메서드&lt;/strong&gt;: 객체가 수행하는 동작. 예: 굽기, 가격 출력하기&lt;/li&gt;
  &lt;/ul&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;-webkit-overflow-scrolling:touch;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:650px;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;C 구조체와 클래스의 입문 수준 비교&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;구분&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;C 구조체&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;Java·Python 클래스&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;주요 목적&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;관련된 데이터를 한 단위로 묶기&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;상태와 동작을 객체 단위로 설계하기&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfd;&quot;&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;구성 요소&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;필드 중심&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;필드·메서드·생성자 등&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;접근 통제&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;언어 차원의 클래스 접근 제어 없음&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;언어에 따라 접근 제어·캡슐화 지원&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;div style=&quot;margin:1.35em 0;padding:1em 1.1em;border:1px solid #e2e8f0;border-left:4px solid #7c5ce7;border-radius:8px;background:#faf9ff;&quot;&gt;
    &lt;strong style=&quot;display:block;margin:0 0 .45em;color:#3f2f83;&quot;&gt;표는 입문 수준의 비교다&lt;/strong&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;“C 구조체는 변수만 담고 클래스는 함수도 담는다”라고만 외우면 지나치게 단순합니다. C 구조체에도 함수 포인터를 넣을 수 있고, C++의 &lt;code&gt;struct&lt;/code&gt;는 메서드를 가질 수 있습니다. 여기서는 정보처리기사에서 자주 비교하는 &lt;strong&gt;C 구조체와 클래스 기반 객체지향&lt;/strong&gt;의 기본 차이에 초점을 맞췄습니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;6. Java와 Python으로 클래스 만들기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;Java 클래스&lt;/h3&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;class Taiyaki {
    String flavor;
    int price;

    Taiyaki(String flavor, int price) {
        this.flavor = flavor;
        this.price = price;
    }

    void bake() {
        System.out.println(flavor + &quot; 붕어빵을 굽습니다.&quot;);
    }

    public static void main(String[] args) {
        Taiyaki redBean = new Taiyaki(&quot;팥&quot;, 1500);
        redBean.bake();
    }
}&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;new Taiyaki(&quot;팥&quot;, 1500)&lt;/code&gt;은 &lt;code&gt;Taiyaki&lt;/code&gt; 클래스를 인스턴스화해 객체를 만들고, 생성자를 호출해 초기값을 넣습니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;Python 클래스&lt;/h3&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;class Taiyaki:
    def __init__(self, flavor, price):
        self.flavor = flavor
        self.price = price

    def bake(self):
        print(f&quot;{self.flavor} 붕어빵을 굽습니다.&quot;)


red_bean = Taiyaki(&quot;팥&quot;, 1500)
red_bean.bake()&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;Python에서는 클래스를 함수처럼 호출해 인스턴스를 만듭니다. &lt;code&gt;__init__()&lt;/code&gt;은 새 인스턴스가 준비된 뒤 초기 상태를 설정합니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;7. 생성자와 소멸자는 정확히 이해하기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;Java 생성자&lt;/h3&gt;

  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;클래스 이름과 같은 이름을 사용합니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;반환형을 적지 않습니다. &lt;code&gt;void&lt;/code&gt;도 적지 않습니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;new&lt;/code&gt;로 객체를 만드는 과정에서 호출되어 필드를 초기화합니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;매개변수의 개수나 자료형을 다르게 하여 여러 생성자를 만들 수 있습니다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#fff5f5;color:#7f1d1d;border:1px solid #fecaca;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;void Taiyaki() { }  // 생성자가 아니라 반환형이 void인 일반 메서드&lt;/code&gt;&lt;/pre&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;Taiyaki() { }       // 올바른 Java 생성자&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;Python의 &lt;code&gt;__init__()&lt;/code&gt;&lt;/h3&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;입문서나 시험에서는 &lt;code&gt;__init__()&lt;/code&gt;을 흔히 생성자라고 부릅니다. 엄밀히 말하면 &lt;code&gt;__new__()&lt;/code&gt;가 인스턴스를 만들고, &lt;code&gt;__init__()&lt;/code&gt;은 이미 만들어진 인스턴스를 초기화합니다. 초보 단계에서는 “객체를 만들 때 자동으로 호출되어 초기값을 설정하는 메서드”라고 이해하면 충분합니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;소멸·정리 관련 주의사항&lt;/h3&gt;

  &lt;div style=&quot;margin:1.35em 0;padding:1em 1.1em;border:1px solid #f1d7d7;border-left:4px solid #e76f51;border-radius:8px;background:#fffafa;&quot;&gt;
    &lt;strong style=&quot;display:block;margin:0 0 .45em;color:#6b1d1d;&quot;&gt;Java의 &lt;code&gt;finalize()&lt;/code&gt;를 소멸자로 외우지 말자&lt;/strong&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;Java에는 C++처럼 개발자가 직접 정의하는 소멸자가 없습니다. 사용하지 않는 객체의 메모리는 가비지 컬렉터가 회수합니다. &lt;code&gt;finalize()&lt;/code&gt;는 실행 시점과 순서를 보장할 수 없고 현재 Java에서 폐기 예정으로 표시되므로 자원 정리 방법으로 사용하면 안 됩니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;div style=&quot;margin:1.35em 0;padding:1em 1.1em;border:1px solid #f4dfb7;border-left:4px solid #e5a800;border-radius:8px;background:#fffaf0;&quot;&gt;
    &lt;strong style=&quot;display:block;margin:0 0 .45em;color:#6a5000;&quot;&gt;Python의 &lt;code&gt;__del__()&lt;/code&gt;도 호출 시점이 보장되지 않는다&lt;/strong&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;시험에서 Python의 소멸 관련 특수 메서드를 묻는다면 &lt;code&gt;__del__()&lt;/code&gt;을 떠올릴 수 있습니다. 다만 실제 프로그램에서는 언제 호출될지 확실하지 않으므로 파일이나 네트워크 연결을 정리하는 수단으로 의존하지 않습니다. 이런 자원은 &lt;code&gt;with&lt;/code&gt;문이나 명시적인 &lt;code&gt;close()&lt;/code&gt;로 정리하는 편이 안전합니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;8. 자기 자신을 가리키는 &lt;code&gt;this&lt;/code&gt;와 &lt;code&gt;self&lt;/code&gt;&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;Java의 &lt;code&gt;this&lt;/code&gt;&lt;/h3&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;this&lt;/code&gt;는 현재 객체를 가리키는 Java 키워드입니다. 생성자의 매개변수와 객체의 필드 이름이 같을 때 둘을 구분하는 용도로 자주 사용합니다.&lt;/p&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;class Taiyaki {
    String flavor;

    Taiyaki(String flavor) {
        this.flavor = flavor;
    }
}&lt;/code&gt;&lt;/pre&gt;

  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;this.flavor&lt;/code&gt;: 현재 객체가 가진 필드&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;flavor&lt;/code&gt;: 생성자로 들어온 매개변수&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;Python의 &lt;code&gt;self&lt;/code&gt;&lt;/h3&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;Python의 인스턴스 메서드에서는 첫 번째 매개변수로 현재 인스턴스가 전달됩니다. 관례상 이 매개변수의 이름을 &lt;code&gt;self&lt;/code&gt;라고 씁니다.&lt;/p&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;class Taiyaki:
    def __init__(self, flavor):
        self.flavor = flavor&lt;/code&gt;&lt;/pre&gt;

  &lt;div style=&quot;margin:1.35em 0;padding:1em 1.1em;border:1px solid #dbe5f5;border-left:4px solid #3f75ff;border-radius:8px;background:#f8fbff;&quot;&gt;
    &lt;strong style=&quot;display:block;margin:0 0 .45em;color:#172033;&quot;&gt;&lt;code&gt;self&lt;/code&gt;는 Python 키워드가 아니다&lt;/strong&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;다른 이름을 써도 문법상 가능하지만 모든 Python 개발자가 알아보기 쉽도록 &lt;code&gt;self&lt;/code&gt;를 사용하는 것이 표준적인 관례입니다. 또한 &lt;code&gt;self&lt;/code&gt;는 인스턴스 메서드에 해당하는 설명입니다. 클래스 메서드는 보통 &lt;code&gt;cls&lt;/code&gt;를 받고, 정적 메서드는 인스턴스를 첫 매개변수로 받지 않습니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;-webkit-overflow-scrolling:touch;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:630px;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;Java this와 Python self 비교&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;구분&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;Java &lt;code&gt;this&lt;/code&gt;&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;Python &lt;code&gt;self&lt;/code&gt;&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;정체&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;언어의 키워드&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;관례적인 매개변수명&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfd;&quot;&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;의미&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;현재 객체 참조&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;현재 인스턴스를 전달받은 참조&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;대표 표현&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;this.flavor&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;self.flavor&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;9. 절차지향과 객체지향의 차이&lt;/h2&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;C를 공부하다가 Java나 Python의 클래스를 만나면 “명령형과 객체지향은 완전히 반대인가?”라는 의문이 생깁니다. 정확히는 &lt;strong&gt;C에서 흔히 사용하는 절차지향적 접근&lt;/strong&gt;과 &lt;strong&gt;클래스 기반 객체지향적 접근&lt;/strong&gt;이 프로그램을 나누고 조직하는 기준에서 차이를 보이는 것입니다.&lt;/p&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;-webkit-overflow-scrolling:touch;&quot;&gt;
    &lt;table style=&quot;width:100%;min-width:680px;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;절차지향 접근과 객체지향 접근 비교&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;구분&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;절차지향 접근&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;객체지향 접근&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;중심 질문&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;어떤 순서와 함수로 처리할까?&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;어떤 객체가 어떤 책임을 맡고 협력할까?&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfd;&quot;&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;주요 분해 단위&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;함수·절차&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;클래스·객체&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;데이터와 동작&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;데이터를 함수에 전달해 처리하는 형태가 흔함&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;관련 상태와 동작을 객체 안에 함께 설계&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr style=&quot;background:#fbfcfd;&quot;&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;font-weight:700;&quot;&gt;강점&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;작업 흐름이 선명한 문제를 간결하게 표현&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;책임 분리, 재사용, 변경 범위 관리에 유리&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;객체지향에서도 실행 순서는 중요하고, 절차지향 프로그램도 함수와 모듈을 잘 나누면 충분히 유지보수하기 좋습니다. Python과 C++은 여러 프로그래밍 방식을 함께 지원하기도 합니다. 따라서 “C는 무조건 빠르고 객체지향은 무조건 느리다”처럼 언어와 패러다임을 단순하게 나누어 외우지 않는 편이 좋습니다.&lt;/p&gt;

  &lt;div style=&quot;margin:1.35em 0;padding:1em 1.1em;border:1px solid #d9eee5;border-left:4px solid #2a9d8f;border-radius:8px;background:#f4fbf8;&quot;&gt;
    &lt;strong style=&quot;display:block;margin:0 0 .45em;color:#165c50;&quot;&gt;캡슐화의 정확한 의미&lt;/strong&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;캡슐화는 단순히 데이터와 함수를 한 상자에 넣는 것에서 끝나지 않습니다. 객체의 내부 상태를 함부로 바꾸지 못하게 숨기고, 필요한 기능만 공개된 인터페이스로 제공해 변경의 영향을 줄이는 설계 원리입니다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;10. 시험 직전 암기 카드&lt;/h2&gt;

  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;조건문&lt;/strong&gt;: &lt;code&gt;if&lt;/code&gt;는 조건식을, &lt;code&gt;switch&lt;/code&gt;는 일치하는 &lt;code&gt;case&lt;/code&gt;를 확인&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;&lt;code&gt;switch&lt;/code&gt; 함정&lt;/strong&gt;: &lt;code&gt;break&lt;/code&gt;가 없으면 다음 &lt;code&gt;case&lt;/code&gt;까지 이어서 실행&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;반복문&lt;/strong&gt;: &lt;code&gt;while&lt;/code&gt;은 0회 가능, &lt;code&gt;do-while&lt;/code&gt;은 최소 1회 실행&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;흐름 제어&lt;/strong&gt;: &lt;code&gt;break&lt;/code&gt;는 종료, &lt;code&gt;continue&lt;/code&gt;는 현재 반복 건너뛰기, &lt;code&gt;return&lt;/code&gt;은 함수 종료&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;함수 원형&lt;/strong&gt;: 반환형·함수명·매개변수 형태를 호출 전에 컴파일러에 알림&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;C의 인수 전달&lt;/strong&gt;: 항상 값을 복사하며, 주소를 전달하고 역참조하면 원본 변경 가능&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;재귀 함수&lt;/strong&gt;: 자기 자신을 호출하므로 반드시 종료 조건이 필요&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;구조체&lt;/strong&gt;: 서로 관련된 서로 다른 자료형을 하나로 묶은 사용자 정의 자료형&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;일반 구조체 변수&lt;/strong&gt;: &lt;code&gt;s1.age&lt;/code&gt;처럼 점(&lt;code&gt;.&lt;/code&gt;) 사용&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;구조체 포인터&lt;/strong&gt;: &lt;code&gt;p-&amp;gt;age&lt;/code&gt;처럼 화살표(&lt;code&gt;-&amp;gt;&lt;/code&gt;) 사용&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;동치식&lt;/strong&gt;: &lt;code&gt;p-&amp;gt;age == (*p).age&lt;/code&gt;&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;클래스&lt;/strong&gt;: 객체의 상태와 동작을 정의한 설계도&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;객체·인스턴스&lt;/strong&gt;: 클래스로부터 만들어진 실체&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;Java 생성자&lt;/strong&gt;: 클래스와 같은 이름, 반환형 없음&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;Python 초기화&lt;/strong&gt;: &lt;code&gt;__init__(self, ...)&lt;/code&gt;&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;현재 객체&lt;/strong&gt;: Java는 &lt;code&gt;this&lt;/code&gt;, Python 인스턴스 메서드는 관례상 &lt;code&gt;self&lt;/code&gt;&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;절차지향&lt;/strong&gt;: 함수와 처리 흐름 중심, &lt;strong&gt;객체지향&lt;/strong&gt;: 객체의 책임과 협력 중심&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;11. 미니 퀴즈로 마무리&lt;/h2&gt;

  &lt;ol style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.5em 0;&quot;&gt;위의 &lt;code&gt;switch&lt;/code&gt; 예제에서 &lt;code&gt;n&lt;/code&gt;이 2일 때 출력되는 문자열은?&lt;/li&gt;
    &lt;li style=&quot;margin:.5em 0;&quot;&gt;&lt;code&gt;do-while&lt;/code&gt;문의 본문은 최소 몇 번 실행될까?&lt;/li&gt;
    &lt;li style=&quot;margin:.5em 0;&quot;&gt;&lt;code&gt;break&lt;/code&gt;와 &lt;code&gt;continue&lt;/code&gt;의 차이는?&lt;/li&gt;
    &lt;li style=&quot;margin:.5em 0;&quot;&gt;C에서 &lt;code&gt;change_value(a)&lt;/code&gt;를 호출한 뒤 원본 &lt;code&gt;a&lt;/code&gt;가 그대로인 이유는?&lt;/li&gt;
    &lt;li style=&quot;margin:.5em 0;&quot;&gt;재귀 함수가 끝나기 위해 반드시 필요한 것은?&lt;/li&gt;
    &lt;li style=&quot;margin:.5em 0;&quot;&gt;구조체 변수 &lt;code&gt;s1&lt;/code&gt;의 &lt;code&gt;age&lt;/code&gt; 멤버에 접근하는 표현은?&lt;/li&gt;
    &lt;li style=&quot;margin:.5em 0;&quot;&gt;구조체 포인터 &lt;code&gt;p&lt;/code&gt;가 가리키는 구조체의 &lt;code&gt;age&lt;/code&gt;에 접근하는 표현 두 가지는?&lt;/li&gt;
    &lt;li style=&quot;margin:.5em 0;&quot;&gt;Java 생성자에 반환형 &lt;code&gt;void&lt;/code&gt;를 적어도 될까?&lt;/li&gt;
    &lt;li style=&quot;margin:.5em 0;&quot;&gt;Python에서 &lt;code&gt;self&lt;/code&gt;는 언어가 예약한 키워드일까?&lt;/li&gt;
    &lt;li style=&quot;margin:.5em 0;&quot;&gt;특정 클래스를 바탕으로 객체를 만드는 과정을 무엇이라고 할까?&lt;/li&gt;
  &lt;/ol&gt;

  &lt;details style=&quot;margin:1.35em 0;border:1px solid #dbe5f5;border-radius:8px;background:#f8fbff;padding:.95em 1.1em;&quot;&gt;
    &lt;summary style=&quot;cursor:pointer;font-weight:800;color:#172033;&quot;&gt;정답 확인하기&lt;/summary&gt;
    &lt;ol style=&quot;margin:.9em 0 0 1.15em;padding:0;&quot;&gt;
      &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;BC&lt;/code&gt;. &lt;code&gt;case 2&lt;/code&gt; 뒤에 &lt;code&gt;break&lt;/code&gt;가 없어 &lt;code&gt;case 3&lt;/code&gt;까지 실행된다.&lt;/li&gt;
      &lt;li style=&quot;margin:.42em 0;&quot;&gt;최소 1번. 본문을 먼저 실행한 뒤 조건을 검사한다.&lt;/li&gt;
      &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;break&lt;/code&gt;는 반복문을 끝내고, &lt;code&gt;continue&lt;/code&gt;는 현재 반복의 나머지만 건너뛴다.&lt;/li&gt;
      &lt;li style=&quot;margin:.42em 0;&quot;&gt;함수에 원본이 아니라 값의 복사본이 전달되기 때문이다.&lt;/li&gt;
      &lt;li style=&quot;margin:.42em 0;&quot;&gt;재귀 호출을 멈추는 종료 조건&lt;/li&gt;
      &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;s1.age&lt;/code&gt;&lt;/li&gt;
      &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;p-&amp;gt;age&lt;/code&gt;, &lt;code&gt;(*p).age&lt;/code&gt;&lt;/li&gt;
      &lt;li style=&quot;margin:.42em 0;&quot;&gt;안 된다. 반환형을 적으면 생성자가 아니라 메서드가 된다.&lt;/li&gt;
      &lt;li style=&quot;margin:.42em 0;&quot;&gt;아니다. 현재 인스턴스를 받는 첫 매개변수에 사용하는 관례적인 이름이다.&lt;/li&gt;
      &lt;li style=&quot;margin:.42em 0;&quot;&gt;인스턴스화&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/details&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;12. 공식 문서 참고 자료&lt;/h2&gt;

  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.48em 0;&quot;&gt;&lt;a href=&quot;https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Statements.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;GNU C Language Manual: Statements&lt;/a&gt;&lt;/li&gt;
    &lt;li style=&quot;margin:.48em 0;&quot;&gt;&lt;a href=&quot;https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Functions.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;GNU C Language Manual: Functions&lt;/a&gt;&lt;/li&gt;
    &lt;li style=&quot;margin:.48em 0;&quot;&gt;&lt;a href=&quot;https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Structures.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;GNU C Language Manual: Structures&lt;/a&gt;&lt;/li&gt;
    &lt;li style=&quot;margin:.48em 0;&quot;&gt;&lt;a href=&quot;https://docs.python.org/3/tutorial/controlflow.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;Python 공식 문서: Control Flow와 함수&lt;/a&gt;&lt;/li&gt;
    &lt;li style=&quot;margin:.48em 0;&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;Oracle Java Tutorials: Constructors&lt;/a&gt;&lt;/li&gt;
    &lt;li style=&quot;margin:.48em 0;&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;Oracle Java Tutorials: this Keyword&lt;/a&gt;&lt;/li&gt;
    &lt;li style=&quot;margin:.48em 0;&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/26/docs/api/deprecated-list.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;Java SE 26 Deprecated API List&lt;/a&gt;&lt;/li&gt;
    &lt;li style=&quot;margin:.48em 0;&quot;&gt;&lt;a href=&quot;https://docs.python.org/3/tutorial/classes.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;Python 공식 문서: Classes&lt;/a&gt;&lt;/li&gt;
    &lt;li style=&quot;margin:.48em 0;&quot;&gt;&lt;a href=&quot;https://docs.python.org/3/reference/datamodel.html#object.__del__&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;Python Data Model: __del__()&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;마무리&lt;/h2&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;3일차의 네 단원은 따로 떨어져 있지 않습니다. 명령문으로 실행 흐름을 만들고, 반복되는 작업은 사용자 정의 함수로 분리합니다. 여러 데이터를 구조체로 묶는 방법을 익힌 뒤에는 상태와 동작을 함께 설계하는 클래스로 확장됩니다.&lt;/p&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;시험 직전에는 &lt;code&gt;switch&lt;/code&gt;의 &lt;code&gt;break&lt;/code&gt;, 반복 횟수, 함수의 값 전달, 재귀 종료 조건, 구조체의 점·화살표 연산자를 우선 확인하세요. 클래스 부분은 “설계도에서 객체를 만들고, 생성자가 초기값을 넣으며, &lt;code&gt;this&lt;/code&gt;와 &lt;code&gt;self&lt;/code&gt;가 현재 객체를 구분한다”는 흐름으로 기억하면 좋습니다.&lt;/p&gt;

  &lt;p style=&quot;margin:1.7em 0 0;padding-top:1.1em;border-top:1px solid #edf0f4;font-size:.88em;color:#747d8c;&quot;&gt;이 글은 정보처리기사 학습 내용을 바탕으로 개념을 다시 구성한 개인 공부 기록입니다. 교재 문장을 그대로 옮긴 해설이 아니며, 세부 출제 범위와 표현은 최신 교재와 출제 기준을 함께 확인해 주세요.&lt;/p&gt;
&lt;/article&gt;</description>
      <category>AI/정보처리기사_스터디</category>
      <category>c언어</category>
      <category>구조체</category>
      <category>구조체포인터</category>
      <category>명령문</category>
      <category>반복문</category>
      <category>사용자정의함수</category>
      <category>수제비</category>
      <category>정보처리기사</category>
      <category>정처기</category>
      <category>조건문</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/112</guid>
      <comments>https://onethingflow.tistory.com/entry/%EC%A0%95%EC%B2%98%EA%B8%B0-3%EC%9D%BC%EC%B0%A8-%EC%88%98%EC%A0%9C%EB%B9%84-%EB%AA%85%EB%A0%B9%EB%AC%B8%C2%B7%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%A0%95%EC%9D%98-%ED%95%A8%EC%88%98%C2%B7%EA%B5%AC%EC%A1%B0%EC%B2%B4%C2%B7%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%B4%9D%EC%A0%95%EB%A6%AC#entry112comment</comments>
      <pubDate>Tue, 14 Jul 2026 21:23:43 +0900</pubDate>
    </item>
    <item>
      <title>Day 9) 프로그래머스 문자열 문제: 리스트 컴프리헨션, zip, 슬라이싱, 접미사 풀이 정리</title>
      <link>https://onethingflow.tistory.com/entry/Day-9-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%AC%B8%EC%A0%9C-%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EC%BB%B4%ED%94%84%EB%A6%AC%ED%97%A8%EC%85%98-zip-%EC%8A%AC%EB%9D%BC%EC%9D%B4%EC%8B%B1-%EC%A0%91%EB%AF%B8%EC%82%AC-%ED%92%80%EC%9D%B4-%EC%A0%95%EB%A6%AC</link>
      <description>&lt;!--
티스토리 제목 추천:
Day 9) 프로그래머스 문자열 문제: 리스트 컴프리헨션, zip, 슬라이싱, 접미사 풀이 정리

메타 설명 추천:
프로그래머스 코딩 기초 트레이닝 Day 9 문자열 문제인 배열 만들기 5, 부분 문자열 이어 붙여 문자열 만들기, 문자열의 뒤의 n글자, 접미사 배열, 접미사인지 확인하기를 파이썬으로 풀며 리스트 컴프리헨션, zip, join, 음수 슬라이싱, sorted, endswith 실수를 정리했습니다.

태그 추천:
프로그래머스, 코딩테스트, 파이썬, 문자열, 리스트컴프리헨션, 슬라이싱, zip, join, sorted, endswith, 배열만들기5, 접미사배열
--&gt;

&lt;article style=&quot;max-width:780px;margin:0 auto;line-height:1.86;font-size:17px;color:#222;word-break:keep-all;&quot;&gt;
  &lt;section style=&quot;margin:0 0 1.5em;padding:1.35em 1.4em;border:1px solid #dde6f2;border-radius:8px;background:linear-gradient(135deg,#f7fbff 0%,#fff 62%,#fff7ed 100%);&quot;&gt;
    &lt;p style=&quot;margin:0 0 .8em;display:inline-block;padding:.25em .7em;border:1px solid #d9e4f2;border-radius:999px;background:#fff;font-size:.84em;font-weight:700;color:#385174;&quot;&gt;Day 9 코딩테스트 공부 기록&lt;/p&gt;
    &lt;h1 style=&quot;margin:.1em 0 .72em;font-size:2em;line-height:1.28;font-weight:800;color:#111;&quot;&gt;프로그래머스 문자열 문제: 리스트 컴프리헨션, zip, 슬라이싱, 접미사 풀이 정리&lt;/h1&gt;
    &lt;p style=&quot;margin:0 0 1em;font-size:1.08em;color:#343b46;&quot;&gt;이번 글은 Google 문서에 정리해 둔 문자열 문제 풀이 흐름을 블로그 글로 다시 다듬은 기록입니다. 핵심은 문자열을 자르고, 필요한 부분만 이어 붙이고, 접미사를 만들고, 조건에 맞게 판별하는 것입니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;처음에는 반복문으로 차근차근 풀고, 그다음 리스트 컴프리헨션, &lt;code&gt;zip()&lt;/code&gt;, &lt;code&gt;join()&lt;/code&gt;, 음수 슬라이싱, &lt;code&gt;sorted()&lt;/code&gt;, &lt;code&gt;endswith()&lt;/code&gt;로 더 간단하게 줄이는 흐름까지 정리했습니다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;div style=&quot;display:grid;grid-template-columns:repeat(3,1fr);gap:.85em;margin:1.35em 0;&quot;&gt;
    &lt;div style=&quot;border:1px solid #e3e8ef;border-radius:8px;background:#fff;padding:1em;&quot;&gt;
      &lt;span style=&quot;display:block;font-size:.82em;color:#687182;margin-bottom:.25em;&quot;&gt;핵심 1&lt;/span&gt;
      &lt;strong style=&quot;display:block;font-size:1.04em;color:#101418;line-height:1.36;&quot;&gt;문자열 슬라이싱&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div style=&quot;border:1px solid #e3e8ef;border-radius:8px;background:#fff;padding:1em;&quot;&gt;
      &lt;span style=&quot;display:block;font-size:.82em;color:#687182;margin-bottom:.25em;&quot;&gt;핵심 2&lt;/span&gt;
      &lt;strong style=&quot;display:block;font-size:1.04em;color:#101418;line-height:1.36;&quot;&gt;컴프리헨션과 join&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div style=&quot;border:1px solid #e3e8ef;border-radius:8px;background:#fff;padding:1em;&quot;&gt;
      &lt;span style=&quot;display:block;font-size:.82em;color:#687182;margin-bottom:.25em;&quot;&gt;핵심 3&lt;/span&gt;
      &lt;strong style=&quot;display:block;font-size:1.04em;color:#101418;line-height:1.36;&quot;&gt;접미사와 사전순 정렬&lt;/strong&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;blockquote style=&quot;margin:1.55em 0;padding:.95em 1.15em;background:#fff9e8;border-left:4px solid #f2b705;border-radius:8px;font-size:1.06em;font-weight:800;color:#584500;&quot;&gt;
    문자열 문제는 “어디서부터 어디까지 자르는가”와 “자른 조각을 언제 합치는가”를 정확히 잡는 것이 핵심이었습니다.
  &lt;/blockquote&gt;

  &lt;section style=&quot;margin:1.6em 0;padding:1em 1.1em;border:1px solid #e2e8f0;border-radius:8px;background:#fbfdff;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 .65em;font-size:1.18em;line-height:1.45;font-weight:800;color:#111;&quot;&gt;이 글에 빠짐없이 반영한 내용&lt;/h2&gt;
    &lt;ol style=&quot;margin:0 0 0 1.15em;padding:0;&quot;&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;배열 만들기 5: &lt;code&gt;s:s+l&lt;/code&gt;, &lt;code&gt;int()&lt;/code&gt;, 리스트 컴프리헨션, 중복 연산 줄이기&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;부분 문자열 이어 붙이기: 잘못된 이중 반복문, &lt;code&gt;zip()&lt;/code&gt;, &lt;code&gt;s:e+1&lt;/code&gt;, &lt;code&gt;join()&lt;/code&gt;&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;문자열의 뒤의 n글자: 음수 슬라이싱 &lt;code&gt;[-n:]&lt;/code&gt;&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;접미사 배열: 접미사 만들기, 리스트 컴프리헨션, 사전순 정렬&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;접미사인지 확인하기: &lt;code&gt;in&lt;/code&gt;의 한계, 하드코딩 제거, 오타 수정, &lt;code&gt;endswith()&lt;/code&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/section&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;1. 문제 및 프로그래머스 공식 링크&lt;/h2&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;이번 글에서 정리한 문제는 모두 프로그래머스 코딩 기초 트레이닝의 문자열 관련 문제입니다.&lt;/p&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;&quot;&gt;
    &lt;table style=&quot;width:100%;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;프로그래머스 문자열 문제 링크와 핵심 개념&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;문제&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;공식 링크&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;핵심 개념&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;배열 만들기 5&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181912&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;슬라이싱, 정수 변환, 리스트 컴프리헨션&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;부분 문자열 이어 붙여 문자열 만들기&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181911&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;zip, 언패킹, join&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;문자열의 뒤의 n글자&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181910&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;음수 인덱싱, 슬라이싱&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;접미사 배열&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181909&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;접미사, sorted&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;접미사인지 확인하기&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181908&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;endswith, 반례, boolean 변환&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;2. 배열 만들기 5: 자른 문자열을 정수로 바꿔 비교하기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;intStrs&lt;/code&gt;의 각 문자열에서 &lt;code&gt;s&lt;/code&gt;번 인덱스부터 길이 &lt;code&gt;l&lt;/code&gt;만큼 잘라냅니다. 잘라낸 부분 문자열을 정수로 바꾼 값이 &lt;code&gt;k&lt;/code&gt;보다 크면 결과 배열에 담습니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;내가 작성한 리스트 컴프리헨션 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(intStrs, k, s, l):
    return [int(intstr[s:s+l]) for intstr in intStrs if int(intstr[s:s+l]) &amp;gt; k]&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;좋았던 점과 보완할 점&lt;/h3&gt;
  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;intstr[s:s+l]&lt;/code&gt;로 &lt;code&gt;s&lt;/code&gt;부터 길이 &lt;code&gt;l&lt;/code&gt;만큼 자르는 핵심을 정확히 사용했습니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;잘라낸 값은 문자열이므로 &lt;code&gt;int()&lt;/code&gt;로 정수 변환한 뒤 &lt;code&gt;k&lt;/code&gt;와 비교해야 합니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;다만 &lt;code&gt;int(intstr[s:s+l])&lt;/code&gt;가 조건문에서 한 번, 결과 리스트에 넣을 때 한 번, 총 두 번 계산됩니다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;중복 계산을 줄인 기본 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(intStrs, k, s, l):
    answer = []

    for intstr in intStrs:
        num = int(intstr[s:s+l])
        if num &amp;gt; k:
            answer.append(num)

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;처음 공부할 때는 이 풀이가 가장 읽기 쉽습니다. &lt;code&gt;num&lt;/code&gt;이라는 변수에 잘라낸 값을 한 번만 저장하고, 조건을 만족하면 &lt;code&gt;answer&lt;/code&gt;에 추가합니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;대입 표현식을 활용한 한 줄 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(intStrs, k, s, l):
    return [val for intstr in intStrs if (val := int(intstr[s:s+l])) &amp;gt; k]&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;:=&lt;/code&gt;는 계산한 값을 변수에 저장하면서 조건식에도 사용할 수 있는 문법입니다. 여기서는 부분 문자열을 정수로 바꾼 값을 &lt;code&gt;val&lt;/code&gt;에 저장하고, 그 값이 &lt;code&gt;k&lt;/code&gt;보다 큰지 확인합니다. 다만 처음 보는 사람에게는 낯설 수 있으므로, 블로그 글에서는 기본 풀이도 함께 보여주는 편이 좋습니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;3. 부분 문자열 이어 붙여 문자열 만들기: 두 배열을 1:1로 묶기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;my_strings&lt;/code&gt;와 &lt;code&gt;parts&lt;/code&gt;가 같은 길이로 주어집니다. &lt;code&gt;parts[i]&lt;/code&gt;는 &lt;code&gt;[s, e]&lt;/code&gt; 형태이고, &lt;code&gt;my_strings[i]&lt;/code&gt;에서 &lt;code&gt;s&lt;/code&gt;부터 &lt;code&gt;e&lt;/code&gt;까지 자른 문자열을 순서대로 이어 붙이면 됩니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;처음 헷갈린 코드&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_strings, parts):
    answer = ''

    for s, e in parts:
        for i in answer += my_strings[i][s:e]

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;잘못된 점&lt;/h3&gt;
  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;for i in&lt;/code&gt; 뒤에 반복할 대상이 비어 있어 문법 오류가 납니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;이 문제는 모든 문자열에 모든 구간을 적용하는 문제가 아닙니다. 같은 위치의 &lt;code&gt;my_strings[i]&lt;/code&gt;와 &lt;code&gt;parts[i]&lt;/code&gt;를 1:1로 매칭해야 합니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;문제는 &lt;code&gt;e&lt;/code&gt; 인덱스까지 포함해서 자르라고 하므로 &lt;code&gt;s:e&lt;/code&gt;가 아니라 &lt;code&gt;s:e+1&lt;/code&gt;을 써야 합니다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;인덱스를 활용한 정석 풀이 1&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_strings, parts):
    answer = ''

    for i in range(len(parts)):
        l, r = parts[i]
        answer += my_strings[i][l:r+1]

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;l, r = parts[i]&lt;/code&gt;는 언패킹입니다. 예를 들어 &lt;code&gt;parts[i]&lt;/code&gt;가 &lt;code&gt;[2, 4]&lt;/code&gt;라면 &lt;code&gt;l&lt;/code&gt;에는 2, &lt;code&gt;r&lt;/code&gt;에는 4가 들어갑니다. 변수 이름을 따로 두면 슬라이싱 범위가 훨씬 잘 보입니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;인덱스를 직접 쓰는 풀이 2&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_strings, parts):
    answer = &quot;&quot;

    for i in range(len(parts)):
        answer += my_strings[i][parts[i][0]:parts[i][1] + 1]

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;이 풀이도 정답입니다. &lt;code&gt;parts[i][0]&lt;/code&gt;은 시작점, &lt;code&gt;parts[i][1]&lt;/code&gt;은 끝점입니다. 다만 대괄호가 많이 겹쳐서 첫 번째 풀이보다 읽기가 조금 어렵습니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;zip을 활용한 기본 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_strings, parts):
    answer = ''

    for string, (s, e) in zip(my_strings, parts):
        answer += string[s:e+1]

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;zip(my_strings, parts)&lt;/code&gt;는 문자열 하나와 구간 하나를 동시에 꺼내 줍니다. 그래서 인덱스 &lt;code&gt;i&lt;/code&gt;를 직접 만들지 않아도 &lt;code&gt;string&lt;/code&gt;과 &lt;code&gt;[s, e]&lt;/code&gt;를 1:1로 다룰 수 있습니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;join까지 활용한 한 줄 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_strings, parts):
    return ''.join(string[s:e+1] for string, (s, e) in zip(my_strings, parts))&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;문자열을 &lt;code&gt;+=&lt;/code&gt;로 계속 더하면 매번 새 문자열을 만드는 흐름이 됩니다. 입력이 크다면 조각들을 모아 &lt;code&gt;join()&lt;/code&gt;으로 한 번에 합치는 방식이 더 깔끔합니다.&lt;/p&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;&quot;&gt;
    &lt;table style=&quot;width:100%;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;부분 문자열 풀이 방식 비교&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;풀이 방식&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;특징&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;추천 상황&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;l, r = parts[i]&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;시작점과 끝점을 변수로 분리해서 읽기 쉽습니다.&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;처음 풀이를 설명할 때 좋습니다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;parts[i][0]&lt;/code&gt;, &lt;code&gt;parts[i][1]&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;변수를 줄일 수 있지만 대괄호가 많아집니다.&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;짧게 쓸 때 가능하지만 가독성은 낮습니다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;zip()&lt;/code&gt;과 &lt;code&gt;join()&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;두 배열을 1:1로 묶고 문자열을 한 번에 합칩니다.&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;실전에서 가장 깔끔하게 쓰기 좋습니다.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;4. 문자열의 뒤의 n글자: 음수 슬라이싱으로 끝에서 자르기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;my_string&lt;/code&gt;의 뒤에서 &lt;code&gt;n&lt;/code&gt;글자만 잘라 반환하면 됩니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;내 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_string, n):
    return my_string[-n:]&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;[-n:]&lt;/code&gt;은 뒤에서 &lt;code&gt;n&lt;/code&gt;번째 위치부터 문자열 끝까지 자르겠다는 뜻입니다. 예를 들어 &lt;code&gt;&quot;He110W0r1d&quot;&lt;/code&gt;에서 &lt;code&gt;n = 5&lt;/code&gt;라면 뒤의 5글자인 &lt;code&gt;&quot;W0r1d&quot;&lt;/code&gt;가 반환됩니다.&lt;/p&gt;

  &lt;section style=&quot;margin:1.35em 0;padding:1em 1.1em;border:1px solid #dbe5f5;border-radius:8px;background:#f8fbff;&quot;&gt;
    &lt;strong style=&quot;display:block;margin:0 0 .45em;color:#172033;&quot;&gt;왜 &lt;code&gt;len(my_string) - n&lt;/code&gt;을 안 써도 될까?&lt;/strong&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;파이썬은 음수 인덱스를 지원합니다. &lt;code&gt;-1&lt;/code&gt;은 마지막 글자, &lt;code&gt;-2&lt;/code&gt;는 뒤에서 두 번째 글자를 의미합니다. 그래서 뒤에서부터 자르는 문제에서는 &lt;code&gt;my_string[len(my_string)-n:]&lt;/code&gt;보다 &lt;code&gt;my_string[-n:]&lt;/code&gt;이 훨씬 간단합니다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;5. 접미사 배열: 모든 접미사를 만들고 사전순으로 정렬하기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;접미사는 어떤 인덱스부터 문자열 끝까지 이어지는 문자열입니다. 예를 들어 &lt;code&gt;&quot;banana&quot;&lt;/code&gt;의 접미사는 &lt;code&gt;&quot;banana&quot;&lt;/code&gt;, &lt;code&gt;&quot;anana&quot;&lt;/code&gt;, &lt;code&gt;&quot;nana&quot;&lt;/code&gt;, &lt;code&gt;&quot;ana&quot;&lt;/code&gt;, &lt;code&gt;&quot;na&quot;&lt;/code&gt;, &lt;code&gt;&quot;a&quot;&lt;/code&gt;입니다. 이 접미사들을 사전순으로 정렬해서 반환해야 합니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;처음 작성한 코드&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_string):
    answer = []

    for i in range(len(my_string)):
        answer.append(my_string[i:])

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;접미사를 만드는 로직 자체는 맞습니다. &lt;code&gt;my_string[i:]&lt;/code&gt;는 &lt;code&gt;i&lt;/code&gt;번째 인덱스부터 끝까지 자르므로, 모든 접미사를 만들 수 있습니다. 다만 문제에서 요구한 것은 “사전순으로 정렬한 배열”이기 때문에 마지막에 정렬이 필요합니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;리스트 컴프리헨션으로 줄이기&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_string):
    return [my_string[i:] for i in range(len(my_string))]&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;이 코드는 모든 접미사를 만드는 데까지는 깔끔합니다. 하지만 &lt;code&gt;접미사 배열&lt;/code&gt; 문제에서는 사전순 정렬 조건이 있으므로 여기서 한 단계 더 가야 합니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;최종 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_string):
    return sorted(my_string[i:] for i in range(len(my_string)))&lt;/code&gt;&lt;/pre&gt;

  &lt;section style=&quot;margin:1.35em 0;padding:1em 1.1em;border:1px solid #dbe5f5;border-radius:8px;background:#f8fbff;&quot;&gt;
    &lt;strong style=&quot;display:block;margin:0 0 .45em;color:#172033;&quot;&gt;사전순은 정렬이다&lt;/strong&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;문제에서 “사전순”이라고 나오면 문자열을 오름차순으로 정렬하라는 뜻으로 받아들이면 됩니다. 파이썬에서는 &lt;code&gt;sorted()&lt;/code&gt;가 문자열 리스트를 자동으로 사전순 정렬해 줍니다. 예를 들어 &lt;code&gt;[&quot;banana&quot;, &quot;apple&quot;, &quot;cherry&quot;]&lt;/code&gt;를 정렬하면 &lt;code&gt;[&quot;apple&quot;, &quot;banana&quot;, &quot;cherry&quot;]&lt;/code&gt;가 됩니다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;6. 접미사인지 확인하기: 포함 여부가 아니라 끝나는지 확인하기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;is_suffix&lt;/code&gt;가 &lt;code&gt;my_string&lt;/code&gt;의 접미사라면 1, 아니면 0을 반환합니다. 접미사는 문자열의 중간에 포함된 단어가 아니라, 문자열의 끝부분과 정확히 일치하는 문자열입니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;처음 작성한 코드&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_string, is_suffix):
    answer = 0

    if is_suffix in my_string:
        answer = 1
    elif &quot;nan&quot; in is_suffix:
        answer = 0
    else:
        ansewr = 0

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;잘못된 점&lt;/h3&gt;
  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;is_suffix in my_string&lt;/code&gt;은 문자열 어디에든 포함되어 있으면 &lt;code&gt;True&lt;/code&gt;입니다. 접미사인지 확인하는 조건으로는 부족합니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;&quot;nan&quot;&lt;/code&gt; 같은 특정 테스트 케이스를 직접 넣는 하드코딩은 피해야 합니다. 다른 반례가 나오면 바로 틀립니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;ansewr&lt;/code&gt;는 &lt;code&gt;answer&lt;/code&gt; 오타입니다. 파이썬은 새로운 변수로 인식할 수 있어 디버깅이 어려워집니다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;중간 보완 코드와 반례&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_string, is_suffix):
    answer = 0

    if is_suffix in my_string and is_suffix[-1] == my_string[-1]:
        answer = 1
    else:
        answer = 0

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;처음 코드보다 좋아졌지만 아직 완벽하지 않습니다. 예를 들어 &lt;code&gt;my_string = &quot;abcbac&quot;&lt;/code&gt;, &lt;code&gt;is_suffix = &quot;bc&quot;&lt;/code&gt;라면 &lt;code&gt;&quot;bc&quot;&lt;/code&gt;는 문자열 안에 있고 마지막 글자도 &lt;code&gt;&quot;c&quot;&lt;/code&gt;로 같습니다. 하지만 &lt;code&gt;&quot;abcbac&quot;&lt;/code&gt;의 끝은 &lt;code&gt;&quot;bc&quot;&lt;/code&gt;가 아니므로 접미사가 아닙니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;음수 슬라이싱으로 해결하기&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_string, is_suffix):
    if my_string[-len(is_suffix):] == is_suffix:
        return 1

    return 0&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;my_string[-len(is_suffix):]&lt;/code&gt;는 &lt;code&gt;is_suffix&lt;/code&gt;의 길이만큼 뒤에서 잘라낸 문자열입니다. 이 조각이 &lt;code&gt;is_suffix&lt;/code&gt;와 같으면 접미사입니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;boolean을 int로 바꾸는 한 줄 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_string, is_suffix):
    return int(my_string[-len(is_suffix):] == is_suffix)&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;파이썬에서 &lt;code&gt;True&lt;/code&gt;는 1, &lt;code&gt;False&lt;/code&gt;는 0으로 바꿀 수 있습니다. 그래서 비교 결과를 &lt;code&gt;int()&lt;/code&gt;로 감싸면 바로 문제의 반환 형태와 맞습니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;가장 간단한 풀이: endswith&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_string, is_suffix):
    return int(my_string.endswith(is_suffix))&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;endswith()&lt;/code&gt;는 문자열이 특정 문자열로 끝나는지 확인하는 메서드입니다. 접미사 문제의 의도와 정확히 맞는 도구라서 가장 짧고 안전합니다. 반대로 시작 문자열을 확인할 때는 &lt;code&gt;startswith()&lt;/code&gt;를 사용할 수 있습니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;7. 입출력 예로 빠르게 검산하기&lt;/h2&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;&quot;&gt;
    &lt;table style=&quot;width:100%;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;문자열 문제별 빠른 검산 예시&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;문제&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;예시 입력&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;기대 결과&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;배열 만들기 5&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[&quot;0123456789&quot;,&quot;9876543210&quot;,&quot;9999999999999&quot;], k=50000, s=5, l=5&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[56789, 99999]&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;부분 문자열 이어 붙이기&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[&quot;progressive&quot;,&quot;hamburger&quot;,&quot;hammer&quot;,&quot;ahocorasick&quot;], [[0,4],[1,2],[3,5],[7,7]]&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;&quot;programmers&quot;&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;문자열의 뒤의 n글자&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;&quot;He110W0r1d&quot;, n=5&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;&quot;W0r1d&quot;&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;접미사 배열&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;&quot;banana&quot;&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[&quot;a&quot;, &quot;ana&quot;, &quot;anana&quot;, &quot;banana&quot;, &quot;na&quot;, &quot;nana&quot;]&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;접미사인지 확인하기&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;&quot;banana&quot;, &quot;nan&quot;&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;8. 실수 방지 체크리스트&lt;/h2&gt;

  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;길이 &lt;code&gt;l&lt;/code&gt;만큼 자를 때는 &lt;code&gt;s:s+l&lt;/code&gt;을 사용한다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;끝 인덱스 &lt;code&gt;e&lt;/code&gt;를 포함해야 하면 &lt;code&gt;s:e+1&lt;/code&gt;을 사용한다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;문자열로 된 숫자는 비교 전에 &lt;code&gt;int()&lt;/code&gt;로 바꾼다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;같은 계산을 두 번 한다면 변수에 저장해서 재사용할 수 있는지 확인한다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;두 배열을 같은 인덱스로 묶어야 할 때는 &lt;code&gt;zip()&lt;/code&gt;을 떠올린다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;문자열을 여러 조각 이어 붙일 때는 &lt;code&gt;+=&lt;/code&gt;보다 &lt;code&gt;join()&lt;/code&gt;이 더 깔끔할 수 있다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;뒤에서 &lt;code&gt;n&lt;/code&gt;글자를 자를 때는 &lt;code&gt;[-n:]&lt;/code&gt;을 사용한다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;“사전순”은 문자열 정렬이므로 &lt;code&gt;sorted()&lt;/code&gt;를 떠올린다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;접미사는 포함 여부가 아니라 끝부분 일치 여부다. &lt;code&gt;in&lt;/code&gt;보다 &lt;code&gt;endswith()&lt;/code&gt;가 정확하다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;특정 테스트 케이스만 막는 하드코딩은 피한다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;answer&lt;/code&gt;처럼 자주 쓰는 변수명은 오타가 나도 에러 없이 새 변수로 생길 수 있으니 철자를 확인한다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;9. 같이 보면 좋은 글&lt;/h2&gt;

  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;파이썬 문자열 슬라이싱 정리&lt;/strong&gt;: &lt;code&gt;s:s+l&lt;/code&gt;, &lt;code&gt;s:e+1&lt;/code&gt;, &lt;code&gt;[-n:]&lt;/code&gt;, &lt;code&gt;[::-1]&lt;/code&gt;을 함께 복습하기 좋습니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;리스트 컴프리헨션 기초&lt;/strong&gt;: 반복문과 조건문을 한 줄로 줄이는 연습에 도움이 됩니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;zip과 언패킹&lt;/strong&gt;: 여러 배열을 동시에 순회하는 문제에서 자주 나옵니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;문자열 메서드 endswith, startswith&lt;/strong&gt;: 접두사와 접미사 문제를 빠르게 풀 수 있습니다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;마무리&lt;/h2&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;이번 문서에서 다룬 문제들은 모두 문자열을 다루는 기본기가 중심이었습니다. 처음에는 반복문으로 직접 풀고, 이후에는 리스트 컴프리헨션이나 &lt;code&gt;zip()&lt;/code&gt;, &lt;code&gt;join()&lt;/code&gt;, &lt;code&gt;sorted()&lt;/code&gt;, &lt;code&gt;endswith()&lt;/code&gt; 같은 파이썬 도구로 코드를 줄여나가는 흐름이 좋았습니다.&lt;/p&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;특히 기억해야 할 점은 두 가지입니다. 첫째, 슬라이싱은 끝 인덱스를 포함하지 않으므로 문제에서 “끝까지 포함”이라고 하면 &lt;code&gt;+1&lt;/code&gt;을 확인해야 합니다. 둘째, 접미사는 단순히 문자열 안에 포함되어 있는지가 아니라 끝부분과 정확히 일치하는지를 확인해야 합니다.&lt;/p&gt;
&lt;/article&gt;</description>
      <category>AI/Coding_Test</category>
      <category>endswith</category>
      <category>join</category>
      <category>sorted</category>
      <category>zip</category>
      <category>리스트컴프리헨션</category>
      <category>문자열</category>
      <category>슬라이싱</category>
      <category>코딩테스트</category>
      <category>파이썬</category>
      <category>프로그래머스</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/111</guid>
      <comments>https://onethingflow.tistory.com/entry/Day-9-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%AC%B8%EC%A0%9C-%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EC%BB%B4%ED%94%84%EB%A6%AC%ED%97%A8%EC%85%98-zip-%EC%8A%AC%EB%9D%BC%EC%9D%B4%EC%8B%B1-%EC%A0%91%EB%AF%B8%EC%82%AC-%ED%92%80%EC%9D%B4-%EC%A0%95%EB%A6%AC#entry111comment</comments>
      <pubDate>Tue, 14 Jul 2026 20:58:57 +0900</pubDate>
    </item>
    <item>
      <title>정보처리기사_수제비_2일차</title>
      <link>https://onethingflow.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC%EC%88%98%EC%A0%9C%EB%B9%842%EC%9D%BC%EC%B0%A8</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 포인터와 역참조&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int a = 10;
int *b = &amp;amp;a;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;div&gt;표현의미결과
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;a&lt;/td&gt;
&lt;td&gt;변수에 저장된 값&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;amp;a&lt;/td&gt;
&lt;td&gt;a의 주소&lt;/td&gt;
&lt;td&gt;주소값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;b&lt;/td&gt;
&lt;td&gt;a의 주소를 저장한 포인터&lt;/td&gt;
&lt;td&gt;&amp;amp;a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;*b&lt;/td&gt;
&lt;td&gt;b가 가리키는 곳의 값&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 b와 a가 같은 것이 아니라, &lt;b&gt;*b와 a가 같은 메모리 공간을 뜻한다&lt;/b&gt;는 것이다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;*b = 20;
printf(&quot;%d&quot;, a);   // 20&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*b를 변경하면 같은 공간을 사용하는 a도 변경된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기호의 문맥도 구분해야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;int *b: 포인터 선언&lt;/li&gt;
&lt;li&gt;*b: 역참조&lt;/li&gt;
&lt;li&gt;&amp;amp;a: 주소 얻기&lt;/li&gt;
&lt;li&gt;a &amp;amp; b: 비트 AND&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문의 ***b를 출력하면?은 문맥상 *b를 출력하면?의 오타다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 배열과 포인터&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int arr[3] = {10, 20, 30};
int *p = arr;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열 이름 arr은 대부분의 식에서 첫 원소의 주소인 &amp;amp;arr[0]으로 변환된다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;arr[i] == *(arr + i)
p[i]   == *(p + i)&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;div&gt;표현값
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;*p 또는 *(p+0)&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;*(p+1)&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;*(p+2)&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;p+1은 주소를 1바이트 이동한다는 뜻이 아니다. &lt;b&gt;포인터가 가리키는 자료형 한 칸만큼 이동&lt;/b&gt;한다. int *p라면 다음 int 원소로 이동한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시험 함정:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;*(p + 1)  // 다음 원소의 값
*p + 1    // 현재 원소의 값에 1을 더함&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 p++는 가능하지만 배열 이름 자체에 arr++는 사용할 수 없다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 시프트&amp;middot;비트 연산자&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;연산자의미암기
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;x &amp;lt;&amp;lt; n&lt;/td&gt;
&lt;td&gt;왼쪽 시프트&lt;/td&gt;
&lt;td&gt;양수 기준 x &amp;times; 2ⁿ&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;x &amp;gt;&amp;gt; n&lt;/td&gt;
&lt;td&gt;오른쪽 시프트&lt;/td&gt;
&lt;td&gt;양수 기준 x &amp;divide; 2ⁿ의 몫&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;amp;&lt;/td&gt;
&lt;td&gt;AND&lt;/td&gt;
&lt;td&gt;둘 다 1이면 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;|&lt;/td&gt;
&lt;td&gt;OR&lt;/td&gt;
&lt;td&gt;하나라도 1이면 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;^&lt;/td&gt;
&lt;td&gt;XOR&lt;/td&gt;
&lt;td&gt;서로 다르면 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;~&lt;/td&gt;
&lt;td&gt;NOT&lt;/td&gt;
&lt;td&gt;모든 비트 반전&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시:&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;10 &amp;lt;&amp;lt; 2   // 10 &amp;times; 4 = 40
10 &amp;gt;&amp;gt; 2   // 10 &amp;divide; 4의 몫 = 2
10 ^ 12   // 6
~10       // -11&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NOT의 시험 공식:&lt;/p&gt;
&lt;pre class=&quot;gml&quot;&gt;&lt;code&gt;~x = -(x + 1)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시프트의 곱셈&amp;middot;나눗셈 공식은 주로 &lt;b&gt;양수이며 오버플로가 없는 문제&lt;/b&gt;에서 사용한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 연산자 우선순위&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;암기어는 &lt;b&gt;최단산시관비논삼대콤&lt;/b&gt;이다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;최: 최우선 (), [], ., -&amp;gt;&lt;/li&gt;
&lt;li&gt;단: 단항 !, ~, ++, --, sizeof, 형변환, 역참조&lt;/li&gt;
&lt;li&gt;산: 산술 * / % &amp;rarr; + -&lt;/li&gt;
&lt;li&gt;시: 시프트 &amp;lt;&amp;lt; &amp;gt;&amp;gt;&lt;/li&gt;
&lt;li&gt;관: 관계 &amp;lt; &amp;lt;= &amp;gt; &amp;gt;= &amp;rarr; == !=&lt;/li&gt;
&lt;li&gt;비: 비트 &amp;amp; &amp;rarr; ^ &amp;rarr; |&lt;/li&gt;
&lt;li&gt;논: 논리 &amp;amp;&amp;amp; &amp;rarr; ||&lt;/li&gt;
&lt;li&gt;삼: 삼항 조건 ? 참 : 거짓&lt;/li&gt;
&lt;li&gt;대: 대입 =, +=, -=&lt;/li&gt;
&lt;li&gt;콤: 콤마 ,&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단항&amp;middot;삼항&amp;middot;대입 연산자는 주로 오른쪽에서 왼쪽으로 결합한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전위와 후위&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int a = 3;
int b = ++a;   // a=4, b=4&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전위는 증가한 값을 사용한다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int a = 3;
int b = a++;   // b=3, 이후 a=4&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후위는 기존 값을 먼저 사용한 뒤 증가한다. 단순히 &amp;ldquo;무조건 줄 마지막에 증가한다&amp;rdquo;보다 &lt;b&gt;식의 결과로 이전 값을 내놓는다&lt;/b&gt;고 이해하는 편이 정확하다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. n진수와 16진수&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n진수를 10진수로 바꾸는 공식:&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;각 자릿수 &amp;times; n의 자릿값을 모두 더한다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1011₂ = 1&amp;times;2&amp;sup3; + 0&amp;times;2&amp;sup2; + 1&amp;times;2&amp;sup1; + 1&amp;times;2⁰ = 11
35₈   = 3&amp;times;8&amp;sup1; + 5&amp;times;8⁰ = 29
1A₁₆  = 1&amp;times;16&amp;sup1; + 10&amp;times;16⁰ = 26&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;16진수는 A=10부터 F=15까지 사용한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;16진수 한 자리 = 2진수 4비트&lt;/h3&gt;
&lt;pre class=&quot;basic&quot;&gt;&lt;code&gt;0x35
3 &amp;rarr; 0011
5 &amp;rarr; 0101

0x35 &amp;rarr; 0011 0101 &amp;rarr; 53&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4비트로 표현할 수 있는 경우가 2⁴=16개이므로 16진수 한 자리와 정확히 대응한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. AND 마스킹&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;0x35 = 0011 0101
0x0F = 0000 1111
       -----------
AND  = 0000 0101 = 0x05&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;0x35 &amp;amp; 0x0F   // 결과 5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;amp; 0x0F는 상위 4비트를 지우고 &lt;b&gt;하위 4비트만 남기는 마스킹&lt;/b&gt;이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 형변환과 %x&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;(int)5.8   // 5
(int)-5.8  // -5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실수를 정수로 형변환하면 소수점 이하를 0 방향으로 버린다. 비트 연산자는 int만 가능한 것이 아니라 char, int, long, unsigned 등 &lt;b&gt;정수형 자료형&lt;/b&gt;에 사용할 수 있고 실수형에는 직접 사용할 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력 서식:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;%d: 10진수&lt;/li&gt;
&lt;li&gt;%x: 소문자 16진수&lt;/li&gt;
&lt;li&gt;%X: 대문자 16진수&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;%x는 계산 결과를 바꾸는 연산자가 아니라, &lt;b&gt;같은 값을 16진수 모양으로 보여주는 출력 규칙&lt;/b&gt;이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시험 직전 10줄 암기&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&amp;amp;a는 주소, *p는 그 주소의 값&lt;/li&gt;
&lt;li&gt;int *p = &amp;amp;a이면 *p와 a는 같은 공간&lt;/li&gt;
&lt;li&gt;arr[i] == *(arr+i)&lt;/li&gt;
&lt;li&gt;p+1은 자료형 한 칸 이동&lt;/li&gt;
&lt;li&gt;&amp;lt;&amp;lt; n은 양수 기준 &amp;times;2ⁿ&lt;/li&gt;
&lt;li&gt;&amp;gt;&amp;gt; n은 양수 기준 &amp;divide;2ⁿ의 몫&lt;/li&gt;
&lt;li&gt;XOR은 다르면 1&lt;/li&gt;
&lt;li&gt;~x = -(x+1)&lt;/li&gt;
&lt;li&gt;16진수 한 자리 = 2진수 4비트&lt;/li&gt;
&lt;li&gt;우선순위는 최단산시관비논삼대콤&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;ailtchrm-ai-chat&quot; style=&quot;color-scheme: initial; forced-color-adjust: initial; math-depth: initial; position-anchor: initial; text-size-adjust: initial; appearance: initial; color: initial; font: initial; font-palette: initial; font-synthesis: initial; position-area: initial; text-orientation: initial; text-rendering: initial; text-spacing-trim: initial; -webkit-font-smoothing: initial; -webkit-locale: initial; -webkit-text-orientation: initial; -webkit-writing-mode: initial; writing-mode: initial; zoom: initial; accent-color: initial; place-content: initial; place-items: initial; place-self: initial; alignment-baseline: initial; anchor-name: initial; anchor-scope: initial; animation-composition: initial; animation: initial; animation-trigger: initial; app-region: initial; aspect-ratio: initial; backdrop-filter: initial; backface-visibility: initial; background: initial; background-blend-mode: initial; baseline-shift: initial; baseline-source: initial; block-size: initial; border-block: initial; border: initial; border-radius: initial; border-collapse: initial; border-end-end-radius: initial; border-end-start-radius: initial; border-inline: initial; border-shape: initial; border-start-end-radius: initial; border-start-start-radius: initial; box-decoration-break: initial; box-shadow: initial; break-after: initial; break-before: initial; break-inside: initial; buffered-rendering: initial; caption-side: initial; caret-animation: initial; caret-color: initial; caret-shape: initial; clear: initial; clip: initial; clip-path: initial; clip-rule: initial; color-interpolation: initial; color-interpolation-filters: initial; color-rendering: initial; columns: initial; column-fill: initial; gap: initial; rule-break: initial; rule: initial; rule-inset: initial; rule-visibility-items: initial; column-span: initial; contain: initial; contain-intrinsic-block-size: initial; contain-intrinsic-size: initial; contain-intrinsic-inline-size: initial; container: initial; content: initial; content-visibility: initial; corner-shape: initial; corner-block-end-shape: initial; corner-block-start-shape: initial; counter-increment: initial; counter-reset: initial; counter-set: initial; cursor: initial; cx: initial; cy: initial; d: initial; dominant-baseline: initial; dynamic-range-limit: initial; empty-cells: initial; field-sizing: initial; fill: initial; fill-opacity: initial; fill-rule: initial; filter: initial; flex: initial; flex-wrap: initial; float: initial; flood-color: initial; flood-opacity: initial; grid: initial; grid-area: initial; height: initial; hyphenate-character: initial; hyphenate-limit-chars: initial; hyphens: initial; image-orientation: initial; image-rendering: initial; initial-letter: initial; inline-size: initial; inset-block: initial; inset-inline: initial; interactivity: initial; interest-delay: initial; interpolate-size: initial; isolation: initial; left: initial; letter-spacing: initial; lighting-color: initial; line-break: initial; list-style: initial; margin-block: initial; margin: initial; margin-inline: initial; marker: initial; mask: initial; mask-type: initial; math-shift: initial; math-style: initial; max-block-size: initial; max-inline-size: initial; max-width: initial; min-block-size: initial; min-height: initial; min-inline-size: initial; min-width: initial; mix-blend-mode: initial; object-fit: initial; object-position: initial; object-view-box: initial; offset: initial; opacity: initial; order: initial; orphans: initial; outline: initial; outline-offset: initial; overflow-anchor: initial; overflow-block: initial; overflow-clip-margin: initial; overflow-inline: initial; overflow-wrap: initial; overlay: initial; overscroll-behavior-block: initial; overscroll-behavior-inline: initial; overscroll-behavior: initial; padding-block: initial; padding: initial; padding-inline: initial; page: initial; page-orientation: initial; paint-order: initial; perspective: initial; perspective-origin: initial; position-try: initial; position-visibility: initial; print-color-adjust: initial; quotes: initial; r: initial; reading-flow: initial; reading-order: initial; resize: initial; rotate: initial; ruby-align: initial; ruby-position: initial; rule-overlap: initial; rx: initial; ry: initial; scale: initial; scroll-behavior: initial; scroll-initial-target: initial; scroll-margin-block: initial; scroll-margin: initial; scroll-margin-inline: initial; scroll-marker-group: initial; scroll-padding-block: initial; scroll-padding: initial; scroll-padding-inline: initial; scroll-snap-align: initial; scroll-snap-stop: initial; scroll-snap-type: initial; scroll-target-group: initial; scroll-timeline: initial; scrollbar-color: initial; scrollbar-gutter: initial; scrollbar-width: initial; shape-image-threshold: initial; shape-margin: initial; shape-outside: initial; shape-rendering: initial; size: initial; speak: initial; stop-color: initial; stop-opacity: initial; stroke: initial; stroke-dasharray: initial; stroke-dashoffset: initial; stroke-linecap: initial; stroke-linejoin: initial; stroke-miterlimit: initial; stroke-opacity: initial; stroke-width: initial; tab-size: initial; table-layout: initial; text-align: initial; text-align-last: initial; text-anchor: initial; text-autospace: initial; text-box: initial; text-combine-upright: initial; text-decoration: initial; text-decoration-skip-ink: initial; text-emphasis: initial; text-emphasis-position: initial; text-indent: initial; text-justify: initial; text-overflow: initial; text-shadow: initial; text-transform: initial; text-underline-offset: initial; text-underline-position: initial; text-wrap: initial; timeline-scope: initial; timeline-trigger: initial; touch-action: initial; transform: initial; transform-box: initial; transform-origin: initial; transform-style: initial; transition: initial; translate: initial; trigger-scope: initial; user-select: initial; vector-effect: initial; vertical-align: initial; view-timeline: initial; view-transition-class: initial; view-transition-group: initial; view-transition-name: initial; view-transition-scope: initial; visibility: initial; border-spacing: initial; -webkit-box-align: initial; -webkit-box-decoration-break: initial; -webkit-box-direction: initial; -webkit-box-flex: initial; -webkit-box-ordinal-group: initial; -webkit-box-orient: initial; -webkit-box-pack: initial; -webkit-box-reflect: initial; -webkit-line-break: initial; -webkit-line-clamp: initial; -webkit-mask-box-image: initial; -webkit-rtl-ordering: initial; -webkit-ruby-position: initial; -webkit-tap-highlight-color: initial; -webkit-text-combine: initial; -webkit-text-decorations-in-effect: initial; -webkit-text-fill-color: initial; -webkit-text-security: initial; -webkit-text-stroke: initial; -webkit-user-drag: initial; white-space-collapse: initial; widows: initial; width: initial; will-change: initial; word-break: initial; word-spacing: initial; x: initial; y: initial; pointer-events: none !important; display: flex !important; box-sizing: border-box; position: fixed !important; top: 0px !important; right: 0px !important; bottom: 0px !important; max-height: 100% !important; z-index: 2000000000 !important; overflow: hidden; flex-direction: column !important;&quot;&gt;&amp;nbsp;&lt;/div&gt;</description>
      <category>AI/정보처리기사_스터디</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/110</guid>
      <comments>https://onethingflow.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC%EC%88%98%EC%A0%9C%EB%B9%842%EC%9D%BC%EC%B0%A8#entry110comment</comments>
      <pubDate>Tue, 14 Jul 2026 09:13:04 +0900</pubDate>
    </item>
    <item>
      <title>Day 8) 프로그래머스 조건문&amp;middot;문자열: 논리 연산, 주사위 게임 3, 문자열 만들기, 9로 나눈 나머지</title>
      <link>https://onethingflow.tistory.com/entry/Day-8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%A1%B0%EA%B1%B4%EB%AC%B8%C2%B7%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%85%BC%EB%A6%AC-%EC%97%B0%EC%82%B0-%EC%A3%BC%EC%82%AC%EC%9C%84-%EA%B2%8C%EC%9E%84-3-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%A7%8C%EB%93%A4%EA%B8%B0-9%EB%A1%9C-%EB%82%98%EB%88%88-%EB%82%98%EB%A8%B8%EC%A7%80</link>
      <description>&lt;!--
티스토리 제목 추천:
Day 8) 프로그래머스 조건문·문자열: 논리 연산, 주사위 게임 3, 문자열 만들기, 9로 나눈 나머지

메타 설명 추천:
프로그래머스 코딩 기초 트레이닝 Day 8 조건문, 문자열 문제인 간단한 논리 연산, 주사위 게임 3, 글자 이어 붙여 문자열 만들기, 9로 나눈 나머지, 문자열 여러 번 뒤집기를 파이썬으로 풀며 논리 연산자, 빈도수, join, map, 슬라이싱 실수를 정리했습니다.

태그 추천:
프로그래머스, 코딩테스트, 파이썬, 조건문, 문자열, 코딩기초트레이닝, 간단한논리연산, 주사위게임3, 글자이어붙여문자열만들기, 9로나눈나머지, 문자열뒤집기
--&gt;

&lt;article style=&quot;max-width:780px;margin:0 auto;line-height:1.86;font-size:17px;color:#222;word-break:keep-all;&quot;&gt;
  &lt;section style=&quot;margin:0 0 1.5em;padding:1.35em 1.4em;border:1px solid #dde6f2;border-radius:8px;background:linear-gradient(135deg,#f7fbff 0%,#fff 62%,#fff7ed 100%);&quot;&gt;
    &lt;p style=&quot;margin:0 0 .8em;display:inline-block;padding:.25em .7em;border:1px solid #d9e4f2;border-radius:999px;background:#fff;font-size:.84em;font-weight:700;color:#385174;&quot;&gt;Day 8 코딩테스트 공부 기록&lt;/p&gt;
    &lt;h1 style=&quot;margin:.1em 0 .72em;font-size:2em;line-height:1.28;font-weight:800;color:#111;&quot;&gt;프로그래머스 Day 8 조건문·문자열: 논리 연산부터 문자열 뒤집기까지&lt;/h1&gt;
    &lt;p style=&quot;margin:0 0 1em;font-size:1.08em;color:#343b46;&quot;&gt;이번 Day 8은 조건문과 문자열을 함께 다루는 문제들이었습니다. 처음에는 문제가 짧아 보여도 막상 풀어보면 &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;, &lt;code&gt;=&lt;/code&gt;와 &lt;code&gt;==&lt;/code&gt;, 문자열 누적, 슬라이싱, 리스트 변환처럼 헷갈리는 지점이 계속 나왔습니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;특히 문자열 문제는 “문자열은 리스트처럼 중간을 바로 바꿀 수 없다”는 점을 이해하는 것이 중요했습니다. 그래서 이번 글은 정답 코드만 적기보다, 처음 헷갈린 코드와 왜 고쳐야 하는지를 같이 정리했습니다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;div style=&quot;display:grid;grid-template-columns:repeat(3,1fr);gap:.85em;margin:1.35em 0;&quot;&gt;
    &lt;div style=&quot;border:1px solid #e3e8ef;border-radius:8px;background:#fff;padding:1em;&quot;&gt;
      &lt;span style=&quot;display:block;font-size:.82em;color:#687182;margin-bottom:.25em;&quot;&gt;핵심 1&lt;/span&gt;
      &lt;strong style=&quot;display:block;font-size:1.04em;color:#101418;line-height:1.36;&quot;&gt;논리 연산자 그대로 쓰기&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div style=&quot;border:1px solid #e3e8ef;border-radius:8px;background:#fff;padding:1em;&quot;&gt;
      &lt;span style=&quot;display:block;font-size:.82em;color:#687182;margin-bottom:.25em;&quot;&gt;핵심 2&lt;/span&gt;
      &lt;strong style=&quot;display:block;font-size:1.04em;color:#101418;line-height:1.36;&quot;&gt;빈도수로 조건 나누기&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div style=&quot;border:1px solid #e3e8ef;border-radius:8px;background:#fff;padding:1em;&quot;&gt;
      &lt;span style=&quot;display:block;font-size:.82em;color:#687182;margin-bottom:.25em;&quot;&gt;핵심 3&lt;/span&gt;
      &lt;strong style=&quot;display:block;font-size:1.04em;color:#101418;line-height:1.36;&quot;&gt;join과 슬라이싱 활용&lt;/strong&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;blockquote style=&quot;margin:1.55em 0;padding:.95em 1.15em;background:#fff9e8;border-left:4px solid #f2b705;border-radius:8px;font-size:1.06em;font-weight:800;color:#584500;&quot;&gt;
    Day 8의 핵심은 “문제 문장을 파이썬 문법으로 정확히 옮기는 것”이었습니다.
  &lt;/blockquote&gt;

  &lt;section style=&quot;margin:1.6em 0;padding:1em 1.1em;border:1px solid #e2e8f0;border-radius:8px;background:#fbfdff;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 .65em;font-size:1.18em;line-height:1.45;font-weight:800;color:#111;&quot;&gt;이 글의 풀이 순서&lt;/h2&gt;
    &lt;ol style=&quot;margin:0 0 0 1.15em;padding:0;&quot;&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;문제 및 프로그래머스 공식 링크&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;내 풀이 또는 처음 헷갈린 코드&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;설명 및 잘못된 점&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;기본 수정 풀이&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;더 간단한 풀이와 설명&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;입출력 예로 검산하기&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/section&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;1. 문제 및 프로그래머스 공식 링크&lt;/h2&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;이번 글에서 정리한 문제는 프로그래머스 코딩 기초 트레이닝 Day 8의 조건문, 문자열 문제입니다.&lt;/p&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;&quot;&gt;
    &lt;table style=&quot;width:100%;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;프로그래머스 Day 8 문제 링크와 핵심 개념&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;문제&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;공식 링크&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;핵심 개념&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;간단한 논리 연산&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181917&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;boolean, and, or&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;주사위 게임 3&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181916&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;조건 분기, 빈도수&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;글자 이어 붙여 문자열 만들기&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181915&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;인덱싱, 문자열 누적, join&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;9로 나눈 나머지&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181914&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;문자열 순회, int, map&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;문자열 여러 번 뒤집기&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181913&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;슬라이싱, 리스트 변환, 구간 뒤집기&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;2. 간단한 논리 연산: 수식을 그대로 코드로 옮기기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;x1&lt;/code&gt;, &lt;code&gt;x2&lt;/code&gt;, &lt;code&gt;x3&lt;/code&gt;, &lt;code&gt;x4&lt;/code&gt;가 주어질 때 &lt;code&gt;(x1 or x2) and (x3 or x4)&lt;/code&gt;의 결과를 반환하면 됩니다. 문제 지문에서는 &lt;code&gt;∨&lt;/code&gt;가 OR, &lt;code&gt;∧&lt;/code&gt;가 AND를 뜻합니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;처음 헷갈린 코드&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(x1, x2, x3, x4):
    answer = True

    if a == True and b == Ture:
        a ∨ b = True
        a ∧ b = True
    elif a == True and b == False:
        a ∨ b = False
        a ∧ b = False

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;잘못된 점&lt;/h3&gt;
  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;Ture&lt;/code&gt;는 오타입니다. 파이썬에서는 &lt;code&gt;True&lt;/code&gt;처럼 정확히 써야 합니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;함수 입력은 &lt;code&gt;x1&lt;/code&gt;, &lt;code&gt;x2&lt;/code&gt;, &lt;code&gt;x3&lt;/code&gt;, &lt;code&gt;x4&lt;/code&gt;인데 코드 안에서는 정의되지 않은 &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;를 사용했습니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;파이썬에서는 &lt;code&gt;∨&lt;/code&gt;, &lt;code&gt;∧&lt;/code&gt; 대신 &lt;code&gt;or&lt;/code&gt;, &lt;code&gt;and&lt;/code&gt;를 씁니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;a ∨ b = True&lt;/code&gt;처럼 연산 결과에 값을 대입할 수 없습니다. 결과를 변수에 담거나 바로 반환해야 합니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;OR는 둘 중 하나만 &lt;code&gt;True&lt;/code&gt;여도 &lt;code&gt;True&lt;/code&gt;입니다. 진리표를 직접 구현하기보다 파이썬 연산자를 그대로 쓰는 편이 정확합니다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;기본 수정 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(x1, x2, x3, x4):
    return (x1 or x2) and (x3 or x4)&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;문제의 식을 그대로 파이썬 문법으로 바꾸면 됩니다. 괄호를 넣어두면 어떤 부분을 먼저 계산하는지 눈에 잘 들어옵니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;더 짧은 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(x1, x2, x3, x4):
    return (x1 | x2) &amp;amp; (x3 | x4)&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;|&lt;/code&gt;와 &lt;code&gt;&amp;amp;&lt;/code&gt;도 boolean 값에서 OR, AND처럼 동작합니다. 다만 일반적인 조건식에서는 단축 평가가 되는 &lt;code&gt;or&lt;/code&gt;, &lt;code&gt;and&lt;/code&gt;가 더 익숙하고 안전합니다. 이 문제처럼 단순한 boolean 변수만 다룰 때는 위 풀이도 가능합니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;3. 주사위 게임 3: 숫자 종류와 등장 횟수로 나누기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;네 개의 주사위 숫자 &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, &lt;code&gt;c&lt;/code&gt;, &lt;code&gt;d&lt;/code&gt;가 주어집니다. 네 숫자가 모두 같은지, 3개만 같은지, 2개씩 같은지, 2개만 같은지, 모두 다른지에 따라 점수 공식이 달라집니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;처음 작성한 코드&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(a, b, c, d):
    answer = 0
    dice = [a, b, c, d]

    if len(set(dice)) == 1:
        answer == 1111 × a
    elif len(set(dice)) == 4:
        answer == min(set(dice))
    elif len(set(dice)) == 2:
        for i in range(1, 7):
            if dice.count(i) == 2:
                p, q = i
                answer = (i) × |p - q|

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;잘못된 점&lt;/h3&gt;
  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;answer == 1111 * a&lt;/code&gt;는 비교입니다. 값을 저장하려면 &lt;code&gt;answer = 1111 * a&lt;/code&gt;처럼 &lt;code&gt;=&lt;/code&gt; 하나를 써야 합니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;파이썬에서 곱하기는 &lt;code&gt;×&lt;/code&gt;가 아니라 &lt;code&gt;*&lt;/code&gt;입니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;절댓값은 수학 기호 &lt;code&gt;|p - q|&lt;/code&gt;가 아니라 &lt;code&gt;abs(p - q)&lt;/code&gt;로 계산합니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;p, q = i&lt;/code&gt;는 숫자 하나를 변수 두 개에 나누어 담으려는 코드라 에러가 납니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;len(set(dice)) == 2&lt;/code&gt;일 때는 &lt;code&gt;3개 + 1개&lt;/code&gt;와 &lt;code&gt;2개 + 2개&lt;/code&gt;를 다시 구분해야 합니다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;빈도수 배열을 활용한 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(a, b, c, d):
    dice = [a, b, c, d]
    counts = [dice.count(x) for x in dice]

    if max(counts) == 4:
        return 1111 * a

    elif max(counts) == 3:
        p = dice[counts.index(3)]
        q = dice[counts.index(1)]
        return (10 * p + q) ** 2

    elif max(counts) == 2:
        if min(counts) == 2:
            p, q = set(dice)
            return (p + q) * abs(p - q)
        else:
            q, r = [dice[i] for i in range(4) if counts[i] == 1]
            return q * r

    else:
        return min(dice)&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;counts = [dice.count(x) for x in dice]&lt;/code&gt;는 각 주사위 숫자가 전체에서 몇 번 나왔는지를 같은 위치에 저장합니다. 예를 들어 &lt;code&gt;[2, 5, 2, 6]&lt;/code&gt;이면 &lt;code&gt;counts&lt;/code&gt;는 &lt;code&gt;[2, 1, 2, 1]&lt;/code&gt;이 됩니다. 그래서 &lt;code&gt;max(counts)&lt;/code&gt;만 봐도 4개가 같은지, 3개가 같은지, 2개가 같은지 큰 분기를 나눌 수 있습니다.&lt;/p&gt;

  &lt;section style=&quot;margin:1.35em 0;padding:1em 1.1em;border:1px solid #f1d7d7;border-radius:8px;background:#fffafa;&quot;&gt;
    &lt;strong style=&quot;display:block;margin:0 0 .45em;color:#6b1d1d;&quot;&gt;eval은 피하는 편이 좋다&lt;/strong&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;다른 풀이에서 &lt;code&gt;eval('*'.join(...))&lt;/code&gt;처럼 문자열을 코드로 실행하는 방식이 보일 수 있습니다. 하지만 이 문제에서는 1번 나온 두 숫자 &lt;code&gt;q&lt;/code&gt;, &lt;code&gt;r&lt;/code&gt;을 뽑아 &lt;code&gt;q * r&lt;/code&gt;로 직접 계산하면 충분합니다. &lt;code&gt;eval()&lt;/code&gt;은 문자열을 실제 코드처럼 실행하기 때문에 안전성과 가독성 면에서 추천하지 않습니다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;Counter를 활용한 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;from collections import Counter

def solution(a, b, c, d):
    dice = [a, b, c, d]
    counts = Counter(dice).most_common()

    if len(counts) == 1:
        p = counts[0][0]
        return 1111 * p

    elif len(counts) == 2:
        if counts[0][1] == 3:
            p = counts[0][0]
            q = counts[1][0]
            return (10 * p + q) ** 2
        else:
            p = counts[0][0]
            q = counts[1][0]
            return (p + q) * abs(p - q)

    elif len(counts) == 3:
        q = counts[1][0]
        r = counts[2][0]
        return q * r

    else:
        return min(dice)&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;Counter(dice).most_common()&lt;/code&gt;은 숫자와 등장 횟수를 많이 나온 순서대로 정리해 줍니다. 주사위 게임 3처럼 “몇 번 등장했는가”가 핵심인 문제에서는 조건문을 훨씬 읽기 좋게 만들 수 있습니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;4. 글자 이어 붙여 문자열 만들기: 인덱스에 해당하는 글자만 모으기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;my_string&lt;/code&gt;에서 &lt;code&gt;index_list&lt;/code&gt;에 들어 있는 인덱스의 글자를 순서대로 꺼내 이어 붙이면 됩니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;내 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_string, index_list):
    answer = ''

    for i in index_list:
        answer += my_string[i]

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;이 풀이는 정답입니다. &lt;code&gt;answer&lt;/code&gt;가 빈 문자열이기 때문에 &lt;code&gt;answer += my_string[i]&lt;/code&gt;로 문자를 이어 붙일 수 있습니다. 다만 여기서 헷갈렸던 부분은 “왜 &lt;code&gt;append()&lt;/code&gt;는 안 되고 &lt;code&gt;+&lt;/code&gt;는 되는가?”였습니다.&lt;/p&gt;

  &lt;section style=&quot;margin:1.35em 0;padding:1em 1.1em;border:1px solid #dbe5f5;border-radius:8px;background:#f8fbff;&quot;&gt;
    &lt;strong style=&quot;display:block;margin:0 0 .45em;color:#172033;&quot;&gt;문자열과 리스트의 차이&lt;/strong&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;문자열에는 &lt;code&gt;append()&lt;/code&gt;가 없습니다. &lt;code&gt;append()&lt;/code&gt;는 리스트 전용 메서드입니다. 문자열을 하나씩 붙일 때는 &lt;code&gt;+&lt;/code&gt;를 사용할 수 있지만, 반복 횟수가 많아질수록 매번 새 문자열을 만드는 방식이라 비효율적일 수 있습니다. 그래서 여러 글자를 모을 때는 리스트에 담고 마지막에 &lt;code&gt;join()&lt;/code&gt;으로 합치는 패턴을 자주 씁니다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;리스트와 join을 활용한 기본 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_string, index_list):
    answer = []

    for i in index_list:
        answer.append(my_string[i])

    return ''.join(answer)&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;더 간단한 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_string, index_list):
    return ''.join(my_string[idx] for idx in index_list)&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;index_list&lt;/code&gt;에서 인덱스 &lt;code&gt;idx&lt;/code&gt;를 하나씩 꺼내고, &lt;code&gt;my_string[idx]&lt;/code&gt;로 해당 위치의 글자를 가져옵니다. 그렇게 나온 글자들을 &lt;code&gt;''.join(...)&lt;/code&gt;으로 빈틈없이 이어 붙이면 됩니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;5. 9로 나눈 나머지: 큰 숫자는 문자열 그대로 순회하기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;문자열 &lt;code&gt;number&lt;/code&gt;로 매우 큰 수가 주어집니다. 숫자를 9로 나눈 나머지는 각 자리 숫자의 합을 9로 나눈 나머지와 같으므로, 한 글자씩 정수로 바꿔 더한 뒤 9로 나누면 됩니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;내 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(number):
    a = list(number)
    answer = 0

    for char in a:
        answer += int(char)
        ans = answer % 9

    return ans&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;보완할 점&lt;/h3&gt;
  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;list(number)&lt;/code&gt;는 없어도 됩니다. 문자열은 그대로 &lt;code&gt;for char in number&lt;/code&gt;처럼 순회할 수 있습니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;ans = answer % 9&lt;/code&gt;를 반복문 안에서 매번 계산할 필요가 없습니다. 모든 자리 숫자를 더한 뒤 마지막에 한 번만 계산하면 됩니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;문제에서 &lt;code&gt;number&lt;/code&gt;의 길이가 최대 100,000이므로, &lt;code&gt;int(number) % 9&lt;/code&gt;처럼 전체 문자열을 한 번에 정수로 바꾸는 방식은 피하는 편이 안전합니다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;기본 수정 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(number):
    answer = 0

    for char in number:
        answer += int(char)

    return answer % 9&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;더 간단한 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(number):
    return sum(map(int, number)) % 9&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;map(int, number)&lt;/code&gt;는 문자열의 각 글자에 &lt;code&gt;int&lt;/code&gt;를 적용합니다. 예를 들어 &lt;code&gt;&quot;123&quot;&lt;/code&gt;이면 &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;으로 바뀌고, &lt;code&gt;sum()&lt;/code&gt;이 이 값들을 모두 더합니다. 마지막으로 &lt;code&gt;% 9&lt;/code&gt;를 붙이면 9로 나눈 나머지가 됩니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;6. 문자열 여러 번 뒤집기: 구간을 자르고 뒤집고 다시 붙이기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;queries&lt;/code&gt;의 각 원소는 &lt;code&gt;[s, e]&lt;/code&gt;입니다. 각 쿼리마다 &lt;code&gt;my_string&lt;/code&gt;의 &lt;code&gt;s&lt;/code&gt;번 인덱스부터 &lt;code&gt;e&lt;/code&gt;번 인덱스까지를 뒤집어야 합니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;처음 작성한 코드&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_string, queries):
    for char in queries:
        for s, e in char:
            my_string[s:e] == my_string[e:s]

    return my_string&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;잘못된 점&lt;/h3&gt;
  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;queries&lt;/code&gt;는 &lt;code&gt;[[2, 3], [0, 7]]&lt;/code&gt;처럼 들어오므로 &lt;code&gt;for s, e in queries:&lt;/code&gt; 한 번으로 꺼내면 됩니다. 이중 반복문을 쓰면 숫자 하나를 &lt;code&gt;s&lt;/code&gt;, &lt;code&gt;e&lt;/code&gt;로 나누려 해서 에러가 납니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;==&lt;/code&gt;는 비교입니다. 문자열을 바꾸려면 새 문자열을 만들어 &lt;code&gt;=&lt;/code&gt;로 다시 저장해야 합니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;my_string[e:s]&lt;/code&gt;라고 쓴다고 문자열이 거꾸로 뒤집히지 않습니다. 뒤집기는 &lt;code&gt;[::-1]&lt;/code&gt;을 사용합니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;슬라이싱에서 끝 인덱스는 포함되지 않으므로 &lt;code&gt;e&lt;/code&gt;까지 포함하려면 &lt;code&gt;s:e+1&lt;/code&gt;로 잘라야 합니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;문자열은 불변 자료형이라 중간 일부만 바로 교체할 수 없습니다. 앞부분, 뒤집은 중간 부분, 뒷부분을 새로 이어 붙여야 합니다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;기본 수정 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_string, queries):
    for s, e in queries:
        my_string = my_string[:s] + my_string[s:e+1][::-1] + my_string[e+1:]

    return my_string&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;핵심은 문자열을 세 조각으로 나누는 것입니다. &lt;code&gt;my_string[:s]&lt;/code&gt;는 앞부분, &lt;code&gt;my_string[s:e+1][::-1]&lt;/code&gt;는 뒤집을 부분, &lt;code&gt;my_string[e+1:]&lt;/code&gt;는 뒷부분입니다. 이 세 조각을 다시 붙이면 쿼리 하나가 처리됩니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;리스트로 바꾼 더 깔끔한 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(my_string, queries):
    answer = list(my_string)

    for s, e in queries:
        answer[s:e+1] = answer[s:e+1][::-1]

    return ''.join(answer)&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;문자열은 직접 수정할 수 없지만 리스트는 구간을 통째로 바꿀 수 있습니다. 그래서 처음에 &lt;code&gt;list(my_string)&lt;/code&gt;으로 바꾼 뒤, &lt;code&gt;answer[s:e+1]&lt;/code&gt; 구간을 뒤집은 리스트로 교체하고, 마지막에 &lt;code&gt;''.join(answer)&lt;/code&gt;로 다시 문자열로 합칩니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;7. 입출력 예로 빠르게 검산하기&lt;/h2&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;&quot;&gt;
    &lt;table style=&quot;width:100%;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;Day 8 문제별 빠른 검산 예시&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;문제&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;예시 입력&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;기대 결과&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;간단한 논리 연산&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;False, True, True, True&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;True&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;주사위 게임 3&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;4, 1, 4, 4&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;1681&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;글자 이어 붙여 문자열 만들기&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;&quot;zpiaz&quot;, [1, 2, 0, 0, 3]&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;&quot;pizza&quot;&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;9로 나눈 나머지&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;&quot;78720646226947352489&quot;&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;문자열 여러 번 뒤집기&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;&quot;rermgorpsam&quot;, [[2,3],[0,7],[5,9],[6,10]]&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;&quot;programmers&quot;&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;8. 실수 방지 체크리스트&lt;/h2&gt;

  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;=&lt;/code&gt;는 대입, &lt;code&gt;==&lt;/code&gt;는 비교다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;논리 연산은 수학 기호 대신 &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;를 먼저 떠올린다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;값이 몇 번 등장했는지 볼 때는 &lt;code&gt;count()&lt;/code&gt;나 &lt;code&gt;Counter&lt;/code&gt;를 활용한다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;문자열에는 &lt;code&gt;append()&lt;/code&gt;가 없다. 여러 글자를 모을 때는 리스트에 담고 &lt;code&gt;join()&lt;/code&gt;을 쓴다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;문자열을 한 글자씩 순회할 때 굳이 &lt;code&gt;list()&lt;/code&gt;로 바꾸지 않아도 된다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;슬라이싱의 끝 인덱스는 포함되지 않는다. &lt;code&gt;e&lt;/code&gt;까지 포함하려면 &lt;code&gt;e+1&lt;/code&gt;을 쓴다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;문자열 뒤집기는 &lt;code&gt;[::-1]&lt;/code&gt;을 사용한다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;문자열은 불변 자료형이므로, 여러 번 수정해야 하면 리스트로 바꾸는 방법을 고려한다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;eval()&lt;/code&gt;은 문자열을 코드로 실행하므로, 코딩테스트 풀이에서도 가능한 한 피한다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;9. 같이 보면 좋은 글&lt;/h2&gt;

  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;파이썬 논리 연산자 정리&lt;/strong&gt;: &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;, 단축 평가가 헷갈릴 때 같이 보면 좋습니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;파이썬 문자열 슬라이싱&lt;/strong&gt;: &lt;code&gt;s:e+1&lt;/code&gt;, &lt;code&gt;[::-1]&lt;/code&gt; 패턴을 연습하기 좋습니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;join과 문자열 누적 차이&lt;/strong&gt;: 문자열을 여러 번 이어 붙이는 문제에서 자주 나옵니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;Counter와 빈도수 문제&lt;/strong&gt;: 주사위 게임 3처럼 등장 횟수로 조건을 나누는 문제와 연결됩니다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;마무리&lt;/h2&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;Day 8은 조건문과 문자열 기본기를 한 번에 점검하기 좋은 날이었습니다. 논리 연산은 문제의 식을 그대로 코드로 옮기면 되고, 주사위 문제는 숫자 종류와 등장 횟수로 나누면 복잡한 조건도 정리됩니다.&lt;/p&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;문자열 문제에서는 &lt;code&gt;append()&lt;/code&gt;, &lt;code&gt;join()&lt;/code&gt;, &lt;code&gt;map()&lt;/code&gt;, 슬라이싱을 언제 쓰는지 구분하는 연습이 중요했습니다. 특히 문자열은 직접 수정할 수 없기 때문에, 구간을 여러 번 바꾸는 문제에서는 리스트로 변환하는 풀이가 훨씬 깔끔하게 느껴졌습니다.&lt;/p&gt;
&lt;/article&gt;</description>
      <category>AI/Coding_Test</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/109</guid>
      <comments>https://onethingflow.tistory.com/entry/Day-8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%A1%B0%EA%B1%B4%EB%AC%B8%C2%B7%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%85%BC%EB%A6%AC-%EC%97%B0%EC%82%B0-%EC%A3%BC%EC%82%AC%EC%9C%84-%EA%B2%8C%EC%9E%84-3-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%A7%8C%EB%93%A4%EA%B8%B0-9%EB%A1%9C-%EB%82%98%EB%88%88-%EB%82%98%EB%A8%B8%EC%A7%80#entry109comment</comments>
      <pubDate>Mon, 13 Jul 2026 16:15:07 +0900</pubDate>
    </item>
    <item>
      <title>Day 7) 프로그래머스 반복문: 구간 쿼리, 배열 만들기, 콜라츠, 스택 풀이 정리</title>
      <link>https://onethingflow.tistory.com/entry/Day-7-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%B0%98%EB%B3%B5%EB%AC%B8-%EA%B5%AC%EA%B0%84-%EC%BF%BC%EB%A6%AC-%EB%B0%B0%EC%97%B4-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EC%BD%9C%EB%9D%BC%EC%B8%A0-%EC%8A%A4%ED%83%9D-%ED%92%80%EC%9D%B4-%EC%A0%95%EB%A6%AC</link>
      <description>&lt;!--
티스토리 제목 추천:
Day 7) 프로그래머스 반복문: 구간 쿼리, 배열 만들기, 콜라츠, 스택 풀이 정리

메타 설명 추천:
프로그래머스 코딩 기초 트레이닝 Day 7 반복문 문제인 수열과 구간 쿼리 4, 배열 만들기 2, 카운트 업, 콜라츠 수열 만들기, 배열 만들기 4를 파이썬으로 풀며 range, while, 종료 조건, append, pop, 모노토닉 스택 실수를 정리했습니다.

태그 추천:
프로그래머스, 코딩테스트, 파이썬, 반복문, 코딩기초트레이닝, 수열과구간쿼리4, 배열만들기2, 카운트업, 콜라츠수열, 배열만들기4, 모노토닉스택
--&gt;
&lt;article style=&quot;max-width: 780px; margin: 0 auto; line-height: 1.86; font-size: 17px; color: #222; word-break: keep-all;&quot;&gt;
&lt;section style=&quot;margin: 0 0 1.5em; padding: 1.35em 1.4em; border: 1px solid #dde6f2; border-radius: 8px; background: linear-gradient(135deg,#f7fbff 0%,#fff 62%,#fff7ed 100%);&quot;&gt;
&lt;p style=&quot;margin: 0 0 .8em; display: inline-block; padding: .25em .7em; border: 1px solid #d9e4f2; border-radius: 999px; background: #fff; font-size: .84em; font-weight: bold; color: #385174;&quot; data-ke-size=&quot;size16&quot;&gt;Day 7 코딩테스트 공부 기록&lt;/p&gt;
&lt;h1 style=&quot;margin: .1em 0 .72em; font-size: 2em; line-height: 1.28; font-weight: 800; color: #111;&quot;&gt;프로그래머스 반복문: 구간 쿼리, 배열 만들기, 콜라츠, 스택 풀이 정리&lt;/h1&gt;
&lt;p style=&quot;margin: 0 0 1em; font-size: 1.08em; color: #343b46;&quot; data-ke-size=&quot;size16&quot;&gt;이번 Day 7은 반복문을 중심으로 정리했습니다. &lt;code&gt;for&lt;/code&gt;로 범위를 돌고, &lt;code&gt;while&lt;/code&gt;로 조건이 끝날 때까지 반복하고, 리스트에 값을 추가하거나 제거하는 흐름이 계속 나왔습니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;특히 콜라츠 수열 만들기에서는 종료 조건과 정수 나눗셈이 헷갈렸고, 배열 만들기 4에서는 &lt;code&gt;i&lt;/code&gt;, &lt;code&gt;len(arr)&lt;/code&gt;, &lt;code&gt;arr[i]&lt;/code&gt;를 구분하는 부분과 &lt;code&gt;stk.pop()&lt;/code&gt;의 의미가 중요했습니다.&lt;/p&gt;
&lt;/section&gt;
&lt;div style=&quot;display: grid; grid-template-columns: repeat(3,1fr); gap: .85em; margin: 1.35em 0;&quot;&gt;
&lt;div style=&quot;border: 1px solid #e3e8ef; border-radius: 8px; background: #fff; padding: 1em;&quot;&gt;&lt;span style=&quot;display: block; font-size: .82em; color: #687182; margin-bottom: .25em;&quot;&gt;핵심 1&lt;/span&gt; &lt;b&gt;range로 구간 반복하기&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;border: 1px solid #e3e8ef; border-radius: 8px; background: #fff; padding: 1em;&quot;&gt;&lt;span style=&quot;display: block; font-size: .82em; color: #687182; margin-bottom: .25em;&quot;&gt;핵심 2&lt;/span&gt; &lt;b&gt;while 종료 조건 잡기&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;border: 1px solid #e3e8ef; border-radius: 8px; background: #fff; padding: 1em;&quot;&gt;&lt;span style=&quot;display: block; font-size: .82em; color: #687182; margin-bottom: .25em;&quot;&gt;핵심 3&lt;/span&gt; &lt;b&gt;append와 pop으로 스택 다루기&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote style=&quot;margin: 1.55em 0; padding: .95em 1.15em; background: #fff9e8; border-left: 4px solid #f2b705; border-radius: 8px; font-size: 1.06em; font-weight: 800; color: #584500;&quot; data-ke-style=&quot;style1&quot;&gt;반복문 문제는 &amp;ldquo;몇 번 도는가&amp;rdquo;보다 &amp;ldquo;언제 값을 바꾸고, 언제 결과에 넣는가&amp;rdquo;가 더 중요했습니다.&lt;/blockquote&gt;
&lt;section style=&quot;margin: 1.6em 0; padding: 1em 1.1em; border: 1px solid #e2e8f0; border-radius: 8px; background: #fbfdff;&quot;&gt;
&lt;h2 style=&quot;margin: 0 0 .65em; font-size: 1.18em; line-height: 1.45; font-weight: 800; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;이 글의 풀이 순서&lt;/h2&gt;
&lt;ol style=&quot;margin: 0 0 0 1.15em; padding: 0;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;margin: .35em 0;&quot;&gt;문제 및 프로그래머스 공식 링크&lt;/li&gt;
&lt;li style=&quot;margin: .35em 0;&quot;&gt;내 풀이 또는 처음 헷갈린 코드&lt;/li&gt;
&lt;li style=&quot;margin: .35em 0;&quot;&gt;설명 및 잘못된 점&lt;/li&gt;
&lt;li style=&quot;margin: .35em 0;&quot;&gt;기본 수정 풀이&lt;/li&gt;
&lt;li style=&quot;margin: .35em 0;&quot;&gt;더 간단한 풀이와 설명&lt;/li&gt;
&lt;li style=&quot;margin: .35em 0;&quot;&gt;입출력 예로 검산하기&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;1. 문제 및 프로그래머스 공식 링크&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;이번 글에서 정리한 문제는 모두 프로그래머스 코딩 기초 트레이닝 Day 7의 반복문 관련 문제입니다.&lt;/p&gt;
&lt;div style=&quot;overflow-x: auto; margin: 1.25em 0 1.55em;&quot;&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; border: 1px solid #e2e8f0; font-size: .96em; background: #fff;&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption style=&quot;position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0);&quot;&gt;프로그래머스 Day 7 문제 링크와 핵심 개념&lt;/caption&gt;
&lt;thead&gt;
&lt;tr style=&quot;background: #f6f8fb;&quot;&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;문제&lt;/th&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;공식 링크&lt;/th&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;핵심 개념&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;수열과 구간 쿼리 4&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;a style=&quot;color: #2459d6; text-decoration: none; border-bottom: 1px solid rgba(36,89,214,.25);&quot; href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181922&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;중첩 반복문, 인덱스 조건&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;배열 만들기 2&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;a style=&quot;color: #2459d6; text-decoration: none; border-bottom: 1px solid rgba(36,89,214,.25);&quot; href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181921&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;문자열 변환, 조건 필터링&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;카운트 업&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;a style=&quot;color: #2459d6; text-decoration: none; border-bottom: 1px solid rgba(36,89,214,.25);&quot; href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181920&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;range의 끝값 처리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;콜라츠 수열 만들기&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;a style=&quot;color: #2459d6; text-decoration: none; border-bottom: 1px solid rgba(36,89,214,.25);&quot; href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181919&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;while 종료 조건, 정수 나눗셈&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;배열 만들기 4&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;a style=&quot;color: #2459d6; text-decoration: none; border-bottom: 1px solid rgba(36,89,214,.25);&quot; href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181918&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;스택, pop, 오름차순 유지&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;2. 수열과 구간 쿼리 4: 범위 안에서 조건에 맞는 인덱스만 바꾸기&lt;/h2&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;문제 요약&lt;/h3&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;각 쿼리는 &lt;code&gt;[s, e, k]&lt;/code&gt; 형태입니다. 쿼리마다 &lt;code&gt;s&lt;/code&gt;부터 &lt;code&gt;e&lt;/code&gt;까지의 인덱스 &lt;code&gt;i&lt;/code&gt;를 확인하면서, &lt;code&gt;i&lt;/code&gt;가 &lt;code&gt;k&lt;/code&gt;의 배수이면 &lt;code&gt;arr[i]&lt;/code&gt;에 1을 더합니다.&lt;/p&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;기본 풀이&lt;/h3&gt;
&lt;pre class=&quot;matlab&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(arr, queries):
    for s, e, k in queries:
        for i in range(s, e + 1):
            if i % k == 0:
                arr[i] += 1
    return arr&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;설명 및 실수 주의&lt;/h3&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;range(s, e + 1)&lt;/code&gt;을 쓰는 이유는 파이썬의 &lt;code&gt;range()&lt;/code&gt;가 끝값을 포함하지 않기 때문입니다. 문제는 &lt;code&gt;s &amp;lt;= i &amp;lt;= e&lt;/code&gt;라고 했으므로 &lt;code&gt;e&lt;/code&gt;까지 포함하려면 &lt;code&gt;e + 1&lt;/code&gt;을 넣어야 합니다. 또 이 문제에서 배수인지 확인하는 대상은 배열의 값이 아니라 인덱스 &lt;code&gt;i&lt;/code&gt;입니다. 그래서 &lt;code&gt;arr[i] % k&lt;/code&gt;가 아니라 &lt;code&gt;i % k&lt;/code&gt;를 확인합니다.&lt;/p&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;조금 더 짧게 쓰기&lt;/h3&gt;
&lt;pre class=&quot;matlab&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(arr, queries):
    for s, e, k in queries:
        for i in range(s, e + 1):
            arr[i] += int(i % k == 0)
    return arr&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;조건식이 참이면 &lt;code&gt;True&lt;/code&gt;, 거짓이면 &lt;code&gt;False&lt;/code&gt;가 됩니다. 파이썬에서 &lt;code&gt;int(True)&lt;/code&gt;는 1, &lt;code&gt;int(False)&lt;/code&gt;는 0이므로 위처럼 더할 수도 있습니다. 다만 처음 공부할 때는 &lt;code&gt;if&lt;/code&gt;문 풀이가 더 읽기 쉽습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;3. 배열 만들기 2: 숫자를 문자열로 바꿔 0과 5만 확인하기&lt;/h2&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;문제 요약&lt;/h3&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;l&lt;/code&gt; 이상 &lt;code&gt;r&lt;/code&gt; 이하의 정수 중에서 숫자 &lt;code&gt;0&lt;/code&gt;과 &lt;code&gt;5&lt;/code&gt;로만 이루어진 수를 오름차순으로 담아 반환합니다. 조건에 맞는 수가 없다면 &lt;code&gt;[-1]&lt;/code&gt;을 반환합니다.&lt;/p&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;기본 풀이&lt;/h3&gt;
&lt;pre class=&quot;properties&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(l, r):
    answer = []

    for num in range(l, r + 1):
        is_valid = True
        for ch in str(num):
            if ch != '0' and ch != '5':
                is_valid = False
                break

        if is_valid:
            answer.append(num)

    if answer:
        return answer
    return [-1]&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;설명 및 실수 주의&lt;/h3&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;숫자 안의 각 자릿수를 확인하려면 숫자를 문자열로 바꾸는 것이 편합니다. &lt;code&gt;str(num)&lt;/code&gt;으로 바꾸면 각 글자를 &lt;code&gt;for ch in str(num)&lt;/code&gt;처럼 하나씩 확인할 수 있습니다. 조건에 맞지 않는 글자를 발견하면 더 볼 필요가 없으므로 &lt;code&gt;break&lt;/code&gt;로 빠져나옵니다.&lt;/p&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;더 간단한 풀이&lt;/h3&gt;
&lt;pre class=&quot;maxima&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(l, r):
    answer = []

    for num in range(l, r + 1):
        if all(ch in '05' for ch in str(num)):
            answer.append(num)

    return answer if answer else [-1]&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;all()&lt;/code&gt;은 안쪽 조건이 모두 참일 때만 &lt;code&gt;True&lt;/code&gt;를 반환합니다. 그래서 모든 자릿수가 &lt;code&gt;0&lt;/code&gt; 또는 &lt;code&gt;5&lt;/code&gt;인지 한 줄로 확인할 수 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;4. 카운트 업: range의 끝값은 포함되지 않는다&lt;/h2&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;문제 요약&lt;/h3&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;start_num&lt;/code&gt;부터 &lt;code&gt;end_num&lt;/code&gt;까지의 숫자를 차례로 담은 리스트를 반환하는 문제입니다.&lt;/p&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;기본 풀이&lt;/h3&gt;
&lt;pre class=&quot;maxima&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(start_num, end_num):
    answer = []

    for num in range(start_num, end_num + 1):
        answer.append(num)

    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;더 간단한 풀이&lt;/h3&gt;
&lt;pre class=&quot;ruby&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(start_num, end_num):
    return list(range(start_num, end_num + 1))&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;이 문제의 핵심은 &lt;code&gt;end_num + 1&lt;/code&gt;입니다. &lt;code&gt;range(3, 10)&lt;/code&gt;은 3부터 9까지만 만들기 때문에, 10까지 포함하려면 &lt;code&gt;range(3, 11)&lt;/code&gt;처럼 끝값보다 1 큰 값을 넣어야 합니다.&lt;/p&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;5. 콜라츠 수열 만들기: while 종료 조건과 정수 나눗셈&lt;/h2&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;문제 요약&lt;/h3&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;자연수 &lt;code&gt;n&lt;/code&gt;에서 시작해, 짝수이면 2로 나누고 홀수이면 &lt;code&gt;3 * n + 1&lt;/code&gt;로 바꾸는 과정을 반복합니다. 이 과정에서 지나간 모든 수를 리스트에 담아 반환해야 합니다. 마지막에는 반드시 1이 포함되어야 합니다.&lt;/p&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;처음 헷갈린 코드&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(n):
    list = []
    new = 0

    while n == 1:
        n % 2 if n % 2 == 0 else 3 * n + 1
        list.append(new)
        break

    return list&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;설명 및 잘못된 점&lt;/h3&gt;
&lt;ul style=&quot;margin: 0 0 1.25em 1.15em; padding: 0;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;code&gt;list&lt;/code&gt;는 파이썬 내장 이름이므로 변수명으로 쓰지 않는 편이 좋습니다. &lt;code&gt;answer&lt;/code&gt;나 &lt;code&gt;result&lt;/code&gt;가 더 안전합니다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;code&gt;while n == 1&lt;/code&gt;은 처음부터 &lt;code&gt;n&lt;/code&gt;이 1일 때만 실행됩니다. 콜라츠 수열은 1이 될 때까지 반복해야 하므로 &lt;code&gt;while n != 1&lt;/code&gt; 또는 &lt;code&gt;while n &amp;gt; 1&lt;/code&gt;을 써야 합니다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;code&gt;n % 2 if ...&lt;/code&gt;는 값을 계산만 할 뿐 &lt;code&gt;n&lt;/code&gt;에 다시 저장하지 않습니다. &lt;code&gt;n = ...&lt;/code&gt;처럼 대입해야 값이 바뀝니다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;짝수일 때 필요한 것은 나머지 &lt;code&gt;n % 2&lt;/code&gt;가 아니라 몫 &lt;code&gt;n // 2&lt;/code&gt;입니다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;code&gt;break&lt;/code&gt;가 조건 없이 들어가면 반복문이 한 번만 돌고 끝납니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;기본 수정 풀이&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(n):
    answer = [n]

    while n != 1:
        if n % 2 == 0:
            n //= 2
        else:
            n = 3 * n + 1

        answer.append(n)

    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;더 간단한 풀이&lt;/h3&gt;
&lt;pre class=&quot;excel&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(n):
    answer = []

    while n &amp;gt; 1:
        answer.append(n)
        n = n // 2 if n % 2 == 0 else 3 * n + 1

    answer.append(1)
    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;section style=&quot;margin: 1.35em 0; padding: 1em 1.1em; border: 1px solid #e7d7aa; border-radius: 8px; background: #fffaf0;&quot;&gt;&lt;b&gt;/ 와 // 차이&lt;/b&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;/&lt;/code&gt;는 나눗셈 결과를 실수로 만듭니다. 예를 들어 &lt;code&gt;4 / 2&lt;/code&gt;는 &lt;code&gt;2.0&lt;/code&gt;입니다. 반면 &lt;code&gt;//&lt;/code&gt;는 몫을 구해 정수 흐름을 유지합니다. 콜라츠 수열은 정수 수열이므로 &lt;code&gt;n /= 2&lt;/code&gt;보다 &lt;code&gt;n //= 2&lt;/code&gt;가 안전합니다.&lt;/p&gt;
&lt;/section&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;6. 배열 만들기 4: i, len(arr), arr[i]를 구분해야 한다&lt;/h2&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;문제 요약&lt;/h3&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;배열 &lt;code&gt;arr&lt;/code&gt;를 보면서 새 배열 &lt;code&gt;stk&lt;/code&gt;를 만듭니다. &lt;code&gt;stk&lt;/code&gt;가 비었거나 &lt;code&gt;stk[-1] &amp;lt; arr[i]&lt;/code&gt;이면 &lt;code&gt;arr[i]&lt;/code&gt;를 넣고 &lt;code&gt;i&lt;/code&gt;를 1 증가시킵니다. 반대로 &lt;code&gt;stk[-1] &amp;gt;= arr[i]&lt;/code&gt;이면 &lt;code&gt;stk&lt;/code&gt;의 마지막 값을 제거하고 &lt;code&gt;i&lt;/code&gt;는 그대로 둡니다.&lt;/p&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;처음 헷갈린 코드&lt;/h3&gt;
&lt;pre class=&quot;matlab&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(arr):
    stk = []
    i = 0

    while i &amp;lt; len(arr):
        if stk == []:
            stk.arr[i]
            i += 1
        elif stk != [] and stk[-1] &amp;lt; arr[i]:
            stk.append(arr[i])
            i += 1
        else:
            stk.pop()

    return stk&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;설명 및 잘못된 점&lt;/h3&gt;
&lt;ul style=&quot;margin: 0 0 1.25em 1.15em; padding: 0;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;code&gt;stk.arr[i]&lt;/code&gt;는 잘못된 문법입니다. 리스트에 값을 넣을 때는 &lt;code&gt;stk.append(arr[i])&lt;/code&gt;를 써야 합니다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;code&gt;i &amp;lt; len(arr)&lt;/code&gt;는 &lt;code&gt;i&lt;/code&gt;가 배열의 길이보다 작은지 확인하는 조건입니다. &lt;code&gt;i &amp;lt; arr[i]&lt;/code&gt;가 아닙니다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;3번 조건에서 &lt;code&gt;stk.pop()&lt;/code&gt;을 할 때는 &lt;code&gt;i&lt;/code&gt;를 증가시키지 않습니다. 같은 &lt;code&gt;arr[i]&lt;/code&gt;를 새로 바뀐 &lt;code&gt;stk&lt;/code&gt;와 다시 비교해야 하기 때문입니다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;code&gt;arr[-1]&lt;/code&gt;은 전체 배열의 마지막 원소입니다. 지금 보고 있는 값은 &lt;code&gt;arr[i]&lt;/code&gt;입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;기본 수정 풀이&lt;/h3&gt;
&lt;pre class=&quot;matlab&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(arr):
    stk = []
    i = 0

    while i &amp;lt; len(arr):
        if not stk:
            stk.append(arr[i])
            i += 1
        elif stk[-1] &amp;lt; arr[i]:
            stk.append(arr[i])
            i += 1
        else:
            stk.pop()

    return stk&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;margin: 1.35em 0 .52em; font-size: 1.08em; line-height: 1.45; font-weight: 800; color: #172033;&quot; data-ke-size=&quot;size23&quot;&gt;더 간단한 풀이: 모노토닉 스택&lt;/h3&gt;
&lt;pre class=&quot;vim&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(arr):
    stk = []

    for i in range(len(arr)):
        while stk and stk[-1] &amp;gt;= arr[i]:
            stk.pop()
        stk.append(arr[i])

    return stk&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;이 코드는 &lt;code&gt;stk&lt;/code&gt; 안의 숫자가 항상 오름차순으로 남도록 만듭니다. 새로 들어올 값 &lt;code&gt;arr[i]&lt;/code&gt;보다 크거나 같은 값이 스택의 끝에 있으면 계속 &lt;code&gt;pop()&lt;/code&gt;으로 제거합니다. 방해되는 값들이 다 사라진 뒤에 현재 값 &lt;code&gt;arr[i]&lt;/code&gt;를 추가합니다.&lt;/p&gt;
&lt;div style=&quot;overflow-x: auto; margin: 1.25em 0 1.55em;&quot;&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; border: 1px solid #e2e8f0; font-size: .96em; background: #fff;&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption style=&quot;position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0);&quot;&gt;배열 만들기 4 예시 흐름&lt;/caption&gt;
&lt;thead&gt;
&lt;tr style=&quot;background: #f6f8fb;&quot;&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;현재 값&lt;/th&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;while 동작&lt;/th&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;append 후 stk&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;스택이 비어 있음&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[1]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;4&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;1 &amp;lt; 4&lt;/code&gt;라서 제거 없음&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[1, 4]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;4 &amp;gt;= 2&lt;/code&gt;라서 &lt;code&gt;4&lt;/code&gt; 제거&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[1, 2]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;5&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;2 &amp;lt; 5&lt;/code&gt;라서 제거 없음&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[1, 2, 5]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;5 &amp;gt;= 3&lt;/code&gt;라서 &lt;code&gt;5&lt;/code&gt; 제거&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[1, 2, 3]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;section style=&quot;margin: 1.35em 0; padding: 1em 1.1em; border: 1px solid #dbe5f5; border-radius: 8px; background: #f8fbff;&quot;&gt;&lt;b&gt;pop, remove, del, clear 차이&lt;/b&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;pop()&lt;/code&gt;은 위치 기준으로 값을 제거하고 제거한 값을 반환합니다. 괄호를 비우면 마지막 값을 제거하므로 스택 문제에서 자주 씁니다. &lt;code&gt;remove()&lt;/code&gt;는 특정 값을 찾아 제거하고, &lt;code&gt;del&lt;/code&gt;은 인덱스나 변수를 삭제하며, &lt;code&gt;clear()&lt;/code&gt;는 리스트 전체를 비웁니다. 이번 문제에서는 마지막 원소를 제거해야 하므로 &lt;code&gt;stk.pop()&lt;/code&gt;이 가장 자연스럽습니다.&lt;/p&gt;
&lt;/section&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;7. 입출력 예로 빠르게 검산하기&lt;/h2&gt;
&lt;div style=&quot;overflow-x: auto; margin: 1.25em 0 1.55em;&quot;&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; border: 1px solid #e2e8f0; font-size: .96em; background: #fff;&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption style=&quot;position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0);&quot;&gt;Day 7 문제별 빠른 검산 예시&lt;/caption&gt;
&lt;thead&gt;
&lt;tr style=&quot;background: #f6f8fb;&quot;&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;문제&lt;/th&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;예시 입력&lt;/th&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;기대 결과&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;수열과 구간 쿼리 4&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[0,1,2,4,3], [[0,4,1],[0,3,2],[0,3,3]]&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[3, 2, 4, 6, 4]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;배열 만들기 2&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;l=5, r=555&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[5, 50, 55, 500, 505, 550, 555]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;카운트 업&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;start_num=3, end_num=10&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[3, 4, 5, 6, 7, 8, 9, 10]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;콜라츠 수열 만들기&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;n=10&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[10, 5, 16, 8, 4, 2, 1]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;배열 만들기 4&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[1, 4, 2, 5, 3]&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[1, 2, 3]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;8. 실수 방지 체크리스트&lt;/h2&gt;
&lt;ul style=&quot;margin: 0 0 1.25em 1.15em; padding: 0;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;code&gt;range()&lt;/code&gt;는 끝값을 포함하지 않으므로, 끝까지 포함하려면 &lt;code&gt;+ 1&lt;/code&gt;을 붙인다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;배수 조건을 볼 때 배열의 값인지 인덱스인지 먼저 확인한다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;숫자의 각 자릿수를 확인해야 할 때는 &lt;code&gt;str(num)&lt;/code&gt;으로 문자열로 바꿔서 본다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;code&gt;while&lt;/code&gt;문은 종료 조건을 잘못 잡으면 무한 루프가 된다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;콜라츠 수열에서 짝수 처리는 &lt;code&gt;/&lt;/code&gt;가 아니라 &lt;code&gt;//&lt;/code&gt; 또는 &lt;code&gt;//=&lt;/code&gt;를 사용한다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;code&gt;i&lt;/code&gt;, &lt;code&gt;len(arr)&lt;/code&gt;, &lt;code&gt;arr[i]&lt;/code&gt;는 서로 다른 의미다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;리스트에 값을 넣을 때는 &lt;code&gt;append()&lt;/code&gt;, 마지막 값을 뺄 때는 &lt;code&gt;pop()&lt;/code&gt;을 떠올린다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;code&gt;arr[-1]&lt;/code&gt;은 전체 배열의 마지막 값이고, 반복문에서 현재 보는 값은 &lt;code&gt;arr[i]&lt;/code&gt;다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;9. 같이 보면 좋은 글&lt;/h2&gt;
&lt;ul style=&quot;margin: 0 0 1.25em 1.15em; padding: 0;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;b&gt;파이썬 range 기초&lt;/b&gt;: 시작값, 끝값, 증가값이 헷갈릴 때 같이 보면 좋습니다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;b&gt;while문과 무한 루프 방지&lt;/b&gt;: 반복 종료 조건을 세우는 연습에 도움이 됩니다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;b&gt;append, pop, remove, del 차이&lt;/b&gt;: 리스트에 값을 넣고 빼는 문제에서 자주 나옵니다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;b&gt;모노토닉 스택 입문&lt;/b&gt;: 배열 만들기 4처럼 스택을 오름차순으로 유지하는 문제와 연결됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;Day 7 문제들은 반복문을 많이 쓰지만, 단순히 많이 반복하는 문제가 아니었습니다. 어떤 조건에서 값을 추가할지, 언제 인덱스를 증가시킬지, 언제 반복을 멈출지를 정확히 정해야 했습니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;특히 콜라츠 수열과 배열 만들기 4는 작은 실수 하나가 바로 무한 루프나 런타임 에러로 이어질 수 있었습니다. 앞으로 비슷한 문제를 풀 때는 반복 조건, 값 갱신, 리스트 추가와 제거 위치를 먼저 확인하는 습관을 들이려고 합니다.&lt;/p&gt;
&lt;/article&gt;</description>
      <category>AI/Coding_Test</category>
      <category>반복문</category>
      <category>배열만들기2</category>
      <category>배열만들기4</category>
      <category>수열과구간쿼리4</category>
      <category>카운트업</category>
      <category>코딩기초트레이닝</category>
      <category>코딩테스트</category>
      <category>콜라츠수열</category>
      <category>파이썬</category>
      <category>프로그래머스</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/108</guid>
      <comments>https://onethingflow.tistory.com/entry/Day-7-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%B0%98%EB%B3%B5%EB%AC%B8-%EA%B5%AC%EA%B0%84-%EC%BF%BC%EB%A6%AC-%EB%B0%B0%EC%97%B4-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EC%BD%9C%EB%9D%BC%EC%B8%A0-%EC%8A%A4%ED%83%9D-%ED%92%80%EC%9D%B4-%EC%A0%95%EB%A6%AC#entry108comment</comments>
      <pubDate>Sun, 12 Jul 2026 21:48:52 +0900</pubDate>
    </item>
    <item>
      <title>Day 6)Programmers Coding Test</title>
      <link>https://onethingflow.tistory.com/entry/Day-6Programmers-Coding-Test</link>
      <description>&lt;!--
티스토리 제목 추천:
프로그래머스 코딩 기초: 마지막 두 원소, 수 조작하기, 구간 쿼리 실수 정리

메타 설명 추천:
프로그래머스 코딩 기초 트레이닝의 마지막 두 원소, 수 조작하기 1, 수 조작하기 2, 수열과 구간 쿼리 3, 수열과 구간 쿼리 2를 파이썬으로 풀며 append 반환값, =와 == 차이, 딕셔너리 매핑, 인덱스 접근, 들여쓰기 실수를 정리했습니다.

태그 추천:
프로그래머스, 코딩테스트, 파이썬, 코딩기초트레이닝, 마지막두원소, 수조작하기, 수열과구간쿼리, 파이썬리스트, append, 딕셔너리
--&gt;

&lt;article style=&quot;max-width:780px;margin:0 auto;line-height:1.86;font-size:17px;color:#222;word-break:keep-all;&quot;&gt;
  &lt;section style=&quot;margin:0 0 1.5em;padding:1.35em 1.4em;border:1px solid #dde6f2;border-radius:8px;background:linear-gradient(135deg,#f7fbff 0%,#fff 62%,#fff7ed 100%);&quot;&gt;
    &lt;p style=&quot;margin:0 0 .8em;display:inline-block;padding:.25em .7em;border:1px solid #d9e4f2;border-radius:999px;background:#fff;font-size:.84em;font-weight:700;color:#385174;&quot;&gt;프로그래머스 코딩 기초 트레이닝&lt;/p&gt;
    &lt;h1 style=&quot;margin:.1em 0 .72em;font-size:2em;line-height:1.28;font-weight:800;color:#111;&quot;&gt;마지막 두 원소, 수 조작하기, 구간 쿼리 실수 정리&lt;/h1&gt;
    &lt;p style=&quot;margin:0 0 1em;font-size:1.08em;color:#343b46;&quot;&gt;이번 글은 제가 파이썬으로 프로그래머스 코딩 기초 트레이닝을 풀면서 헷갈렸던 내용을 다시 정리한 기록입니다. 특히 &lt;code&gt;append()&lt;/code&gt;의 반환값, &lt;code&gt;=&lt;/code&gt;와 &lt;code&gt;==&lt;/code&gt;의 차이, 리스트 인덱스 접근, 딕셔너리 매핑, 그리고 들여쓰기 위치에서 실수가 많이 나왔습니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;정답 코드만 보면 쉬워 보이지만, 막상 직접 쓰면 어디에서 값이 바뀌고 어디에서 반환해야 하는지 헷갈립니다. 그래서 각 문제마다 처음 헷갈린 코드, 잘못된 점, 기본 수정 풀이, 더 간단한 풀이 순서로 정리했습니다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;div style=&quot;display:grid;grid-template-columns:repeat(3,1fr);gap:.85em;margin:1.35em 0;&quot;&gt;
    &lt;div style=&quot;border:1px solid #e3e8ef;border-radius:8px;background:#fff;padding:1em;&quot;&gt;
      &lt;span style=&quot;display:block;font-size:.82em;color:#687182;margin-bottom:.25em;&quot;&gt;핵심 1&lt;/span&gt;
      &lt;strong style=&quot;display:block;font-size:1.04em;color:#101418;line-height:1.36;&quot;&gt;append는 None을 반환&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div style=&quot;border:1px solid #e3e8ef;border-radius:8px;background:#fff;padding:1em;&quot;&gt;
      &lt;span style=&quot;display:block;font-size:.82em;color:#687182;margin-bottom:.25em;&quot;&gt;핵심 2&lt;/span&gt;
      &lt;strong style=&quot;display:block;font-size:1.04em;color:#101418;line-height:1.36;&quot;&gt;값과 인덱스 구분&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div style=&quot;border:1px solid #e3e8ef;border-radius:8px;background:#fff;padding:1em;&quot;&gt;
      &lt;span style=&quot;display:block;font-size:.82em;color:#687182;margin-bottom:.25em;&quot;&gt;핵심 3&lt;/span&gt;
      &lt;strong style=&quot;display:block;font-size:1.04em;color:#101418;line-height:1.36;&quot;&gt;쿼리는 끝까지 처리 후 판단&lt;/strong&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;blockquote style=&quot;margin:1.55em 0;padding:.95em 1.15em;background:#fff9e8;border-left:4px solid #f2b705;border-radius:8px;font-size:1.06em;font-weight:800;color:#584500;&quot;&gt;
    이번 문제들은 어려운 알고리즘보다, 파이썬 기본 문법을 정확한 위치에 쓰는 연습에 가까웠습니다.
  &lt;/blockquote&gt;

  &lt;section style=&quot;margin:1.6em 0;padding:1em 1.1em;border:1px solid #e2e8f0;border-radius:8px;background:#fbfdff;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 .65em;font-size:1.18em;line-height:1.45;font-weight:800;color:#111;&quot;&gt;이 글의 풀이 순서&lt;/h2&gt;
    &lt;ol style=&quot;margin:0 0 0 1.15em;padding:0;&quot;&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;문제 및 프로그래머스 공식 링크&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;내 풀이 또는 처음 헷갈린 코드&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;설명 및 잘못된 점&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;기본 수정 풀이&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;더 간단한 풀이와 설명&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;입출력 예로 검산하기&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/section&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;1. 문제 및 프로그래머스 공식 링크&lt;/h2&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;이번 글에서 정리한 문제는 모두 프로그래머스 코딩 기초 트레이닝 문제입니다.&lt;/p&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;&quot;&gt;
    &lt;table style=&quot;width:100%;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;프로그래머스 문제 링크와 핵심 개념&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;문제&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;공식 링크&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;핵심 개념&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;마지막 두 원소&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181927&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;마지막 값과 직전 값 비교, append&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;수 조작하기 1&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181926&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;문자별 숫자 변화, 딕셔너리&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;수 조작하기 2&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181925&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;두 값의 차이로 문자 복원&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;수열과 구간 쿼리 3&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181924&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;인덱스 쌍으로 자리 바꾸기&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;수열과 구간 쿼리 2&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181923&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;범위 안에서 k보다 큰 최솟값 찾기&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;2. 마지막 두 원소: append 결과를 변수에 담으면 안 되는 이유&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;리스트의 마지막 원소가 그전 원소보다 크면 두 값의 차이를 추가하고, 그렇지 않으면 마지막 원소의 두 배를 추가해 리스트를 반환하는 문제입니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;처음 헷갈린 코드&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(num_list):
    answer = []
    if num_list[-1] &amp;gt; num_list[-2]:
        new = num_list[-1] - num_list[-2]
    else:
        new = num_list[-1] * 2

    answer = num_list.append(new)
    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;설명 및 잘못된 점&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;핵심 실수는 &lt;code&gt;answer = num_list.append(new)&lt;/code&gt;입니다. &lt;code&gt;append()&lt;/code&gt;는 리스트에 값을 직접 추가하지만, 그 실행 결과로 새 리스트를 반환하지 않습니다. 그래서 &lt;code&gt;answer&lt;/code&gt;에는 리스트가 아니라 &lt;code&gt;None&lt;/code&gt;이 들어갑니다. 값을 추가한 뒤에는 바뀐 &lt;code&gt;num_list&lt;/code&gt; 자체를 반환해야 합니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;기본 수정 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(num_list):
    if num_list[-1] &amp;gt; num_list[-2]:
        new = num_list[-1] - num_list[-2]
    else:
        new = num_list[-1] * 2

    num_list.append(new)
    return num_list&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;더 간단한 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(num_list):
    last = num_list[-1]
    prev = num_list[-2]
    num_list.append(last - prev if last &amp;gt; prev else last * 2)
    return num_list&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;num_list[-1]&lt;/code&gt;은 마지막 원소, &lt;code&gt;num_list[-2]&lt;/code&gt;는 뒤에서 두 번째 원소입니다. 리스트 끝의 값만 보면 되므로 반복문은 필요하지 않습니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;3. 수 조작하기 1: =와 ==를 확실히 구분하기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;문자열 &lt;code&gt;control&lt;/code&gt;을 앞에서부터 읽으며 &lt;code&gt;w&lt;/code&gt;, &lt;code&gt;s&lt;/code&gt;, &lt;code&gt;d&lt;/code&gt;, &lt;code&gt;a&lt;/code&gt;에 따라 정수 &lt;code&gt;n&lt;/code&gt;을 각각 1 증가, 1 감소, 10 증가, 10 감소시키는 문제입니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;처음 헷갈린 코드&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(n, control):
    answer = 0
    for char in control:
        if char = &quot;w&quot;:
            answer += 1&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;설명 및 잘못된 점&lt;/h3&gt;
  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;if char = &quot;w&quot;&lt;/code&gt;는 문법 오류입니다. 조건 비교에는 &lt;code&gt;==&lt;/code&gt;를 사용해야 합니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;문제는 새로 만든 &lt;code&gt;answer = 0&lt;/code&gt;을 조작하는 것이 아니라, 매개변수로 받은 &lt;code&gt;n&lt;/code&gt;을 조작하는 문제입니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;answer&lt;/code&gt;를 &lt;code&gt;answser&lt;/code&gt;처럼 잘못 쓰면 변수명 오타 때문에 오류가 납니다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;section style=&quot;margin:1.35em 0;padding:1em 1.1em;border:1px solid #e7d7aa;border-radius:8px;background:#fffaf0;&quot;&gt;
    &lt;strong style=&quot;display:block;margin:0 0 .45em;color:#5c4300;&quot;&gt;= 와 == 차이&lt;/strong&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;code&gt;=&lt;/code&gt;는 변수에 값을 넣는 대입입니다. &lt;code&gt;n = 1&lt;/code&gt;은 &lt;code&gt;n&lt;/code&gt; 값을 1로 바꿉니다. &lt;code&gt;==&lt;/code&gt;는 두 값이 같은지 비교하는 조건식입니다. &lt;code&gt;char == &quot;w&quot;&lt;/code&gt;는 &lt;code&gt;char&lt;/code&gt;가 &lt;code&gt;&quot;w&quot;&lt;/code&gt;인지 확인합니다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;기본 수정 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(n, control):
    for char in control:
        if char == &quot;w&quot;:
            n += 1
        elif char == &quot;s&quot;:
            n -= 1
        elif char == &quot;d&quot;:
            n += 10
        else:
            n -= 10

    return n&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;더 간단한 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(n, control):
    control_dict = {&quot;w&quot;: 1, &quot;s&quot;: -1, &quot;d&quot;: 10, &quot;a&quot;: -10}
    return n + sum(control_dict[char] for char in control)&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;문자와 변화량이 일대일로 대응되기 때문에 딕셔너리를 쓰면 조건문을 줄일 수 있습니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;4. 수 조작하기 2: 값이 아니라 차이를 문자로 바꾸기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;정수 배열 &lt;code&gt;numLog&lt;/code&gt;에는 조작 후의 값들이 차례대로 들어 있습니다. 연속된 두 값의 차이가 1이면 &lt;code&gt;w&lt;/code&gt;, -1이면 &lt;code&gt;s&lt;/code&gt;, 10이면 &lt;code&gt;d&lt;/code&gt;, -10이면 &lt;code&gt;a&lt;/code&gt;를 붙여 원래 조작 문자열을 복원해야 합니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;처음 헷갈린 코드&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(numLog):
    ans = ''
    c = {&quot;w&quot;: 1, &quot;s&quot;: -1, &quot;d&quot;: 10, &quot;a&quot;: -10}
    for l in numLog:
        # numLog[l + 1]처럼 접근하려고 하면 위험합니다.
        pass&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;설명 및 잘못된 점&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;for l in numLog&lt;/code&gt;에서 &lt;code&gt;l&lt;/code&gt;은 인덱스가 아니라 리스트 안의 실제 값입니다. 그래서 &lt;code&gt;numLog[l + 1]&lt;/code&gt;처럼 쓰면 의도와 다르게 동작합니다. 이 문제는 현재 값과 다음 값의 차이를 구해야 하므로 인덱스로 접근하거나, &lt;code&gt;zip()&lt;/code&gt;으로 앞뒤 값을 묶어야 합니다. 또한 딕셔너리는 문자에서 숫자로 가는 방향이 아니라 숫자 차이에서 문자로 가는 방향이어야 합니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;기본 수정 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(numLog):
    answer = ''
    diff_to_char = {1: &quot;w&quot;, -1: &quot;s&quot;, 10: &quot;d&quot;, -10: &quot;a&quot;}

    for i in range(1, len(numLog)):
        diff = numLog[i] - numLog[i - 1]
        answer += diff_to_char[diff]

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;더 간단한 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(numLog):
    diff_to_char = {1: &quot;w&quot;, -1: &quot;s&quot;, 10: &quot;d&quot;, -10: &quot;a&quot;}
    return ''.join(diff_to_char[next_num - cur] for cur, next_num in zip(numLog, numLog[1:]))&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;zip(numLog, numLog[1:])&lt;/code&gt;은 현재 값과 다음 값을 한 쌍으로 묶어줍니다. 그래서 &lt;code&gt;next_num - cur&lt;/code&gt;만 계산하면 변화량을 바로 얻을 수 있습니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;5. 수열과 구간 쿼리 3: queries는 자리 바꾸기 지시서다&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;queries&lt;/code&gt;의 각 원소는 &lt;code&gt;[i, j]&lt;/code&gt; 형태입니다. 각 쿼리마다 &lt;code&gt;arr[i]&lt;/code&gt;와 &lt;code&gt;arr[j]&lt;/code&gt;의 값을 서로 바꾼 뒤, 모든 쿼리를 처리한 최종 배열을 반환합니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;처음 헷갈린 코드&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(arr, queries):
    answer = []
    for char in queries:
        char = queries&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;설명 및 잘못된 점&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;반복문에서 꺼낸 &lt;code&gt;char&lt;/code&gt;에 다시 &lt;code&gt;queries&lt;/code&gt; 전체를 넣으면, 현재 쿼리의 의미가 사라집니다. 이 문제에서 중요한 것은 &lt;code&gt;queries&lt;/code&gt; 안의 &lt;code&gt;[i, j]&lt;/code&gt;를 하나씩 꺼내 &lt;code&gt;arr&lt;/code&gt;의 두 위치를 바꾸는 것입니다. 따라서 &lt;code&gt;for i, j in queries&lt;/code&gt;처럼 구조 분해를 사용하는 것이 가장 직관적입니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;기본 수정 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(arr, queries):
    for i, j in queries:
        arr[i], arr[j] = arr[j], arr[i]

    return arr&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;arr[i], arr[j] = arr[j], arr[i]&lt;/code&gt;는 파이썬에서 두 값을 서로 바꿀 때 자주 쓰는 문법입니다. 임시 변수를 따로 만들지 않아도 됩니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;6. 수열과 구간 쿼리 2: 최솟값 판단은 안쪽 반복문이 끝난 뒤에&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;각 쿼리는 &lt;code&gt;[s, e, k]&lt;/code&gt; 형태입니다. &lt;code&gt;arr[s]&lt;/code&gt;부터 &lt;code&gt;arr[e]&lt;/code&gt;까지 보면서 &lt;code&gt;k&lt;/code&gt;보다 큰 값 중 가장 작은 값을 찾아야 합니다. 조건에 맞는 값이 없으면 &lt;code&gt;-1&lt;/code&gt;을 넣습니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;처음 헷갈린 흐름&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(arr, queries):
    answer = []
    for s, e, k in queries:
        sub_arr = []
        for i in range(s, e + 1):
            if arr[i] &amp;gt; k:
                sub_arr.append(arr[i])
                answer.append(min(sub_arr))  # 위치가 너무 빠릅니다.&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;설명 및 잘못된 점&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;이 문제에서 가장 중요한 부분은 들여쓰기입니다. 후보를 모두 모으기도 전에 &lt;code&gt;answer.append(min(sub_arr))&lt;/code&gt;를 실행하면, 범위를 끝까지 확인하기 전에 결과가 들어가고 쿼리 하나에서 답이 여러 번 추가될 수 있습니다. &lt;code&gt;-1&lt;/code&gt;을 넣는 판단도 마찬가지로 안쪽 반복문이 끝난 뒤에 해야 합니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;기본 수정 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(arr, queries):
    answer = []

    for s, e, k in queries:
        candidates = []

        for i in range(s, e + 1):
            if arr[i] &amp;gt; k:
                candidates.append(arr[i])

        if candidates:
            answer.append(min(candidates))
        else:
            answer.append(-1)

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;더 간단한 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(arr, queries):
    answer = []

    for s, e, k in queries:
        candidates = [x for x in arr[s:e + 1] if x &amp;gt; k]
        answer.append(min(candidates) if candidates else -1)

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;arr[s:e + 1]&lt;/code&gt;은 s부터 e까지의 구간을 잘라냅니다. 파이썬 슬라이싱은 끝 인덱스를 포함하지 않기 때문에 &lt;code&gt;e + 1&lt;/code&gt;을 사용합니다. 그리고 빈 리스트는 조건문에서 거짓처럼 동작하므로 &lt;code&gt;if candidates&lt;/code&gt;로 후보가 있는지 확인할 수 있습니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;7. 입출력 예로 빠르게 검산하기&lt;/h2&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;&quot;&gt;
    &lt;table style=&quot;width:100%;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;문제별 빠른 검산 예시&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;문제&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;예시 입력&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;기대 결과&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;마지막 두 원소&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[2, 1, 6]&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[2, 1, 6, 5]&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;수 조작하기 1&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;0, &quot;wsdawsdassw&quot;&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;-1&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;수 조작하기 2&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[0, 1, 0, 10, 0, 1, 0, 10, 0, -1, -2, -1]&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;&quot;wsdawsdassw&quot;&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;수열과 구간 쿼리 3&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[0,1,2,3,4], [[0,3],[1,2],[1,4]]&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[3, 4, 1, 0, 2]&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;수열과 구간 쿼리 2&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[0,1,2,4,3], [[0,4,2],[0,3,2],[0,2,2]]&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[3, 4, -1]&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;8. 실수 방지 체크리스트&lt;/h2&gt;

  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;append()&lt;/code&gt;는 리스트를 직접 바꾸지만 새 리스트를 반환하지 않는다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;=&lt;/code&gt;는 대입, &lt;code&gt;==&lt;/code&gt;는 비교다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;문제를 풀 때 새 변수 &lt;code&gt;answer&lt;/code&gt;가 필요한지, 기존 입력값을 바꿔 반환해야 하는지 먼저 확인한다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;for x in 리스트&lt;/code&gt;에서 &lt;code&gt;x&lt;/code&gt;는 인덱스가 아니라 실제 값이다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;연속된 두 값의 차이를 봐야 하면 &lt;code&gt;range(1, len(...))&lt;/code&gt; 또는 &lt;code&gt;zip()&lt;/code&gt;을 떠올린다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;쿼리 문제에서는 안쪽 반복문이 끝난 뒤 결과를 한 번만 추가해야 하는 경우가 많다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;리스트가 비었는지는 &lt;code&gt;if candidates:&lt;/code&gt;, &lt;code&gt;if not candidates:&lt;/code&gt;로 간단히 확인할 수 있다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;9. 같이 보면 좋은 글&lt;/h2&gt;

  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;파이썬 리스트 인덱싱 기초&lt;/strong&gt;: &lt;code&gt;[-1]&lt;/code&gt;, &lt;code&gt;[-2]&lt;/code&gt;, 슬라이싱을 헷갈릴 때 같이 보기 좋습니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;파이썬 append와 return 차이&lt;/strong&gt;: 리스트를 직접 바꾸는 메서드를 이해하는 데 도움이 됩니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;딕셔너리로 조건문 줄이기&lt;/strong&gt;: 문자와 숫자를 매핑하는 문제에서 자주 쓰입니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;구간 쿼리 문제 읽는 법&lt;/strong&gt;: &lt;code&gt;[i, j]&lt;/code&gt;, &lt;code&gt;[s, e, k]&lt;/code&gt; 형태의 입력을 해석할 때 도움이 됩니다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;마무리&lt;/h2&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;이번 문제들을 풀면서 가장 크게 느낀 점은, 코딩테스트 초반에는 알고리즘보다 기본 문법 실수가 더 자주 발목을 잡는다는 것입니다. &lt;code&gt;append()&lt;/code&gt;를 변수에 담는 실수, &lt;code&gt;=&lt;/code&gt;와 &lt;code&gt;==&lt;/code&gt;를 헷갈리는 실수, 값과 인덱스를 섞는 실수만 줄여도 코드가 훨씬 안정적으로 돌아갑니다.&lt;/p&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;다음에 비슷한 문제를 만나면 먼저 “반복문이 정말 필요한가?”, “반환해야 하는 값은 무엇인가?”, “결과를 언제 추가해야 하는가?”를 확인하려고 합니다. 이 세 가지만 체크해도 같은 실수를 꽤 많이 줄일 수 있을 것 같습니다.&lt;/p&gt;
&lt;/article&gt;</description>
      <category>AI/Coding_Test</category>
      <category>append</category>
      <category>딕셔너리</category>
      <category>마지막두원소</category>
      <category>수열과구간쿼리</category>
      <category>수조작하기</category>
      <category>코딩기초트레이닝</category>
      <category>코딩테스트</category>
      <category>파이썬</category>
      <category>파이썬리스트</category>
      <category>프로그래머스</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/107</guid>
      <comments>https://onethingflow.tistory.com/entry/Day-6Programmers-Coding-Test#entry107comment</comments>
      <pubDate>Sat, 11 Jul 2026 18:14:48 +0900</pubDate>
    </item>
    <item>
      <title>Day5) Programmers Coding Test</title>
      <link>https://onethingflow.tistory.com/entry/Day5-Programmers-Coding-Test</link>
      <description>&lt;article style=&quot;max-width:780px;margin:0 auto;line-height:1.86;font-size:17px;color:#222;word-break:keep-all;&quot;&gt;
  &lt;section style=&quot;margin:0 0 1.5em;padding:1.35em 1.4em;border:1px solid #dde6f2;border-radius:8px;background:linear-gradient(135deg,#f7fbff 0%,#fff 62%,#fff7ed 100%);&quot;&gt;
    &lt;p style=&quot;margin:0 0 .8em;display:inline-block;padding:.25em .7em;border:1px solid #d9e4f2;border-radius:999px;background:#fff;font-size:.84em;font-weight:700;color:#385174;&quot;&gt;프로그래머스 코딩 기초 트레이닝&lt;/p&gt;
    &lt;h1 style=&quot;margin:.1em 0 .72em;font-size:2em;line-height:1.28;font-weight:800;color:#111;&quot;&gt;코드 처리하기, 등차수열, 주사위 게임 2, 리스트 문제 풀이 정리&lt;/h1&gt;
    &lt;p style=&quot;margin:0 0 1em;font-size:1.08em;color:#343b46;&quot;&gt;이번 글에서는 프로그래머스 코딩 기초 트레이닝 문제 중에서 조건 전환, 등차수열 누적, 같은 값 판별, 리스트의 합과 곱, 홀짝 이어 붙이기를 정리했습니다. 문제 자체는 짧지만 직접 풀어보면 &lt;code&gt;=&lt;/code&gt;와 &lt;code&gt;==&lt;/code&gt;, 문자열 &lt;code&gt;'1'&lt;/code&gt;과 숫자 &lt;code&gt;1&lt;/code&gt;, 곱셈 초기값, 반복문 안팎의 비교 위치처럼 헷갈리는 부분이 계속 나옵니다.&lt;/p&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;그래서 정답 코드만 적기보다, 제가 헷갈렸던 지점을 먼저 짚고 기본 풀이와 더 간단한 풀이를 함께 정리했습니다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;div style=&quot;display:grid;grid-template-columns:repeat(3,1fr);gap:.85em;margin:1.35em 0;&quot;&gt;
    &lt;div style=&quot;border:1px solid #e3e8ef;border-radius:8px;background:#fff;padding:1em;&quot;&gt;
      &lt;span style=&quot;display:block;font-size:.82em;color:#687182;margin-bottom:.25em;&quot;&gt;핵심 1&lt;/span&gt;
      &lt;strong style=&quot;display:block;font-size:1.04em;color:#101418;line-height:1.36;&quot;&gt;mode 전환과 문자열 누적&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div style=&quot;border:1px solid #e3e8ef;border-radius:8px;background:#fff;padding:1em;&quot;&gt;
      &lt;span style=&quot;display:block;font-size:.82em;color:#687182;margin-bottom:.25em;&quot;&gt;핵심 2&lt;/span&gt;
      &lt;strong style=&quot;display:block;font-size:1.04em;color:#101418;line-height:1.36;&quot;&gt;등차수열과 조건 누적&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div style=&quot;border:1px solid #e3e8ef;border-radius:8px;background:#fff;padding:1em;&quot;&gt;
      &lt;span style=&quot;display:block;font-size:.82em;color:#687182;margin-bottom:.25em;&quot;&gt;핵심 3&lt;/span&gt;
      &lt;strong style=&quot;display:block;font-size:1.04em;color:#101418;line-height:1.36;&quot;&gt;set, 합, 곱, 홀짝 분리&lt;/strong&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;blockquote style=&quot;margin:1.55em 0;padding:.95em 1.15em;background:#fff9e8;border-left:4px solid #f2b705;border-radius:8px;font-size:1.06em;font-weight:800;color:#584500;&quot;&gt;
    오늘 문제들의 공통점은 “문제를 읽은 그대로 변수와 조건으로 옮기는 연습”이었습니다.
  &lt;/blockquote&gt;

  &lt;section style=&quot;margin:1.6em 0;padding:1em 1.1em;border:1px solid #e2e8f0;border-radius:8px;background:#fbfdff;&quot;&gt;
    &lt;h2 style=&quot;margin:0 0 .65em;font-size:1.18em;line-height:1.45;font-weight:800;color:#111;&quot;&gt;이 글의 풀이 순서&lt;/h2&gt;
    &lt;ol style=&quot;margin:0 0 0 1.15em;padding:0;&quot;&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;문제 및 프로그래머스 공식 링크&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;내 풀이&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;설명 및 잘못된 점&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;기본 수정 풀이&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;여러 더 간편한 풀이와 설명&lt;/li&gt;
      &lt;li style=&quot;margin:.35em 0;&quot;&gt;입출력 예로 검산하기&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/section&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;1. 문제 및 프로그래머스 공식 링크&lt;/h2&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;이번 글에서 정리한 문제는 모두 프로그래머스 코딩 기초 트레이닝 문제입니다.&lt;/p&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;&quot;&gt;
    &lt;table style=&quot;width:100%;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;프로그래머스 문제 링크와 핵심 개념&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;문제&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;공식 링크&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;핵심 개념&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;코드 처리하기&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181932&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;mode 전환, 인덱스 홀짝&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;등차수열의 특정한 항만 더하기&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181931&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;등차수열 공식, boolean 조건&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;주사위 게임 2&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181930&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;세 값이 같은지 판별&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;원소들의 곱과 합&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181929&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;곱 초기값, 합의 제곱&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;이어 붙인 수&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181928&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; style=&quot;color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;홀수와 짝수 문자열 분리&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;2. 코드 처리하기: mode, '1', ret, answer 헷갈리지 않기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;문자열 &lt;code&gt;code&lt;/code&gt;를 앞에서부터 읽으면서 문자가 &lt;code&gt;'1'&lt;/code&gt;이면 &lt;code&gt;mode&lt;/code&gt;를 0에서 1로, 또는 1에서 0으로 바꾸는 문제입니다. &lt;code&gt;mode&lt;/code&gt;가 0일 때는 짝수 인덱스의 문자를, &lt;code&gt;mode&lt;/code&gt;가 1일 때는 홀수 인덱스의 문자를 결과 문자열에 붙입니다. 마지막 결과가 빈 문자열이면 &lt;code&gt;&quot;EMPTY&quot;&lt;/code&gt;를 반환해야 합니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;설명 및 잘못된 점&lt;/h3&gt;
  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;mode&lt;/code&gt;는 처음에 0으로 시작해야 합니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;code[i]&lt;/code&gt;는 문자열이므로 숫자 &lt;code&gt;1&lt;/code&gt;이 아니라 문자열 &lt;code&gt;'1'&lt;/code&gt;과 비교해야 합니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;mode == 1&lt;/code&gt;은 비교이고, &lt;code&gt;mode = 1&lt;/code&gt;은 값을 바꾸는 대입입니다. 상태를 바꿀 때는 &lt;code&gt;=&lt;/code&gt;를 써야 합니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;문제 설명에는 결과 문자열을 &lt;code&gt;ret&lt;/code&gt;라고 부르지만, 파이썬 기본 코드에서는 보통 &lt;code&gt;answer&lt;/code&gt;를 사용합니다. 중요한 것은 변수 이름을 하나로 통일하는 것입니다. &lt;code&gt;ret&lt;/code&gt;를 따로 만들지 않았는데 &lt;code&gt;answer = ret + code[idx]&lt;/code&gt;처럼 쓰면 오류가 납니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;idx&lt;/code&gt;를 쓸지 &lt;code&gt;i&lt;/code&gt;를 쓸지도 통일해야 합니다. 반복문에서 &lt;code&gt;for i in ...&lt;/code&gt;라고 했다면 본문에서도 &lt;code&gt;code[i]&lt;/code&gt;를 쓰는 편이 안전합니다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;section style=&quot;margin:1.35em 0;padding:1em 1.1em;border:1px solid #e7d7aa;border-radius:8px;background:#fffaf0;&quot;&gt;
    &lt;strong style=&quot;display:block;margin:0 0 .45em;color:#5c4300;&quot;&gt;= 와 == 차이&lt;/strong&gt;
    &lt;p style=&quot;margin:0;&quot;&gt;&lt;code&gt;=&lt;/code&gt;는 변수에 값을 넣는 대입입니다. 예를 들어 &lt;code&gt;mode = 1&lt;/code&gt;은 &lt;code&gt;mode&lt;/code&gt; 값을 1로 바꿉니다. 반대로 &lt;code&gt;==&lt;/code&gt;는 두 값이 같은지 확인하는 비교입니다. 예를 들어 &lt;code&gt;mode == 1&lt;/code&gt;은 &lt;code&gt;mode&lt;/code&gt;가 1인지 묻는 조건식입니다.&lt;/p&gt;
  &lt;/section&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;기본 수정 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(code):
    answer = ''
    mode = 0

    for i in range(len(code)):
        if mode == 0:
            if code[i] != '1':
                if i % 2 == 0:
                    answer += code[i]
            else:
                mode = 1
        elif mode == 1:
            if code[i] != '1':
                if i % 2 != 0:
                    answer += code[i]
            else:
                mode = 0

    if answer == '':
        return &quot;EMPTY&quot;

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;여기서 &lt;code&gt;elif&lt;/code&gt;를 사용하면 한 번의 반복에서 &lt;code&gt;mode&lt;/code&gt;가 바뀐 뒤 곧바로 다음 조건까지 이어서 실행되는 흐름을 막을 수 있어 읽기 좋습니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;더 간단한 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(code):
    return &quot;&quot;.join(code.split(&quot;1&quot;))[::2] or &quot;EMPTY&quot;&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;이 풀이는 처음 보면 갑자기 느껴질 수 있습니다. 핵심은 &lt;code&gt;'1'&lt;/code&gt;을 기준으로 &lt;code&gt;mode&lt;/code&gt;가 바뀌고, &lt;code&gt;'1'&lt;/code&gt;을 제거한 뒤에는 선택해야 할 문자가 짝수 위치에 남는다는 점입니다. 그래도 처음 공부할 때는 위의 기본 풀이처럼 &lt;code&gt;mode&lt;/code&gt;를 직접 바꿔보는 방식이 더 이해하기 쉽습니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;3. 등차수열의 특정한 항만 더하기: included가 True인 항만 누적하기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;첫째항이 &lt;code&gt;a&lt;/code&gt;, 공차가 &lt;code&gt;d&lt;/code&gt;인 등차수열이 있을 때, &lt;code&gt;included[i]&lt;/code&gt;가 &lt;code&gt;True&lt;/code&gt;인 항만 더하는 문제입니다. 인덱스 &lt;code&gt;i&lt;/code&gt;에서의 항은 &lt;code&gt;a + d * i&lt;/code&gt;입니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;내 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(a, d, included):
    answer = 0

    for i in range(len(included)):
        if included[i] == True:
            answer += a + (d * i)

    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;설명 및 잘못된 점&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;반복 범위는 &lt;code&gt;included&lt;/code&gt; 자체가 아니라 &lt;code&gt;len(included)&lt;/code&gt;로 잡아야 합니다. 그리고 &lt;code&gt;included[i] == True&lt;/code&gt;는 틀린 표현은 아니지만, 파이썬에서는 &lt;code&gt;if included[i]:&lt;/code&gt;처럼 더 간단하게 쓸 수 있습니다. 가장 중요한 부분은 등차수열의 i번째 값을 &lt;code&gt;a + d * i&lt;/code&gt;로 계산하는 것입니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;더 간단한 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(a, d, included):
    return sum(a + d * i for i in range(len(included)) if included[i])&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 .8em;&quot;&gt;또는 &lt;code&gt;True&lt;/code&gt;가 1, &lt;code&gt;False&lt;/code&gt;가 0처럼 계산된다는 점을 이용하면 이렇게도 쓸 수 있습니다.&lt;/p&gt;

  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(a, d, included):
    answer = 0
    for i in range(len(included)):
        answer += (a + d * i) * int(included[i])
    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;4. 주사위 게임 2: 두 숫자만 같은 모든 경우를 확인하기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;세 숫자 &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, &lt;code&gt;c&lt;/code&gt;가 모두 다르면 합만 반환하고, 두 숫자만 같으면 합과 제곱합을 곱하고, 세 숫자가 모두 같으면 합, 제곱합, 세제곱합을 모두 곱하는 문제입니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;처음 작성한 코드&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(a, b, c):
    answer = 0
    if a == b == c:
        answer = (a + b + c) * (a**2 + b**2 + c**2) * (a**3 + b**3 + c**3)
    elif a == b:
        if a != c:
            answer = (a + b + c) * (a**2 + b**2 + c**2)
    else:
        answer = a + b + c
    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;설명 및 잘못된 점&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;이 코드의 핵심 문제는 두 숫자만 같은 경우를 &lt;code&gt;a == b&lt;/code&gt;만 확인했다는 점입니다. 실제로는 &lt;code&gt;a == b&lt;/code&gt;, &lt;code&gt;b == c&lt;/code&gt;, &lt;code&gt;a == c&lt;/code&gt; 세 가지 경우가 모두 가능합니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;기본 수정 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(a, b, c):
    if a == b == c:
        return (a + b + c) * (a**2 + b**2 + c**2) * (a**3 + b**3 + c**3)
    elif a == b or b == c or a == c:
        return (a + b + c) * (a**2 + b**2 + c**2)
    else:
        return a + b + c&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;더 간단한 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(a, b, c):
    count = len(set([a, b, c]))

    if count == 1:
        return (a + b + c) * (a**2 + b**2 + c**2) * (a**3 + b**3 + c**3)
    elif count == 2:
        return (a + b + c) * (a**2 + b**2 + c**2)
    else:
        return a + b + c&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;&lt;code&gt;set([a, b, c])&lt;/code&gt;는 중복을 제거합니다. 길이가 1이면 세 숫자가 모두 같고, 길이가 2이면 두 숫자만 같고, 길이가 3이면 모두 다릅니다. 사용자가 적은 &lt;code&gt;3*a*3*(a**2)*3*(a**3)&lt;/code&gt;도 세 숫자가 모두 같을 때는 계산 결과가 맞지만, 공식의 모양이 바로 보이지 않기 때문에 위처럼 원래 식을 유지하는 편이 읽기 좋습니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;5. 원소들의 곱과 합: 곱은 1로 시작해야 한다&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;리스트의 모든 원소를 곱한 값이 모든 원소의 합을 제곱한 값보다 작으면 1, 아니면 0을 반환하는 문제입니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;처음 작성한 코드&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(num_list):
    answer = 0
    sum_multi = 0
    multi = 0
    for i in range(len(num_list)):
        sum_multi += num_list[i] * num_list[i]
        multi *= num_list[i]
        if sum_multi &amp;gt; multi:
            answer = 1
        else:
            answer = 0
    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;설명 및 잘못된 점&lt;/h3&gt;
  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;곱을 저장하는 변수는 &lt;code&gt;0&lt;/code&gt;이 아니라 &lt;code&gt;1&lt;/code&gt;로 시작해야 합니다. 0으로 시작하면 무엇을 곱해도 계속 0입니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;문제는 원소의 제곱합이 아니라, 원소들의 합을 구한 뒤 그 합을 제곱해야 합니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;비교는 반복문 안에서 매번 하는 것이 아니라, 모든 합과 곱을 구한 뒤 마지막에 한 번만 하면 됩니다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;기본 수정 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(num_list):
    sum_val = 0
    multi = 1

    for num in num_list:
        sum_val += num
        multi *= num

    if multi &amp;lt; (sum_val ** 2):
        return 1
    else:
        return 0&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;더 간단한 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(num_list):
    a = 1
    b = 0

    for x in num_list:
        a *= x
        b += x

    if a &amp;lt; b * b:
        return 1
    return 0&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;여기서 &lt;code&gt;a&lt;/code&gt;는 곱, &lt;code&gt;b&lt;/code&gt;는 합입니다. 변수명을 더 명확하게 쓰고 싶다면 &lt;code&gt;product&lt;/code&gt;, &lt;code&gt;total&lt;/code&gt;처럼 바꿔도 좋습니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;6. 이어 붙인 수: 홀수 문자열과 짝수 문자열을 따로 만들기&lt;/h2&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;문제 요약&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;리스트에서 홀수만 순서대로 이어 붙인 수와 짝수만 순서대로 이어 붙인 수를 만든 뒤, 두 수를 더하는 문제입니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;내 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(num_list):
    answer = 0
    answer1 = ''
    answer2 = ''

    for num in num_list:
        if num % 2 == 0:
            answer1 += str(num)
        if num % 2 != 0:
            answer2 += str(num)

    answer = int(answer1) + int(answer2)
    return answer&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;설명 및 잘못된 점&lt;/h3&gt;
  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;이 코드는 결과 합 자체는 맞을 수 있습니다. 다만 문제 설명은 홀수로 만든 수와 짝수로 만든 수를 더하라고 하므로, 변수 이름도 홀수와 짝수를 기준으로 잡는 편이 읽기 좋습니다. 또 짝수와 홀수는 동시에 성립하지 않으므로 두 번째 &lt;code&gt;if&lt;/code&gt;는 &lt;code&gt;else&lt;/code&gt;로 바꿀 수 있습니다.&lt;/p&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;기본 수정 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(num_list):
    odd = ''
    even = ''

    for num in num_list:
        if num % 2 != 0:
            odd += str(num)
        else:
            even += str(num)

    return int(odd) + int(even)&lt;/code&gt;&lt;/pre&gt;

  &lt;h3 style=&quot;margin:1.35em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;&quot;&gt;더 간단한 풀이&lt;/h3&gt;
  &lt;pre style=&quot;margin:1em 0 1.2em;padding:1.05em 1.1em;background:#101418;color:#f6f8fb;border-radius:8px;overflow-x:auto;font-size:.92em;line-height:1.68;&quot;&gt;&lt;code&gt;def solution(num_list):
    odd = ''.join(str(num) for num in num_list if num % 2 != 0)
    even = ''.join(str(num) for num in num_list if num % 2 == 0)
    return int(odd) + int(even)&lt;/code&gt;&lt;/pre&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;리스트에 홀수와 짝수가 적어도 한 개씩 있다는 조건이 있으므로 &lt;code&gt;int(odd)&lt;/code&gt;, &lt;code&gt;int(even)&lt;/code&gt;을 바로 사용할 수 있습니다.&lt;/p&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;7. 입출력 예로 빠르게 검산하기&lt;/h2&gt;

  &lt;div style=&quot;overflow-x:auto;margin:1.25em 0 1.55em;&quot;&gt;
    &lt;table style=&quot;width:100%;border-collapse:collapse;border:1px solid #e2e8f0;font-size:.96em;background:#fff;&quot;&gt;
      &lt;caption style=&quot;position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);&quot;&gt;문제별 빠른 검산 예시&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr style=&quot;background:#f6f8fb;&quot;&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;문제&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;예시&lt;/th&gt;
          &lt;th scope=&quot;col&quot; style=&quot;padding:.75em;border:1px solid #e2e8f0;text-align:left;color:#283244;&quot;&gt;결과&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;코드 처리하기&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;&quot;abc1abc1abc&quot;&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;&quot;acbac&quot;&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;등차수열&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;a=3, d=4, [True, False, False, True, True]&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;37&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;주사위 게임 2&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;a=5, b=3, c=3&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;473&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;원소들의 곱과 합&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[3, 4, 5, 2, 1]&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;1&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;이어 붙인 수&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;&lt;code&gt;[3, 4, 5, 2, 1]&lt;/code&gt;&lt;/td&gt;
          &lt;td style=&quot;padding:.75em;border:1px solid #e2e8f0;&quot;&gt;393&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;8. 실수 방지 체크리스트&lt;/h2&gt;

  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;code&gt;=&lt;/code&gt;는 값을 넣는 연산자, &lt;code&gt;==&lt;/code&gt;는 같은지 비교하는 연산자다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;문자열의 문자와 비교할 때는 &lt;code&gt;'1'&lt;/code&gt;처럼 따옴표를 붙인다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;문제 설명의 &lt;code&gt;ret&lt;/code&gt;와 실제 코드의 &lt;code&gt;answer&lt;/code&gt;를 섞어 쓰지 않는다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;곱을 누적할 때 초기값은 0이 아니라 1이다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;반복문으로 값을 모두 만든 뒤 비교해야 하는 문제인지 확인한다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;두 숫자만 같은 경우는 &lt;code&gt;a == b&lt;/code&gt; 하나만이 아니라 &lt;code&gt;b == c&lt;/code&gt;, &lt;code&gt;a == c&lt;/code&gt;도 확인한다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;9. 같이 보면 좋은 글&lt;/h2&gt;

  &lt;ul style=&quot;margin:0 0 1.25em 1.15em;padding:0;&quot;&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;파이썬 if문 기초&lt;/strong&gt;: 조건이 여러 갈래로 나뉘는 문제를 풀 때 도움이 됩니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;문자열 누적과 join 사용법&lt;/strong&gt;: 문자열을 하나씩 붙이는 문제에서 자주 나옵니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;range, enumerate, 인덱스 사용법&lt;/strong&gt;: 인덱스 홀짝을 확인해야 하는 문제와 잘 연결됩니다.&lt;/li&gt;
    &lt;li style=&quot;margin:.42em 0;&quot;&gt;&lt;strong&gt;set으로 중복 제거하기&lt;/strong&gt;: 같은 값이 몇 종류인지 확인할 때 유용합니다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h2 style=&quot;margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;&quot;&gt;마무리&lt;/h2&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;이번 문제들은 어려운 알고리즘보다 기본 문법을 정확히 쓰는 연습에 가까웠습니다. 특히 &lt;code&gt;=&lt;/code&gt;와 &lt;code&gt;==&lt;/code&gt;, 문자열과 숫자 비교, 곱의 초기값, 변수 이름 통일은 초반에 자주 틀리는 부분이라 따로 기록해둘 만했습니다.&lt;/p&gt;

  &lt;p style=&quot;margin:0 0 1.12em;&quot;&gt;다음에 비슷한 문제를 풀 때는 먼저 “무엇을 누적하는지”, “초기값이 무엇이어야 하는지”, “조건 비교와 값 변경을 헷갈리지 않았는지”부터 확인하려고 합니다. 이렇게 체크 순서를 만들어두면 코드가 훨씬 안정적으로 정리됩니다.&lt;/p&gt;
&lt;/article&gt;</description>
      <category>AI/Coding_Test</category>
      <category>등차수열</category>
      <category>원소들의곱과합</category>
      <category>이어붙인수</category>
      <category>주사위게임2</category>
      <category>코드처리하기</category>
      <category>코딩기초트레이닝</category>
      <category>코딩테스트</category>
      <category>파이썬</category>
      <category>파이썬기초</category>
      <category>프로그래머스</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/106</guid>
      <comments>https://onethingflow.tistory.com/entry/Day5-Programmers-Coding-Test#entry106comment</comments>
      <pubDate>Sat, 11 Jul 2026 10:09:58 +0900</pubDate>
    </item>
    <item>
      <title>Day4)Programmers Coding Test</title>
      <link>https://onethingflow.tistory.com/entry/Day4Programmers-Coding-Test</link>
      <description>&lt;!--
티스토리 제목 추천:
프로그래머스 코딩 기초: 배수, 공배수, 홀짝, 조건문 문제 풀이 정리

메타 설명 추천:
프로그래머스 코딩 기초 트레이닝의 n의 배수, 공배수, 홀짝에 따라 다른 값 반환하기, 조건 문자열, flag에 따라 다른 값 반환하기 문제를 풀며 나머지 연산자, 조건문, 삼항 표현식, sum과 range 사용법을 초보자 관점에서 정리했습니다.

태그 추천:
프로그래머스, 코딩테스트, 파이썬, 코딩기초트레이닝, n의배수, 공배수, 홀짝, 조건문, 나머지연산자, range, sum
--&gt;
&lt;article style=&quot;max-width: 780px; margin: 0 auto; line-height: 1.86; font-size: 17px; color: #222; word-break: keep-all;&quot;&gt;
&lt;section style=&quot;margin: 0 0 1.5em; padding: 1.35em 1.4em; border: 1px solid #dde6f2; border-radius: 8px; background: linear-gradient(135deg,#f7fbff 0%,#fff 62%,#fff7ed 100%);&quot;&gt;
&lt;p style=&quot;margin: 0 0 .8em; display: inline-block; padding: .25em .7em; border: 1px solid #d9e4f2; border-radius: 999px; background: #fff; font-size: .84em; font-weight: bold; color: #385174;&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스 코딩 기초 트레이닝&lt;/p&gt;
&lt;h1 style=&quot;margin: .1em 0 .72em; font-size: 2em; line-height: 1.28; font-weight: 800; color: #111;&quot;&gt;배수, 공배수, 홀짝, 조건문 문제 풀이 정리&lt;/h1&gt;
&lt;p style=&quot;margin: 0 0 1em; font-size: 1.08em; color: #343b46;&quot; data-ke-size=&quot;size16&quot;&gt;이번에는 프로그래머스 코딩 기초 트레이닝에서 조건문과 나머지 연산자를 사용하는 문제들을 정리했습니다. 문제 자체는 짧지만, 직접 풀어보면 변수 이름 오타, &lt;code&gt;return&lt;/code&gt; 방식, &lt;code&gt;and&lt;/code&gt;와 &lt;code&gt;&amp;amp;&lt;/code&gt;의 차이, 리스트 컴프리헨션 괄호 실수처럼 놓치기 쉬운 부분이 많았습니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;이 글은 제가 적어둔 풀이 메모를 바탕으로, 실수한 코드와 고친 코드, 더 간단한 풀이, 그리고 왜 그렇게 동작하는지를 한 번에 볼 수 있도록 정리한 기록입니다.&lt;/p&gt;
&lt;/section&gt;
&lt;div style=&quot;display: grid; grid-template-columns: repeat(3,1fr); gap: .85em; margin: 1.35em 0;&quot;&gt;
&lt;div style=&quot;border: 1px solid #e3e8ef; border-radius: 8px; background: #fff; padding: 1em;&quot;&gt;&lt;span style=&quot;display: block; font-size: .82em; color: #687182; margin-bottom: .25em;&quot;&gt;핵심 1&lt;/span&gt; &lt;b&gt;나머지 연산자로 배수 확인&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;border: 1px solid #e3e8ef; border-radius: 8px; background: #fff; padding: 1em;&quot;&gt;&lt;span style=&quot;display: block; font-size: .82em; color: #687182; margin-bottom: .25em;&quot;&gt;핵심 2&lt;/span&gt; &lt;b&gt;조건문과 한 줄 반환&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;border: 1px solid #e3e8ef; border-radius: 8px; background: #fff; padding: 1em;&quot;&gt;&lt;span style=&quot;display: block; font-size: .82em; color: #687182; margin-bottom: .25em;&quot;&gt;핵심 3&lt;/span&gt; &lt;b&gt;sum, range, 조건 비교&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote style=&quot;margin: 1.55em 0; padding: .95em 1.15em; background: #fff9e8; border-left: 4px solid #f2b705; border-radius: 8px; font-size: 1.06em; font-weight: 800; color: #584500;&quot; data-ke-style=&quot;style1&quot;&gt;오늘 문제들은 어려운 알고리즘보다 &amp;ldquo;조건을 정확히 코드로 옮기는 연습&amp;rdquo;에 가까웠습니다.&lt;/blockquote&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;1. 오늘 정리한 프로그래머스 문제 링크&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;이번 글에서 다루는 문제는 모두 프로그래머스 코딩 기초 트레이닝에 있는 문제입니다. 배수 판별, 공배수 판별, 홀짝 조건, 문자열로 주어진 비교 연산, 불리언 값에 따른 반환을 차례대로 정리했습니다.&lt;/p&gt;
&lt;div style=&quot;overflow-x: auto; margin: 1.25em 0 1.55em;&quot;&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; border: 1px solid #e2e8f0; font-size: .96em; background: #fff;&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption style=&quot;position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0);&quot;&gt;프로그래머스 문제 링크와 핵심 개념&lt;/caption&gt;
&lt;thead&gt;
&lt;tr style=&quot;background: #f6f8fb;&quot;&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;문제&lt;/th&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;공식 링크&lt;/th&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;핵심 개념&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;n의 배수&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;a style=&quot;color: #2459d6; text-decoration: none; border-bottom: 1px solid rgba(36,89,214,.25);&quot; href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181937&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;나머지가 0인지 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;공배수&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;a style=&quot;color: #2459d6; text-decoration: none; border-bottom: 1px solid rgba(36,89,214,.25);&quot; href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181936&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;두 배수 조건을 동시에 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;홀짝에 따라 다른 값 반환하기&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;a style=&quot;color: #2459d6; text-decoration: none; border-bottom: 1px solid rgba(36,89,214,.25);&quot; href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181935&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;홀수 합, 짝수 제곱합&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;조건 문자열&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;a style=&quot;color: #2459d6; text-decoration: none; border-bottom: 1px solid rgba(36,89,214,.25);&quot; href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181934&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;문자열 조건을 비교식으로 변환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;flag에 따라 다른 값 반환하기&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;a style=&quot;color: #2459d6; text-decoration: none; border-bottom: 1px solid rgba(36,89,214,.25);&quot; href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181933&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문제 보기&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;참이면 더하기, 거짓이면 빼기&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #111111; font-size: 1.34em; font-weight: 800; letter-spacing: -1px;&quot;&gt;2. n의 배수: 오타가 숨어 있어도 방심하면 안 된다&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;첫 번째 문제는 &lt;code&gt;num&lt;/code&gt;이 &lt;code&gt;n&lt;/code&gt;의 배수이면 1, 아니면 0을 반환하는 문제입니다. 배수 판별은 나머지 연산자 &lt;code&gt;%&lt;/code&gt;를 사용하면 됩니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 .8em;&quot; data-ke-size=&quot;size16&quot;&gt;처음 작성한 코드는 아래와 같았습니다.&lt;/p&gt;
&lt;pre class=&quot;properties&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(num, n):
    answer = 0
    if num % n == 0:
        answer = 1
    else:
        ansewer = 0
    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 .8em;&quot; data-ke-size=&quot;size16&quot;&gt;기본 풀이를 깔끔하게 정리하면 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(num, n):
    if num % n == 0:
        return 1
    return 0&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 .8em;&quot; data-ke-size=&quot;size16&quot;&gt;더 간단하게 쓰면 조건식의 참/거짓을 정수로 바꿀 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;dart&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(num, n):
    return int(num % n == 0)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;num % n&lt;/code&gt;은 &lt;code&gt;num&lt;/code&gt;을 &lt;code&gt;n&lt;/code&gt;으로 나눈 나머지입니다. 나머지가 0이면 정확히 나누어떨어진다는 뜻이므로 배수입니다. 그리고 &lt;code&gt;True&lt;/code&gt;는 정수로 바꾸면 1, &lt;code&gt;False&lt;/code&gt;는 0이 됩니다.&lt;/p&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;3. 공배수: 두 조건은 and로 묶기&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;두 번째 문제는 &lt;code&gt;number&lt;/code&gt;가 &lt;code&gt;n&lt;/code&gt;의 배수이면서 동시에 &lt;code&gt;m&lt;/code&gt;의 배수인지 확인하는 문제입니다. 두 조건이 모두 참이어야 하므로 &lt;code&gt;and&lt;/code&gt;를 사용합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 .8em;&quot; data-ke-size=&quot;size16&quot;&gt;가장 이해하기 쉬운 기본 풀이는 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(number, n, m):
    if number % n == 0 and number % m == 0:
        return 1
    return 0&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 .8em;&quot; data-ke-size=&quot;size16&quot;&gt;조건 표현식으로 쓰면 한 줄에 가깝게 정리할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(number, n, m):
    return 1 if number % n == 0 and number % m == 0 else 0&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 .8em;&quot; data-ke-size=&quot;size16&quot;&gt;또는 참/거짓을 바로 정수로 바꾸면 더 짧습니다.&lt;/p&gt;
&lt;pre class=&quot;autoit&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(number, n, m):
    return int(number % n == 0 and number % m == 0)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;여기서 &lt;code&gt;&amp;amp;&lt;/code&gt;를 써도 경우에 따라 동작할 수는 있지만, 논리 조건을 읽기 좋게 표현할 때는 &lt;code&gt;and&lt;/code&gt;가 더 적절합니다. &lt;code&gt;&amp;amp;&lt;/code&gt;는 기본적으로 비트 연산자이므로 초반에는 조건문에서 &lt;code&gt;and&lt;/code&gt;를 쓰는 습관을 들이는 편이 안전합니다.&lt;/p&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;4. 홀짝에 따라 다른 값 반환하기: range와 sum으로 정리하기&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;세 번째 문제는 &lt;code&gt;n&lt;/code&gt;이 홀수이면 &lt;code&gt;n&lt;/code&gt; 이하의 홀수 합을 구하고, 짝수이면 &lt;code&gt;n&lt;/code&gt; 이하의 짝수 제곱합을 구하는 문제입니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(n):
    if n % 2 == 1:
        return sum(range(1, n + 1, 2))
    else:
        return sum(i ** 2 for i in range(2, n + 1, 2))&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;range(1, n + 1, 2)&lt;/code&gt;는 1부터 &lt;code&gt;n&lt;/code&gt;까지 2씩 증가하므로 홀수만 꺼냅니다. 반대로 &lt;code&gt;range(2, n + 1, 2)&lt;/code&gt;는 2부터 시작하므로 짝수만 꺼냅니다. 짝수일 때는 각 숫자를 제곱해야 하므로 &lt;code&gt;i ** 2&lt;/code&gt;를 사용했습니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 .8em;&quot; data-ke-size=&quot;size16&quot;&gt;주의할 점은 괄호입니다. 아래처럼 마지막에 대괄호가 하나 더 붙으면 문법 오류가 납니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #fff5f5; color: #7f1d1d; border: 1px solid #fecaca; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;return sum(i ** 2 for i in range(2, n + 1, 2)])&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;리스트로 만들어도 되지만, 여기서는 &lt;code&gt;sum(i ** 2 for i in ...)&lt;/code&gt;처럼 바로 합계를 구하는 방식이 더 간단합니다.&lt;/p&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;5. 조건 문자열: 긴 if문을 안전하게 줄이기&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;네 번째 문제는 &lt;code&gt;ineq&lt;/code&gt;와 &lt;code&gt;eq&lt;/code&gt;라는 문자열 조합에 따라 &lt;code&gt;n&lt;/code&gt;과 &lt;code&gt;m&lt;/code&gt;을 비교하는 문제입니다. 처음에는 모든 경우를 나누어 작성할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;nimrod&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(ineq, eq, n, m):
    if ineq == &quot;&amp;gt;&quot; and eq == &quot;!&quot;:
        return int(n &amp;gt; m)
    elif ineq == &quot;&amp;gt;&quot; and eq == &quot;=&quot;:
        return int(n &amp;gt;= m)
    elif ineq == &quot;&amp;lt;&quot; and eq == &quot;!&quot;:
        return int(n &amp;lt; m)
    else:
        return int(n &amp;lt;= m)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 쓰면 각 조건이 눈에 잘 보입니다. 다만 처음 작성한 것처럼 매번 &lt;code&gt;answer = 1&lt;/code&gt;, &lt;code&gt;answer = 0&lt;/code&gt;을 반복해서 넣기보다는, 비교 결과를 &lt;code&gt;int()&lt;/code&gt;로 바꾸면 코드가 짧아집니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 .8em;&quot; data-ke-size=&quot;size16&quot;&gt;조금 더 줄이고 싶다면 문자열 조합을 키로 쓰는 방법도 있습니다.&lt;/p&gt;
&lt;pre class=&quot;excel&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(ineq, eq, n, m):
    conditions = {
        &quot;&amp;gt;!&quot;: n &amp;gt; m,
        &quot;&amp;gt;=&quot;: n &amp;gt;= m,
        &quot;&amp;lt;!&quot;: n &amp;lt; m,
        &quot;&amp;lt;=&quot;: n &amp;lt;= m,
    }
    return int(conditions[ineq + eq])&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;여기서 &lt;code&gt;ineq + eq&lt;/code&gt;는 &lt;code&gt;&quot;&amp;gt;=&quot;&lt;/code&gt;, &lt;code&gt;&quot;&amp;lt;!&quot;&lt;/code&gt;처럼 하나의 문자열 키가 됩니다. 그리고 그 키에 맞는 비교 결과를 꺼내 정수로 바꿉니다. 짧게 만들려고 &lt;code&gt;eval()&lt;/code&gt;을 쓰는 풀이도 볼 수 있지만, 문자열을 코드처럼 실행하는 방식이라 학습용 글에서는 추천하지 않습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;6. flag에 따라 다른 값 반환하기: 조건 표현식 연습&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;마지막 문제는 &lt;code&gt;flag&lt;/code&gt;가 참이면 &lt;code&gt;a + b&lt;/code&gt;, 거짓이면 &lt;code&gt;a - b&lt;/code&gt;를 반환하는 문제입니다. 조건이 단순하기 때문에 한 줄 조건 표현식으로 정리하기 좋습니다.&lt;/p&gt;
&lt;pre class=&quot;ruby&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(a, b, flag):
    return a + b if flag else a - b&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;이 표현은 &amp;ldquo;&lt;code&gt;flag&lt;/code&gt;가 참이면 &lt;code&gt;a + b&lt;/code&gt;를 반환하고, 아니면 &lt;code&gt;a - b&lt;/code&gt;를 반환한다&amp;rdquo;는 뜻입니다. 조건이 짧고 결과가 두 갈래로 명확할 때 사용하면 읽기 좋습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;7. 입출력 예로 빠르게 검산하기&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;코드를 제출하기 전에는 공식 예시를 손으로 한 번 따라가 보는 것이 좋습니다. 특히 오늘 문제들은 한 줄 풀이가 가능해서 오히려 조건을 거꾸로 쓰거나 괄호를 잘못 닫아도 눈치채기 어려울 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;overflow-x: auto; margin: 1.25em 0 1.55em;&quot;&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; border: 1px solid #e2e8f0; font-size: .96em; background: #fff;&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption style=&quot;position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0);&quot;&gt;문제별 빠른 검산 예시&lt;/caption&gt;
&lt;thead&gt;
&lt;tr style=&quot;background: #f6f8fb;&quot;&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;문제&lt;/th&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;확인할 예시&lt;/th&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;검산 포인트&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;n의 배수&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;98 % 2 == 0&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;나머지가 0이면 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;공배수&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;60 % 2 == 0&lt;/code&gt;, &lt;code&gt;60 % 3 == 0&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;두 조건이 모두 참이어야 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;홀짝&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;n = 7&lt;/code&gt;, &lt;code&gt;1 + 3 + 5 + 7&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;홀수이면 홀수 합&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;조건 문자열&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;ineq = &quot;&amp;lt;&quot;&lt;/code&gt;, &lt;code&gt;eq = &quot;=&quot;&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;n &amp;lt;= m&lt;/code&gt;으로 바뀌는지 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;flag&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;flag = True&lt;/code&gt;, &lt;code&gt;flag = False&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;참이면 더하기, 거짓이면 빼기&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 예시를 하나씩 대입해보면, 코드가 짧아졌을 때도 조건을 잘못 줄였는지 확인할 수 있습니다. 특히 &lt;code&gt;and&lt;/code&gt; 조건과 &lt;code&gt;range()&lt;/code&gt;의 시작값, 끝값, 증가값은 제출 전에 한 번 더 보는 편이 안전합니다.&lt;/p&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;8. 실수 방지 체크리스트&lt;/h2&gt;
&lt;ul style=&quot;margin: 0 0 1.25em 1.15em; padding: 0;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;배수 문제는 &lt;code&gt;%&lt;/code&gt; 결과가 0인지 먼저 확인한다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;두 조건이 모두 필요할 때는 &lt;code&gt;and&lt;/code&gt;를 먼저 떠올린다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;참/거짓을 1과 0으로 바꿀 때는 &lt;code&gt;int(조건식)&lt;/code&gt;을 사용할 수 있다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;code&gt;sum()&lt;/code&gt; 안에 제너레이터를 넣을 때 괄호 짝을 꼼꼼히 확인한다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;문자열 조건을 코드처럼 실행하는 방식은 피하고, 명시적인 조건문이나 매핑을 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;9. 같이 보면 좋은 것&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;이번 글에서 헷갈린 부분은 나머지 연산자, 조건문, 반복 범위, 참/거짓 처리와 연결됩니다. 아래 주제들을 함께 보면 다음 문제를 풀 때 훨씬 안정적으로 접근할 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;margin: 0 0 1.25em 1.15em; padding: 0;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;b&gt;코딩의 덧셈&amp;middot;나눗셈&amp;middot;몫&amp;middot;나머지 완전 기초&lt;/b&gt;: &lt;code&gt;%&lt;/code&gt;와 &lt;code&gt;//&lt;/code&gt;처럼 기본 연산자가 헷갈릴 때 같이 보기 좋습니다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;b&gt;조건문 if, elif, else 기초 정리&lt;/b&gt;: 여러 조건을 순서대로 나눠야 할 때 필요한 내용입니다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;b&gt;range와 sum으로 반복 계산하기&lt;/b&gt;: 홀수 합, 짝수 합, 제곱합처럼 범위를 만들어 계산하는 문제에 도움이 됩니다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;b&gt;참과 거짓을 1과 0으로 바꾸는 방법&lt;/b&gt;: &lt;code&gt;int(True)&lt;/code&gt;, &lt;code&gt;int(False)&lt;/code&gt;를 이해하면 짧은 풀이를 읽기 쉬워집니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;오늘 정리한 문제들은 짧은 코드로 풀 수 있지만, 그 안에 중요한 기본기가 많이 들어 있었습니다. 특히 나머지 연산자, 조건문, 한 줄 반환, &lt;code&gt;sum()&lt;/code&gt;과 &lt;code&gt;range()&lt;/code&gt;는 앞으로도 계속 나올 내용입니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;다음에 비슷한 문제를 만나면 먼저 &amp;ldquo;조건이 하나인지 여러 개인지&amp;rdquo;, &amp;ldquo;참/거짓을 그대로 쓸 수 있는지&amp;rdquo;, &amp;ldquo;반복 범위가 홀수인지 짝수인지&amp;rdquo;를 확인하려고 합니다. 이렇게 문제를 읽는 순서를 정해두면 코드가 훨씬 덜 흔들릴 것 같습니다.&lt;/p&gt;
&lt;/article&gt;</description>
      <category>AI/Coding_Test</category>
      <category>day4</category>
      <category>programmers</category>
      <category>프로그래머스</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/105</guid>
      <comments>https://onethingflow.tistory.com/entry/Day4Programmers-Coding-Test#entry105comment</comments>
      <pubDate>Wed, 8 Jul 2026 21:00:39 +0900</pubDate>
    </item>
    <item>
      <title>Day3) Programmers Coding Test</title>
      <link>https://onethingflow.tistory.com/entry/Day3-Programmers-Coding-Test</link>
      <description>&lt;!--
티스토리 제목 추천:
Day3) 프로그래머스 코딩테스트: 문자열 합치기와 join 정리

메타 설명 추천:
프로그래머스 코딩 기초 트레이닝을 풀며 문자열 섞기, 문자 리스트 합치기, join 함수, f-string, return 들여쓰기 실수를 초보자 관점에서 정리했습니다.

태그 추천:
프로그래머스, 코딩테스트, 파이썬, 문자열섞기, 문자리스트를문자열로변환하기, join함수, f-string, 더크게합치기, 두수의연산값비교하기
--&gt;
&lt;article style=&quot;max-width: 780px; margin: 0 auto; line-height: 1.86; font-size: 17px; color: #222; word-break: keep-all;&quot;&gt;
&lt;section style=&quot;margin: 0 0 1.5em; padding: 1.35em 1.4em; border: 1px solid #dde6f2; border-radius: 8px; background: linear-gradient(135deg,#f7fbff 0%,#fff 62%,#fff7ed 100%);&quot;&gt;
&lt;p style=&quot;margin: 0 0 .8em; display: inline-block; padding: .25em .7em; border: 1px solid #d9e4f2; border-radius: 999px; background: #fff; font-size: .84em; font-weight: bold; color: #385174;&quot; data-ke-size=&quot;size16&quot;&gt;Day 3 Coding Test Note&lt;/p&gt;
&lt;h1 style=&quot;margin: .1em 0 .72em; font-size: 2em; line-height: 1.28; font-weight: 800; color: #111;&quot;&gt;Day3) 프로그래머스 코딩테스트: 문자열 합치기와 join 정리&lt;/h1&gt;
&lt;p style=&quot;margin: 0 0 1em; font-size: 1.08em; color: #343b46;&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 프로그래머스 코딩 기초 트레이닝을 풀면서 헷갈렸던 문자열 처리 문제들을 정리했습니다. 문제 자체는 어렵지 않았지만, 직접 코드를 쓰다 보니 &lt;code&gt;answer = 0&lt;/code&gt;으로 시작해도 되는지, &lt;code&gt;return&lt;/code&gt;을 어디에 둬야 하는지, &lt;code&gt;join()&lt;/code&gt;은 정확히 어떤 의미인지가 계속 걸렸습니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;이번 글은 정답만 나열하는 글이 아니라, 제가 실제로 헷갈렸던 코드와 그 코드를 어떻게 고쳤는지 중심으로 정리한 공부 기록입니다.&lt;/p&gt;
&lt;/section&gt;
&lt;div style=&quot;display: grid; grid-template-columns: repeat(3,1fr); gap: .85em; margin: 1.35em 0;&quot;&gt;
&lt;div style=&quot;border: 1px solid #e3e8ef; border-radius: 8px; background: #fff; padding: 1em;&quot;&gt;&lt;span style=&quot;display: block; font-size: .82em; color: #687182; margin-bottom: .25em;&quot;&gt;실수 1&lt;/span&gt; &lt;b&gt;숫자와 문자열을 섞어 더함&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;border: 1px solid #e3e8ef; border-radius: 8px; background: #fff; padding: 1em;&quot;&gt;&lt;span style=&quot;display: block; font-size: .82em; color: #687182; margin-bottom: .25em;&quot;&gt;실수 2&lt;/span&gt; &lt;b&gt;return 위치를 잘못 둠&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;border: 1px solid #e3e8ef; border-radius: 8px; background: #fff; padding: 1em;&quot;&gt;&lt;span style=&quot;display: block; font-size: .82em; color: #687182; margin-bottom: .25em;&quot;&gt;정리한 개념&lt;/span&gt; &lt;b&gt;join, f-string, 형 변환&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote style=&quot;margin: 1.55em 0; padding: .95em 1.15em; background: #fff9e8; border-left: 4px solid #f2b705; border-radius: 8px; font-size: 1.06em; font-weight: 800; color: #584500;&quot; data-ke-style=&quot;style1&quot;&gt;오늘 문제들의 핵심은 어려운 알고리즘이 아니라, 지금 다루는 값이 숫자인지 문자열인지 정확히 구분하는 것이었습니다.&lt;/blockquote&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;오늘 풀어본 문제&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;이번에 정리한 문제는 모두 프로그래머스 코딩 기초 트레이닝에 있는 문제입니다. 서로 다른 문제처럼 보이지만, 실제로는 문자열을 만들고 비교하는 감각을 익히는 흐름으로 이어져 있었습니다.&lt;/p&gt;
&lt;ul style=&quot;margin: 0 0 1.25em 1.15em; padding: 0;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;a style=&quot;color: #2459d6; text-decoration: none; border-bottom: 1px solid rgba(36,89,214,.25);&quot; href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181942&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문자열 섞기&lt;/a&gt;: 두 문자열을 한 글자씩 번갈아 붙이기&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;a style=&quot;color: #2459d6; text-decoration: none; border-bottom: 1px solid rgba(36,89,214,.25);&quot; href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181941&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문자 리스트를 문자열로 변환하기&lt;/a&gt;: 리스트의 원소를 하나의 문자열로 합치기&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;a style=&quot;color: #2459d6; text-decoration: none; border-bottom: 1px solid rgba(36,89,214,.25);&quot; href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181939&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;더 크게 합치기&lt;/a&gt;: 두 수를 서로 다른 순서로 붙여 비교하기&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;a style=&quot;color: #2459d6; text-decoration: none; border-bottom: 1px solid rgba(36,89,214,.25);&quot; href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181938&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;두 수의 연산값 비교하기&lt;/a&gt;: 붙인 값과 곱한 값을 비교하기&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;1. 문자열 섞기: answer = 0으로 시작하면 안 되는 이유&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;처음 문제는 두 문자열을 앞에서부터 한 글자씩 번갈아 붙이는 문제였습니다. 예를 들어 &lt;code&gt;&quot;aaaaa&quot;&lt;/code&gt;와 &lt;code&gt;&quot;bbbbb&quot;&lt;/code&gt;가 주어지면 결과는 &lt;code&gt;&quot;ababababab&quot;&lt;/code&gt;가 됩니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 .8em;&quot; data-ke-size=&quot;size16&quot;&gt;처음에는 아래처럼 생각했습니다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(str1, str2):
    answer = 0
    for i in range(len(str1)):
        answer += str1[i] + str2[i]
        return answer&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;이 코드는 두 가지 이유로 문제가 생깁니다.&lt;/p&gt;
&lt;div style=&quot;overflow-x: auto; margin: 1.25em 0 1.55em;&quot;&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; border: 1px solid #e2e8f0; font-size: .96em; background: #fff;&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption style=&quot;position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0);&quot;&gt;문자열 섞기 실수 정리&lt;/caption&gt;
&lt;thead&gt;
&lt;tr style=&quot;background: #f6f8fb;&quot;&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;처음 쓴 부분&lt;/th&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;문제점&lt;/th&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;고친 방향&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;answer = 0&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;0은 숫자입니다. 여기에 문자를 더하려고 하면 자료형이 맞지 않습니다.&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;answer = &quot;&quot;&lt;/code&gt;처럼 빈 문자열로 시작합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;return&lt;/code&gt;이 반복문 안에 있음&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;첫 번째 반복이 끝나는 순간 함수가 종료됩니다.&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;return&lt;/code&gt;을 반복문 밖으로 빼야 합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p style=&quot;margin: 0 0 .8em;&quot; data-ke-size=&quot;size16&quot;&gt;수정한 코드는 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(str1, str2):
    answer = &quot;&quot;

    for i in range(len(str1)):
        answer += str1[i] + str2[i]

    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;여기서 기억할 점은 간단합니다. 문자열을 쌓아갈 때는 처음 상자도 문자열이어야 합니다. 그리고 반복문으로 결과를 모두 만든 뒤에 반환해야 합니다.&lt;/p&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;2. 문자 리스트를 문자열로 변환하기: join을 이해하기&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;다음 문제는 리스트 안에 들어 있는 문자들을 순서대로 이어 붙여 하나의 문자열로 만드는 문제였습니다. 반복문으로 풀면 아래처럼 작성할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;ruby&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(arr):
    answer = ''
    for i in range(len(arr)):
        answer += arr[i]
    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;이 풀이도 흐름을 이해하기에는 좋습니다. 빈 문자열을 만들고, 리스트 안의 문자를 하나씩 더해가는 방식이기 때문입니다. 다만 같은 작업을 더 간단하게 표현하면 이렇게 쓸 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;ruby&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(arr):
    return ''.join(arr)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;''.join(arr)&lt;/code&gt;에서 앞의 &lt;code&gt;''&lt;/code&gt;는 글자와 글자 사이에 넣을 구분자입니다. 아무것도 들어 있지 않으므로 공백이나 쉼표 없이 그대로 붙입니다. 예를 들어 &lt;code&gt;['a', 'b', 'c']&lt;/code&gt;를 넣으면 &lt;code&gt;&quot;abc&quot;&lt;/code&gt;라는 하나의 문자열이 됩니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;구분자를 바꾸면 결과도 달라집니다. 예를 들어 &lt;code&gt;arr = ['apple', 'banana', 'orange']&lt;/code&gt;라고 할 때 아래처럼 사용할 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;overflow-x: auto; margin: 1.25em 0 1.55em;&quot;&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; border: 1px solid #e2e8f0; font-size: .96em; background: #fff;&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption style=&quot;position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0);&quot;&gt;join 구분자 예시&lt;/caption&gt;
&lt;thead&gt;
&lt;tr style=&quot;background: #f6f8fb;&quot;&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;사용 방법&lt;/th&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;결과&lt;/th&gt;
&lt;th style=&quot;padding: .75em; border: 1px solid #e2e8f0; text-align: left; color: #283244;&quot; scope=&quot;col&quot;&gt;언제 쓰기 좋은가&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;' '.join(arr)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;apple banana orange&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;단어 사이를 띄어 보여줄 때&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;','.join(arr)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;apple,banana,orange&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;값을 쉼표로 구분할 때&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;&lt;code&gt;'\n'.join(arr)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;각 단어가 줄바꿈되어 출력&lt;/td&gt;
&lt;td style=&quot;padding: .75em; border: 1px solid #e2e8f0;&quot;&gt;목록처럼 세로로 보여줄 때&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;처음에는 반복문 풀이로 원리를 이해하고, 익숙해지면 &lt;code&gt;join()&lt;/code&gt;으로 더 간결하게 쓰는 식으로 정리하면 좋을 것 같습니다.&lt;/p&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;3. 더 크게 합치기: 붙인 값을 비교하기&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;이 문제는 두 정수를 서로 다른 순서로 붙여본 뒤, 더 큰 값을 반환하는 문제입니다. 예를 들어 &lt;code&gt;a = 9&lt;/code&gt;, &lt;code&gt;b = 91&lt;/code&gt;이라면 &lt;code&gt;991&lt;/code&gt;과 &lt;code&gt;919&lt;/code&gt;를 비교합니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 .8em;&quot; data-ke-size=&quot;size16&quot;&gt;처음에는 이렇게 풀 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;properties&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(a, b):
    answer = 0
    case1 = str(a) + str(b)
    case2 = str(b) + str(a)

    if case1 &amp;gt; case2:
        answer = int(case1)
    else:
        answer = int(case2)

    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;방향은 맞습니다. 숫자를 바로 더하는 것이 아니라 문자열로 바꿔 붙여야 하기 때문입니다. 다만 &lt;code&gt;answer&lt;/code&gt; 변수를 꼭 만들 필요는 없고, 비교할 값을 처음부터 숫자로 바꿔두면 더 간단하게 쓸 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;python&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(a, b):
    return max(int(f&quot;{a}{b}&quot;), int(f&quot;{b}{a}&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;f&quot;{a}{b}&quot;&lt;/code&gt;는 &lt;code&gt;a&lt;/code&gt;와 &lt;code&gt;b&lt;/code&gt;를 이어 붙인 문자열을 만들어줍니다. 그 결과를 &lt;code&gt;int()&lt;/code&gt;로 바꿔서 숫자 크기로 비교하면 됩니다.&lt;/p&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;4. 두 수의 연산값 비교하기: 비슷하지만 비교 대상이 다르다&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;마지막 문제는 앞 문제와 비슷해 보이지만 비교 대상이 다릅니다. 이번에는 &lt;code&gt;a&lt;/code&gt; 뒤에 &lt;code&gt;b&lt;/code&gt;를 붙인 값과 &lt;code&gt;2 * a * b&lt;/code&gt;를 비교해야 합니다.&lt;/p&gt;
&lt;pre class=&quot;ceylon&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(a, b):
    case1, case2 = int(f&quot;{a}{b}&quot;), 2 * a * b

    return case1 if case1 &amp;gt;= case2 else case2&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;여기서는 &lt;code&gt;case1&lt;/code&gt;이 붙인 값이고, &lt;code&gt;case2&lt;/code&gt;가 곱한 값입니다. 문제 조건상 두 값이 같으면 붙인 값을 반환해야 하므로 &lt;code&gt;case1 &amp;gt;= case2&lt;/code&gt;로 비교했습니다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 .8em;&quot; data-ke-size=&quot;size16&quot;&gt;반환값만 놓고 보면 아래처럼 더 짧게 쓸 수도 있습니다.&lt;/p&gt;
&lt;pre class=&quot;python&quot; style=&quot;margin: 1em 0 1.2em; padding: 1.05em 1.1em; background: #101418; color: #f6f8fb; border-radius: 8px; overflow-x: auto; font-size: .92em; line-height: 1.68;&quot;&gt;&lt;code&gt;def solution(a, b):
    return max(int(f&quot;{a}{b}&quot;), 2 * a * b)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;다만 처음 공부할 때는 두 값을 변수로 나누어 보는 편이 더 이해하기 쉽습니다. 어떤 값과 어떤 값을 비교하는지 눈에 보이기 때문입니다.&lt;/p&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;오늘 정리한 내용&lt;/h2&gt;
&lt;ul style=&quot;margin: 0 0 1.25em 1.15em; padding: 0;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;문자열을 누적할 때는 숫자 &lt;code&gt;0&lt;/code&gt;이 아니라 빈 문자열 &lt;code&gt;&quot;&quot;&lt;/code&gt;로 시작한다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;&lt;code&gt;return&lt;/code&gt;이 반복문 안에 있으면 첫 번째 반복에서 함수가 끝날 수 있다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;리스트 안의 문자열을 합칠 때는 &lt;code&gt;''.join(arr)&lt;/code&gt;을 사용할 수 있다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;두 값을 붙여 표현할 때는 &lt;code&gt;f&quot;{a}{b}&quot;&lt;/code&gt;처럼 쓸 수 있다.&lt;/li&gt;
&lt;li style=&quot;margin: .42em 0;&quot;&gt;문제마다 비교 대상이 다르므로 &lt;code&gt;a + b&lt;/code&gt;, &lt;code&gt;ab&lt;/code&gt;, &lt;code&gt;ba&lt;/code&gt;, &lt;code&gt;2 * a * b&lt;/code&gt;를 구분해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;오늘 공부에서 가장 크게 남은 건 문법을 외우는 것보다 자료형을 먼저 보는 습관입니다. 내가 지금 숫자를 다루는지, 문자열을 다루는지에 따라 시작값도 달라지고, 비교 방식도 달라집니다.&lt;/p&gt;
&lt;h2 style=&quot;margin: 2.45em 0 .78em; font-size: 1.34em; line-height: 1.42; font-weight: 800; padding-bottom: .38em; border-bottom: 2px solid #edf0f4; color: #111;&quot; data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p style=&quot;margin: 0 0 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;Day3는 어려운 알고리즘을 배운 날이라기보다, 기본기를 다시 확인한 날에 가까웠습니다. 작은 실수였지만 &lt;code&gt;answer = 0&lt;/code&gt;과 &lt;code&gt;answer = &quot;&quot;&lt;/code&gt;의 차이, &lt;code&gt;return&lt;/code&gt;의 들여쓰기 차이를 직접 겪어보니 왜 기초 문법이 중요한지 더 확실히 느꼈습니다.&lt;/p&gt;
&lt;/article&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI/Coding_Test</category>
      <category>DAY3</category>
      <category>programmers</category>
      <category>프로그래머스</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/104</guid>
      <comments>https://onethingflow.tistory.com/entry/Day3-Programmers-Coding-Test#entry104comment</comments>
      <pubDate>Wed, 8 Jul 2026 10:59:20 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 DAY 2: 파이썬 문자열 출력과 슬라이싱 한 번에 정리</title>
      <link>https://onethingflow.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-DAY-2-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EB%AC%B8%EC%9E%90%EC%97%B4-%EC%B6%9C%EB%A0%A5%EA%B3%BC-%EC%8A%AC%EB%9D%BC%EC%9D%B4%EC%8B%B1-%ED%95%9C-%EB%B2%88%EC%97%90-%EC%A0%95%EB%A6%AC</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;오늘 배운 핵심&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그래머스 DAY 2에서는 파이썬 문자열을 다루는 가장 기본적인 감각을 익혔다. 핵심은 세 가지다. 변수에 담긴 값을 출력하는 법, 문자열을 한 글자씩 꺼내는 법, 그리고 원하는 구간만 자르는 슬라이싱이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;print(text)&lt;/b&gt;: 변수 text 안에 들어 있는 값을 출력한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;print(&quot;text&quot;)&lt;/b&gt;: 변수 값이 아니라 text라는 글자 자체를 출력한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;print(f&quot;{text}&quot;)&lt;/b&gt;: 결과는 같을 수 있지만, 단순 출력 문제에서는 굳이 필요하지 않다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;b&gt;독자 팁&lt;/b&gt;&lt;br /&gt;예제에서는 str보다 text, letter처럼 의미가 보이는 변수명을 쓰면 코드를 훨씬 쉽게 읽을 수 있다. str은 파이썬의 내장 이름이기도 해서 학습용 코드에서는 피하는 편이 좋다.&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. print(text)와 print(&quot;text&quot;)의 차이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 헷갈리기 쉬운 부분은 따옴표의 의미다. 따옴표를 붙이면 파이썬은 그것을 변수로 보지 않고, 그대로 출력해야 하는 문자열로 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 의미 언제 쓰나&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;print(text)&lt;/td&gt;
&lt;td&gt;변수에 담긴 값을 출력&lt;/td&gt;
&lt;td&gt;입력값이나 계산 결과를 보여줄 때&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;print(&quot;text&quot;)&lt;/td&gt;
&lt;td&gt;text라는 글자 자체를 출력&lt;/td&gt;
&lt;td&gt;고정 문장을 보여줄 때&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;print(f&quot;{text}&quot;)&lt;/td&gt;
&lt;td&gt;f-string으로 변수 값을 문자열에 삽입&lt;/td&gt;
&lt;td&gt;문장 안에 값을 섞어 출력할 때&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;isbl&quot;&gt;&lt;code&gt;text = input()
print(text)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력받은 내용을 그대로 출력하는 문제라면 위처럼 쓰는 것이 가장 단순하고 읽기 좋다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 문자열을 한 글자씩 출력하는 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자열은 글자들이 순서대로 모여 있는 자료형이다. 그래서 인덱스로 접근할 수도 있고, 반복문으로 글자를 바로 꺼낼 수도 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;방법 1: 인덱스로 접근하기&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;text = input()

for i in range(len(text)):
    print(text[i])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 글자의 위치, 즉 인덱스가 필요할 때 유용하다. 예를 들어 몇 번째 글자인지 함께 확인해야 한다면 이 구조가 도움이 된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;방법 2: 글자를 직접 꺼내기&lt;/h3&gt;
&lt;pre class=&quot;isbl&quot;&gt;&lt;code&gt;text = input()

for letter in text:
    print(letter)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글자 자체만 필요하다면 이 방식이 더 직관적이다. for letter in text는 &amp;ldquo;문자열에서 글자를 하나씩 꺼내겠다&amp;rdquo;는 뜻이 바로 보인다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;정리&lt;/b&gt;&lt;br /&gt;인덱스가 필요하면 range(len(text)), 글자만 필요하면 for letter in text를 쓰면 된다.&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 슬라이싱의 기본 공식&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;슬라이싱은 문자열에서 원하는 범위만 잘라내는 문법이다. 기본 모양은 아래와 같다.&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;text[start:end:step]&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;start&lt;/b&gt;: 시작 인덱스&lt;/li&gt;
&lt;li&gt;&lt;b&gt;end&lt;/b&gt;: 끝 인덱스. 단, 이 위치는 포함되지 않는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;step&lt;/b&gt;: 몇 칸씩 이동할지 정하는 값&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 중요한 규칙은 &lt;b&gt;end는 포함하지 않는다&lt;/b&gt;는 점이다. 즉 text[2:5]는 2번, 3번, 4번 인덱스까지만 가져온다.&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;text = &quot;ABCDEFGHIJ&quot;

print(text[2:5])   # CDE
print(text[:3])    # ABC
print(text[3:])    # DEFGHIJ
print(text[::2])   # ACEGI
print(text[::-1])  # JIHGFEDCBA&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 코딩테스트에서 기억할 포인트&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문자열을 그대로 출력해야 하면 print(text)를 먼저 떠올린다.&lt;/li&gt;
&lt;li&gt;한 글자씩 처리해야 하면 for letter in text가 가장 읽기 쉽다.&lt;/li&gt;
&lt;li&gt;위치 정보가 함께 필요하면 range(len(text)) 또는 enumerate(text)를 사용한다.&lt;/li&gt;
&lt;li&gt;슬라이싱에서는 끝 인덱스가 포함되지 않는다는 규칙을 꼭 기억한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DAY 2의 내용은 어렵다기보다 &amp;ldquo;문자열을 어떻게 읽고 자를 것인가&amp;rdquo;에 익숙해지는 단계였다. 작은 문법 하나를 정확히 구분해두면, 이후 문자열 문제에서 훨씬 빠르게 풀이 방향을 잡을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에 비슷한 문제를 만나면 먼저 이렇게 생각해보자. &lt;b&gt;그대로 출력할 것인가, 한 글자씩 볼 것인가, 아니면 일부만 잘라낼 것인가?&lt;/b&gt; 이 질문만 잡아도 문자열 문제의 절반은 이미 정리된다.&lt;/p&gt;
&lt;div class=&quot;ailtchrm-ai-chat&quot; style=&quot;color-scheme: initial; forced-color-adjust: initial; math-depth: initial; position-anchor: initial; text-size-adjust: initial; appearance: initial; color: initial; font: initial; font-palette: initial; font-synthesis: initial; position-area: initial; text-orientation: initial; text-rendering: initial; text-spacing-trim: initial; -webkit-font-smoothing: initial; -webkit-locale: initial; -webkit-text-orientation: initial; -webkit-writing-mode: initial; writing-mode: initial; zoom: initial; accent-color: initial; place-content: initial; place-items: initial; place-self: initial; alignment-baseline: initial; anchor-name: initial; anchor-scope: initial; animation-composition: initial; animation: initial; animation-trigger: initial; app-region: initial; aspect-ratio: initial; backdrop-filter: initial; backface-visibility: initial; background: initial; background-blend-mode: initial; baseline-shift: initial; baseline-source: initial; block-size: initial; border-block: initial; border: initial; border-radius: initial; border-collapse: initial; border-end-end-radius: initial; border-end-start-radius: initial; border-inline: initial; border-shape: initial; border-start-end-radius: initial; border-start-start-radius: initial; box-decoration-break: initial; box-shadow: initial; break-after: initial; break-before: initial; break-inside: initial; buffered-rendering: initial; caption-side: initial; caret-animation: initial; caret-color: initial; caret-shape: initial; clear: initial; clip: initial; clip-path: initial; clip-rule: initial; color-interpolation: initial; color-interpolation-filters: initial; color-rendering: initial; columns: initial; column-fill: initial; gap: initial; rule-break: initial; rule: initial; rule-inset: initial; rule-visibility-items: initial; column-span: initial; contain: initial; contain-intrinsic-block-size: initial; contain-intrinsic-size: initial; contain-intrinsic-inline-size: initial; container: initial; content: initial; content-visibility: initial; corner-shape: initial; corner-block-end-shape: initial; corner-block-start-shape: initial; counter-increment: initial; counter-reset: initial; counter-set: initial; cursor: initial; cx: initial; cy: initial; d: initial; dominant-baseline: initial; dynamic-range-limit: initial; empty-cells: initial; field-sizing: initial; fill: initial; fill-opacity: initial; fill-rule: initial; filter: initial; flex: initial; flex-wrap: initial; float: initial; flood-color: initial; flood-opacity: initial; grid: initial; grid-area: initial; height: initial; hyphenate-character: initial; hyphenate-limit-chars: initial; hyphens: initial; image-orientation: initial; image-rendering: initial; initial-letter: initial; inline-size: initial; inset-block: initial; inset-inline: initial; interactivity: initial; interest-delay: initial; interpolate-size: initial; isolation: initial; left: initial; letter-spacing: initial; lighting-color: initial; line-break: initial; list-style: initial; margin-block: initial; margin: initial; margin-inline: initial; marker: initial; mask: initial; mask-type: initial; math-shift: initial; math-style: initial; max-block-size: initial; max-inline-size: initial; max-width: initial; min-block-size: initial; min-height: initial; min-inline-size: initial; min-width: initial; mix-blend-mode: initial; object-fit: initial; object-position: initial; object-view-box: initial; offset: initial; opacity: initial; order: initial; orphans: initial; outline: initial; outline-offset: initial; overflow-anchor: initial; overflow-block: initial; overflow-clip-margin: initial; overflow-inline: initial; overflow-wrap: initial; overlay: initial; overscroll-behavior-block: initial; overscroll-behavior-inline: initial; overscroll-behavior: initial; padding-block: initial; padding: initial; padding-inline: initial; page: initial; page-orientation: initial; paint-order: initial; perspective: initial; perspective-origin: initial; position-try: initial; position-visibility: initial; print-color-adjust: initial; quotes: initial; r: initial; reading-flow: initial; reading-order: initial; resize: initial; rotate: initial; ruby-align: initial; ruby-position: initial; rule-overlap: initial; rx: initial; ry: initial; scale: initial; scroll-behavior: initial; scroll-initial-target: initial; scroll-margin-block: initial; scroll-margin: initial; scroll-margin-inline: initial; scroll-marker-group: initial; scroll-padding-block: initial; scroll-padding: initial; scroll-padding-inline: initial; scroll-snap-align: initial; scroll-snap-stop: initial; scroll-snap-type: initial; scroll-target-group: initial; scroll-timeline: initial; scrollbar-color: initial; scrollbar-gutter: initial; scrollbar-width: initial; shape-image-threshold: initial; shape-margin: initial; shape-outside: initial; shape-rendering: initial; size: initial; speak: initial; stop-color: initial; stop-opacity: initial; stroke: initial; stroke-dasharray: initial; stroke-dashoffset: initial; stroke-linecap: initial; stroke-linejoin: initial; stroke-miterlimit: initial; stroke-opacity: initial; stroke-width: initial; tab-size: initial; table-layout: initial; text-align: initial; text-align-last: initial; text-anchor: initial; text-autospace: initial; text-box: initial; text-combine-upright: initial; text-decoration: initial; text-decoration-skip-ink: initial; text-emphasis: initial; text-emphasis-position: initial; text-indent: initial; text-justify: initial; text-overflow: initial; text-shadow: initial; text-transform: initial; text-underline-offset: initial; text-underline-position: initial; text-wrap: initial; timeline-scope: initial; timeline-trigger: initial; touch-action: initial; transform: initial; transform-box: initial; transform-origin: initial; transform-style: initial; transition: initial; translate: initial; trigger-scope: initial; user-select: initial; vector-effect: initial; vertical-align: initial; view-timeline: initial; view-transition-class: initial; view-transition-group: initial; view-transition-name: initial; view-transition-scope: initial; visibility: initial; border-spacing: initial; -webkit-box-align: initial; -webkit-box-decoration-break: initial; -webkit-box-direction: initial; -webkit-box-flex: initial; -webkit-box-ordinal-group: initial; -webkit-box-orient: initial; -webkit-box-pack: initial; -webkit-box-reflect: initial; -webkit-line-break: initial; -webkit-line-clamp: initial; -webkit-mask-box-image: initial; -webkit-rtl-ordering: initial; -webkit-ruby-position: initial; -webkit-tap-highlight-color: initial; -webkit-text-combine: initial; -webkit-text-decorations-in-effect: initial; -webkit-text-fill-color: initial; -webkit-text-security: initial; -webkit-text-stroke: initial; -webkit-user-drag: initial; white-space-collapse: initial; widows: initial; width: initial; will-change: initial; word-break: initial; word-spacing: initial; x: initial; y: initial; pointer-events: none !important; display: flex !important; box-sizing: border-box; position: fixed !important; top: 0px !important; right: 0px !important; bottom: 0px !important; max-height: 100% !important; z-index: 2000000000 !important; overflow: hidden; flex-direction: column !important;&quot;&gt;&amp;nbsp;&lt;/div&gt;</description>
      <category>AI/Coding_Test</category>
      <category>programmers</category>
      <category>코딩테스트</category>
      <category>프로그래머스</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/103</guid>
      <comments>https://onethingflow.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-DAY-2-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EB%AC%B8%EC%9E%90%EC%97%B4-%EC%B6%9C%EB%A0%A5%EA%B3%BC-%EC%8A%AC%EB%9D%BC%EC%9D%B4%EC%8B%B1-%ED%95%9C-%EB%B2%88%EC%97%90-%EC%A0%95%EB%A6%AC#entry103comment</comments>
      <pubDate>Mon, 6 Jul 2026 20:20:16 +0900</pubDate>
    </item>
    <item>
      <title>편입 합격 후기: 상위 70% 모의고사에서 경희대 합격까지 바꾼 공부법</title>
      <link>https://onethingflow.tistory.com/entry/%ED%8E%B8%EC%9E%85-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0-%EA%B2%BD%ED%9D%AC%EB%8C%80-%ED%95%A9%EA%B2%A9%EA%B9%8C%EC%A7%80-%EB%A7%8C%EB%93%A0-%EB%82%98%EC%9D%98-%ED%8E%B8%EC%9E%85-%EA%B3%B5%EB%B6%80%EB%B2%952024%EB%85%84-%ED%95%A9%EA%B2%A9</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;style&gt;
.hb-post{max-width:780px;margin:0 auto;line-height:1.86;font-size:17px;color:#222;word-break:keep-all;}
.hb-post *{box-sizing:border-box;}
.hb-post h1{margin:0 0 .72em;font-size:2em;line-height:1.28;font-weight:800;color:#111;letter-spacing:0;}
.hb-post h2{margin:2.45em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;}
.hb-post h3{margin:1.75em 0 .52em;font-size:1.08em;line-height:1.45;font-weight:800;color:#172033;}
.hb-post p{margin:0 0 1.12em;}
.hb-post a{color:#2459d6;text-decoration:none;border-bottom:1px solid rgba(36,89,214,.25);}
.hb-post a:hover{border-bottom-color:#2459d6;}
.hb-post strong{font-weight:800;}
.hb-post .hb-hero{margin:0 0 1.6em;padding:1.45em 1.45em;border:1px solid #dde6f2;border-radius:8px;background:linear-gradient(135deg,#f7fbff 0%,#fff 58%,#fff7ed 100%);}
.hb-post .hb-hero p:last-child{margin-bottom:0;}
.hb-post .hb-eyebrow{display:inline-flex;margin:0 0 .85em;padding:.28em .72em;border:1px solid #d9e4f2;border-radius:999px;background:#fff;font-size:.82em;font-weight:800;color:#385174;}
.hb-post .hb-lead{font-size:1.08em;color:#343b46;}
.hb-post .hb-cover{margin:0 0 1.45em;}
.hb-post .hb-cover img{display:block;width:100%;height:auto;border-radius:8px;border:1px solid #e1e5eb;background:#f3f5f8;}
.hb-post .hb-cover figcaption{margin-top:.55em;font-size:.86em;color:#707887;text-align:center;line-height:1.55;}
.hb-post .hb-badges{display:flex;flex-wrap:wrap;gap:.5em;margin:1.05em 0 1.35em;}
.hb-post .hb-badge{display:inline-flex;align-items:center;border:1px solid #dfe5ee;border-radius:999px;padding:.28em .68em;background:#fff;font-size:.84em;font-weight:800;color:#303846;}
.hb-post .hb-kpi{display:grid;grid-template-columns:repeat(3,1fr);gap:.85em;margin:1.35em 0;}
.hb-post .hb-kpi div{border:1px solid #e3e8ef;border-radius:8px;background:#fff;padding:1em;}
.hb-post .hb-kpi span{display:block;font-size:.82em;color:#687182;margin-bottom:.25em;}
.hb-post .hb-kpi strong{display:block;font-size:1.06em;color:#101418;line-height:1.36;}
.hb-post blockquote.hb-pull{margin:1.55em 0;padding:.95em 1.15em;background:#fff9e8;border-left:4px solid #f2b705;border-radius:8px;font-size:1.06em;font-weight:800;color:#584500;}
.hb-post .hb-note{background:#f7f9fc;border:1px solid #e2e8f0;border-left:4px solid #3f75ff;border-radius:8px;padding:1.05em 1.2em;margin:1.45em 0;}
.hb-post .hb-note p{margin:0 0 .58em;}
.hb-post .hb-note p:last-child{margin-bottom:0;}
.hb-post .hb-green{background:#f4fbf8;border-color:#d7eee3;border-left-color:#2a9d8f;}
.hb-post .hb-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:.85em;margin:1.35em 0;}
.hb-post .hb-card{border:1px solid #e4e8ef;border-radius:8px;background:#fff;padding:1em;}
.hb-post .hb-card strong{display:block;margin-bottom:.28em;color:#172033;}
.hb-post .hb-card p{margin:0;color:#566173;font-size:.94em;line-height:1.72;}
.hb-post ul,.hb-post ol{margin:0 0 1.18em;padding-left:1.38em;}
.hb-post ul li{list-style:disc;}
.hb-post ol li{list-style:decimal;}
.hb-post li{margin:.38em 0;}
.hb-post .hb-table-wrap{overflow-x:auto;margin:1.45em 0;-webkit-overflow-scrolling:touch;}
.hb-post table{border-collapse:collapse;width:100%;font-size:.92em;min-width:760px;}
.hb-post th,.hb-post td{border:1px solid #e1e5eb;padding:.72em .82em;text-align:left;vertical-align:top;}
.hb-post thead th{background:#f1f4f8;font-weight:800;color:#172033;}
.hb-post tbody tr:nth-child(even){background:#fafbfc;}
.hb-post caption{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);}
.hb-post .hb-step{counter-reset:step;margin:1.3em 0;}
.hb-post .hb-step div{position:relative;margin:0 0 .72em;padding:.9em 1em .9em 3.1em;border:1px solid #e2e8f0;border-radius:8px;background:#fff;}
.hb-post .hb-step div:before{counter-increment:step;content:counter(step);position:absolute;left:1em;top:.9em;width:1.45em;height:1.45em;border-radius:999px;background:#1f3b73;color:#fff;font-size:.82em;font-weight:800;line-height:1.45em;text-align:center;}
.hb-post .hb-step strong{display:block;margin-bottom:.2em;color:#111827;}
.hb-post .hb-step p{margin:0;color:#566173;font-size:.94em;line-height:1.72;}
.hb-post .hb-small{font-size:.9em;color:#697386;}
@media (max-width:640px){
  .hb-post{font-size:16px;}
  .hb-post h1{font-size:1.58em;}
  .hb-post .hb-kpi,.hb-post .hb-grid{grid-template-columns:1fr;}
  .hb-post table{font-size:.9em;min-width:860px;}
}
&lt;/style&gt;
&lt;/div&gt;
&lt;article class=&quot;hb-post&quot;&gt;
&lt;div class=&quot;hb-hero&quot;&gt;&lt;span class=&quot;hb-eyebrow&quot;&gt;2024 편입 합격 후기&lt;/span&gt;
&lt;h1&gt;편입 합격 후기: 모의고사 성적이 무너진 뒤 바꾼 공부법&lt;/h1&gt;
&lt;p class=&quot;hb-lead&quot; data-ke-size=&quot;size16&quot;&gt;처음부터 잘했던 합격 후기는 아닙니다. 편입영어 단어는 외워도 금방 흐려졌고, 편입수학은 개념을 봐도 기출 앞에서 손이 멈췄습니다. 시험이 가까워질수록 불안해서 자료를 더 찾았지만, 성적은 생각만큼 움직이지 않았습니다. 그때 알았습니다. 제게 먼저 필요했던 건 더 많은 공부가 아니라 &lt;b&gt;공부 순서의 정리&lt;/b&gt;였습니다.&lt;/p&gt;
&lt;div class=&quot;hb-badges&quot;&gt;&lt;span class=&quot;hb-badge&quot;&gt;경희대 편입&lt;/span&gt; &lt;span class=&quot;hb-badge&quot;&gt;편입영어&lt;/span&gt; &lt;span class=&quot;hb-badge&quot;&gt;편입수학&lt;/span&gt; &lt;span class=&quot;hb-badge&quot;&gt;기출 분석&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 마지막까지 붙잡은 핵심은 단순했습니다. &lt;b&gt;기출을 먼저 보고, 필요한 개념을 채우고, 다시 기출로 확인하는 것&lt;/b&gt;. 이 글은 그 과정을 최대한 솔직하게 정리한 편입 공부 후기입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;figure class=&quot;hb-cover&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dna/rKqd5/dJMcagGbpNv/AAAAAAAAAAAAAAAAAAAAAE5TxWNlOsh2Ai68HCygZgGc-bMUFC7YZQhuSEBREKmG/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&amp;amp;expires=1785509999&amp;amp;allow_ip=&amp;amp;allow_referer=&amp;amp;signature=wpLkJfTVGZy0Ke8D8oTgEAaux0g%3D&quot; alt=&quot;10월 편입 모의고사 영어 성적표&quot; /&gt;
&lt;figcaption&gt;10월 모의고사 결과입니다. 이후에도 성적이 안정적으로 올라간 것이 아니라 계속 흔들렸고, 이때부터 학교별 기출 정리 방식과 마지막 한 달 루틴을 다시 잡기 시작했습니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;div class=&quot;hb-kpi&quot;&gt;
&lt;div&gt;&lt;span&gt;핵심 전략&lt;/span&gt; &lt;b&gt;기출 &amp;rarr; 개념 &amp;rarr; 다시 기출&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;가장 큰 변화&lt;/span&gt; &lt;b&gt;공부량보다 우선순위 정리&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;마지막 한 달&lt;/span&gt; &lt;b&gt;새 자료보다 반복 구조 고정&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote class=&quot;hb-pull&quot; data-ke-style=&quot;style1&quot;&gt;편입은 개념을 많이 아는 시험이라기보다, 제한된 시간 안에 학교가 반복해서 묻는 것을 정확히 처리하는 시험에 가깝다고 느꼈습니다.&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;처음부터 잘했던 수험생활은 아니었습니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;편입을 준비하면서 가장 많이 들었던 말은 &quot;개념부터 완벽하게 끝내야 한다&quot;는 말이었습니다. 저도 처음에는 그 말이 맞다고 생각했습니다. 기본서를 붙잡고, 강의를 듣고, 단어장을 반복해서 보면 언젠가 점수가 올라갈 거라고 믿었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 실제 공부는 생각처럼 흘러가지 않았습니다. 편입영어 단어는 외워도 금방 희미해졌고, 편입수학은 개념을 볼 때는 이해한 것 같은데 기출문제 앞에서는 손이 멈췄습니다. 자료를 더 모으면 불안이 줄어들 것 같아 이것저것 찾아보기도 했고, 여러 학교 준비를 동시에 생각하다 보니 공부 방향이 계속 흔들렸습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 시험이 가까워졌을 때 모의고사 성적이 기대보다 낮게 나오면서 마음이 많이 무너졌습니다. 정확한 순위를 하나의 숫자로 단정하기는 어렵지만, 당시 제 체감은 &quot;이 상태로는 합격권과 멀다&quot;에 가까웠습니다. 그때부터 저는 공부 방식을 완전히 바꿨습니다.&lt;/p&gt;
&lt;div class=&quot;hb-note hb-green&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;읽기 전에&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 &quot;이대로 하면 무조건 합격한다&quot;는 식의 이야기가 아닙니다. 제가 실제로 흔들렸던 과정, 마지막에 효과를 본 공부 순서, 그리고 지금 다시 준비한다면 꼭 지킬 기준을 솔직하게 정리한 글입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;먼저, 제가 버린 공부 방식이 있었습니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 돌아보면 초반의 저는 공부를 안 한 것이 아니라, 불안한 만큼 이것저것 붙잡았습니다. 강의를 하나 더 들으면 괜찮아질 것 같았고, 새로운 자료를 찾으면 놓친 부분이 채워질 것 같았습니다. 그런데 그렇게 할수록 하루는 바빴지만, 정작 시험장에서 쓸 수 있는 실력은 천천히 늘었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 아래 세 가지는 시험이 가까워질수록 과감하게 줄였습니다. 완전히 나쁜 공부라서가 아니라, 당시 제 상황에서는 점수로 이어지는 속도가 너무 느렸기 때문입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개념을 처음부터 끝까지 완벽하게 정리한 뒤에야 문제를 풀려고 하는 방식&lt;/li&gt;
&lt;li&gt;불안할 때마다 새 자료와 새 강의를 추가하면서 기존 오답을 밀어두는 방식&lt;/li&gt;
&lt;li&gt;많이 공부했다는 느낌은 남지만, 어떤 약점이 줄었는지 설명하지 못하는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공부 방향을 바꾼 뒤에는 하루를 평가하는 기준도 달라졌습니다. 예전에는 &quot;오늘 몇 시간 앉아 있었는가&quot;를 먼저 봤다면, 이후에는 &quot;오늘 다시 틀리지 않게 만든 문제가 있는가&quot;를 봤습니다. 이 차이가 생각보다 컸습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 공부량보다 먼저 고쳐야 했던 것은 공부 순서였습니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성적이 나오지 않을 때 저는 공부 시간이 부족해서만 그런 줄 알았습니다. 그래서 더 오래 앉아 있으려고 했고, 더 많은 자료를 보려고 했습니다. 하지만 시간이 지나면서 문제는 공부량보다 공부 순서에 있다는 것을 느꼈습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;편입 시험은 범위가 넓습니다. 편입영어는 어휘, 문법, 논리, 독해가 모두 나오고, 편입수학은 미분, 적분, 선형대수, 공업수학까지 학교에 따라 넓게 출제됩니다. 이 모든 것을 같은 비중으로 완벽하게 공부하려고 하면 시간이 너무 오래 걸립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 저는 &quot;개념을 다 끝낸 다음 문제를 풀자&quot;는 생각을 버렸습니다. 대신 기출을 먼저 보면서 시험이 실제로 무엇을 묻는지 확인했습니다. 처음부터 맞히려고 기출을 본 것이 아닙니다. 제가 기출에서 확인한 것은 정답이 아니라 방향이었습니다.&lt;/p&gt;
&lt;div class=&quot;hb-grid&quot;&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;b&gt;학교별 유형&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 학교가 자주 내는 문제 형태가 무엇인지 먼저 확인했습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;b&gt;반복 단원&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매년 비슷하게 등장하는 단원과 거의 나오지 않는 단원을 구분했습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;b&gt;오답 원인&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개념 부족, 계산 실수, 시간 부족, 선지 판단 실수를 따로 나눴습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;b&gt;실전 연결&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개념을 봤다면 반드시 같은 유형의 기출로 다시 확인했습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 기출을 먼저 보면 버려야 할 공부도 보입니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기출을 먼저 보는 가장 큰 장점은 우선순위가 생긴다는 점입니다. 수험생활에서 불안한 사람일수록 모든 것을 다 하려고 합니다. 저도 그랬습니다. 새로운 강의, 새로운 자료, 새로운 단어장, 새로운 문제집을 보면 놓치면 안 될 것 같았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 시험 직전에는 &quot;더 많이 하는 것&quot;보다 &quot;점수로 연결되는 것을 남기는 것&quot;이 중요했습니다. 기출을 보면 어떤 부분은 매년 반복되고, 어떤 부분은 생각보다 비중이 작습니다. 자주 나오는 유형은 깊게 공부하고, 자주 나오지 않는 부분은 최소한의 기준만 세워야 했습니다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;기출 분석 기준&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;기출에서 본 것&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;확인한 질문&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;다음 행동&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;반복 출제 단원&lt;/td&gt;
&lt;td&gt;최근 몇 년 동안 계속 나오는가?&lt;/td&gt;
&lt;td&gt;개념과 대표 풀이를 우선 정리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;시간이 오래 걸린 문제&lt;/td&gt;
&lt;td&gt;몰라서 오래 걸렸는가, 풀이가 길었는가?&lt;/td&gt;
&lt;td&gt;빠른 풀이와 계산 단축법 정리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;영어 오답&lt;/td&gt;
&lt;td&gt;단어를 몰랐는가, 문장 구조를 놓쳤는가?&lt;/td&gt;
&lt;td&gt;어휘, 구문, 선지 판단으로 분류&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;학교별 차이&lt;/td&gt;
&lt;td&gt;이 학교가 좋아하는 유형이 있는가?&lt;/td&gt;
&lt;td&gt;학교별 기출 분석표를 따로 작성&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 공부하면 막연함이 줄어듭니다. &quot;공부를 많이 해야 한다&quot;가 아니라 &quot;이 학교에서 자주 나오는 이 유형을 줄여야 한다&quot;로 바뀌기 때문입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 편입영어는 단어를 많이 외우는 것보다 오래 남기는 방식이 중요했습니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;편입영어에서 어휘는 정말 중요합니다. 독해를 잘하려고 해도 핵심 단어를 모르면 문장이 막히고, 논리 문제에서도 단어의 뉘앙스를 모르면 선지를 고르기 어렵습니다. 문제는 단어량이 많다는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 처음에 단어를 무작정 반복했습니다. 그런데 하루 이틀 지나면 까먹는 단어가 많았습니다. 그래서 단어를 외우는 방식을 바꿨습니다. 단순히 뜻 하나를 외우는 것이 아니라, 단어에 이미지, 소리, 어원, 예문을 붙여서 기억하려고 했습니다.&lt;/p&gt;
&lt;div class=&quot;hb-step&quot;&gt;
&lt;div&gt;&lt;b&gt;1회독: 훑어보기&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음부터 완벽히 외우려 하지 않고, 단어를 빠르게 만나며 익숙하게 만들었습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;b&gt;2회독: 뜻 떠올리기&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뜻을 가리고 바로 떠올리는지 확인했습니다. 오래 고민해야 하는 단어는 따로 표시했습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;b&gt;3회독: 동의어 연결&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;편입영어는 선지에서 비슷한 의미를 바꿔 묻는 경우가 많아서 동의어와 반의어를 함께 봤습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;b&gt;4회독: 기출 문장 확인&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단어장 안의 뜻이 아니라 실제 독해 문장에서 어떤 느낌으로 쓰이는지 확인했습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단어장만 따로 보면 시험과 분리되기 쉽습니다. 그래서 마지막에는 반드시 기출 문장으로 돌아갔습니다. 단어가 실제 독해에서 어떻게 쓰이는지 확인해야 기억도 오래가고, 문제를 풀 때도 바로 떠올랐습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 편입수학은 개념을 오래 붙잡기보다 적용력을 먼저 확인했습니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;편입수학은 개념 자체도 어렵지만, 더 힘든 부분은 &quot;알고 있다고 생각한 개념이 문제에서 안 풀리는 순간&quot;입니다. 저도 강의를 들을 때는 이해한 것 같았는데, 기출문제를 풀면 어디서 시작해야 할지 막히는 경우가 많았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 수학도 기출을 먼저 봤습니다. 처음부터 모든 문제를 풀려고 하지 않았습니다. 대신 문제 옆에 &quot;이 문제는 어떤 개념을 쓰는 문제인가?&quot;를 표시했습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;미분 문제처럼 보이지만 실제로는 극값 조건을 묻는 문제인지&lt;/li&gt;
&lt;li&gt;적분 계산보다 치환 아이디어가 중요한 문제인지&lt;/li&gt;
&lt;li&gt;선형대수에서 행렬식, 고윳값, 벡터공간 중 무엇을 묻는지&lt;/li&gt;
&lt;li&gt;공업수학에서 라플라스 변환처럼 반복되는 패턴인지&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 표시하고 나면 개념 공부의 우선순위가 보였습니다. 모든 개념을 똑같이 오래 보는 것이 아니라, 기출에서 반복되는 개념부터 다시 봤습니다. 그리고 개념을 본 뒤에는 반드시 같은 유형의 기출로 돌아갔습니다.&lt;/p&gt;
&lt;div class=&quot;hb-note&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오답노트에 적은 네 가지&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정답만 적지 않았습니다. 틀린 이유, 필요한 개념, 더 빠른 풀이, 다음에 떠올릴 키워드까지 적었습니다. 실전에서는 &quot;아는 문제&quot;보다 &quot;시간 안에 풀 수 있는 문제&quot;가 더 중요했기 때문입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 마지막 한 달은 새로운 것을 늘리기보다 반복 구조를 고정했습니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시험이 가까워지면 마음이 급해집니다. 주변에서 특강을 듣는다는 이야기를 들으면 나도 들어야 할 것 같고, 새로운 자료가 나오면 놓치면 안 될 것 같습니다. 저도 불안했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 마지막 한 달에는 새로운 것을 무작정 늘리기보다 매일 반복할 구조를 고정하려고 했습니다. 하루 공부가 끝났을 때 &quot;오늘 몇 시간을 했는가&quot;보다 &quot;오늘 줄인 약점이 무엇인가&quot;를 보려고 했습니다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;마지막 한 달 공부 루틴&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;시간대&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;공부 내용&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;목적&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;오전&lt;/td&gt;
&lt;td&gt;전날 오답 복습, 기출 1회분, 오답 분석&lt;/td&gt;
&lt;td&gt;전날 약점 재확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;낮&lt;/td&gt;
&lt;td&gt;학교별 기출 1회분 또는 주요 유형 풀이&lt;/td&gt;
&lt;td&gt;실전 감각 유지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;오후&lt;/td&gt;
&lt;td&gt;오답 분석, 기출 1회분, 오답 분석&lt;/td&gt;
&lt;td&gt;실전 감각 유지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;저녁&lt;/td&gt;
&lt;td&gt;기출 1회분, 오답 분석.&lt;/td&gt;
&lt;td&gt;실전 감각 요지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;자기 전&lt;/td&gt;
&lt;td&gt;오늘 틀린 문제의 키워드만 짧게 확인&lt;/td&gt;
&lt;td&gt;다음 날 반복할 약점 표시&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 학교별 기출 분석은 따로 해야 합니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;편입은 대학마다 스타일이 다릅니다. 어떤 학교는 계산 속도가 중요하고, 어떤 학교는 응용력이 중요합니다. 영어도 어떤 학교는 어휘 난도가 높고, 어떤 학교는 독해 지문 길이나 논리 문제가 부담스럽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 저는 학교별로 기출을 섞어 풀지 않으려고 했습니다. 경희대, 건국대, 세종대, 국민대처럼 지원을 생각한 학교는 따로 묶어서 봤습니다. 모집요강에서 과목, 반영 방식, 시험 시간을 확인하고, 기출문제로 실제 문제 스타일을 확인했습니다.&lt;/p&gt;
&lt;div class=&quot;hb-grid&quot;&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;b&gt;과목 비중&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영어와 수학 중 어느 쪽이 더 중요한지 먼저 확인했습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;b&gt;시험 시간&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 수에 비해 시간이 얼마나 부족한 시험인지 확인했습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;b&gt;출제 스타일&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계산형, 응용형, 독해형, 어휘형 중 어떤 성격이 강한지 봤습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;b&gt;내 강점과의 궁합&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 강한 유형이 자주 나오는 학교인지 따져봤습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 학교를 똑같이 준비하면 효율이 떨어집니다. 특히 시간이 부족한 상황에서는 학교별 전략이 필요했습니다. 저는 제 강점과 약점을 기준으로 학교별 공부 비중을 다르게 가져갔고, 이 과정이 실제 합격 가능성을 높이는 데 도움이 됐다고 생각합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 합격에 가장 도움이 된 것은 방향을 계속 수정한 태도였습니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;돌이켜보면 저는 처음부터 안정적인 수험생이 아니었습니다. 공부 외적인 것에 흔들린 적도 있었고, 자료를 모으느라 시간을 쓰기도 했고, 모의고사 결과가 좋지 않아 자신감이 떨어진 시기도 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 마지막에는 기준을 단순하게 만들었습니다.&lt;/p&gt;
&lt;blockquote class=&quot;hb-pull&quot; data-ke-style=&quot;style1&quot;&gt;기출로 방향을 잡고, 개념으로 약점을 메우고, 다시 기출로 실전력을 확인한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 순서를 지키면서 공부가 조금씩 정리됐습니다. 개념만 보면 불안했고, 기출만 풀면 같은 실수를 반복했습니다. 두 가지를 연결했을 때 비로소 점수로 이어졌습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;편입은 단순히 오래 앉아 있는 시험이 아닙니다. 물론 공부 시간은 필요합니다. 하지만 더 중요한 것은 내가 지금 무엇을 줄이고 있는지 아는 것입니다. 틀린 문제를 다시 틀리지 않게 만들고, 자주 나오는 유형을 실전 시간 안에 풀 수 있게 만드는 과정이 결국 합격에 가까워지는 길이었습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 공부가 안 될 때는 생활 습관을 바꿨습니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공부법만큼이나 도움이 됐던 것은 생활 습관을 작게 바꾼 일이었습니다. 저는 책상에 오래 앉아 있는 편이 아니었고, 집중이 끊기면 그대로 시간을 흘려보내는 날도 많았습니다. 그래서 억지로 한 장소에 버티기보다, 공부할 수 있는 장면을 하루 곳곳에 흩어놓으려고 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 효과가 있었던 방법은 &lt;b&gt;아침에 목차를 프린트해서 파일에 넣어두는 것&lt;/b&gt;이었습니다. 수학 단원 목차, 영어 문법 목차, 자주 틀리는 유형 목록을 종이로 뽑아두고, 아침에 한 번 훑었습니다. 그리고 러닝을 할 때 그 목차를 머릿속으로 다시 떠올렸습니다. 종이를 계속 들여다본다기보다, &quot;오늘 내가 봐야 할 단원이 뭐였지?&quot;, &quot;어제 틀린 유형이 어느 파트였지?&quot;를 스스로 묻는 식이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식이 좋았던 이유는 공부를 책상 앞에서만 하는 것으로 한정하지 않게 해줬기 때문입니다. 러닝 중에 목차를 떠올리면, 막연했던 공부 범위가 조금씩 정리됐습니다. 공부를 시작하기 전에 이미 머릿속에 지도가 생기는 느낌이었습니다.&lt;/p&gt;
&lt;div class=&quot;hb-grid&quot;&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;b&gt;아침 목차 프린트&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하루에 볼 단원과 오답 유형을 종이로 뽑아 파일에 넣고, 공부 시작 전에 먼저 훑었습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;b&gt;러닝 중 떠올리기&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;달리면서 목차와 전날 오답 키워드를 떠올렸습니다. 암기라기보다 머릿속 정리에 가까웠습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;b&gt;장소 바꾸기&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;집중이 끊기면 집, 도서관, 버스 안, 화장실처럼 가능한 장소를 바꿔가며 짧게라도 이어갔습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-card&quot;&gt;&lt;b&gt;짧게 다시 시작하기&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 번 흐트러졌다고 하루를 버리지 않고, 단어 10개나 오답 1문제처럼 작은 단위로 다시 시작했습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 화장실이나 버스 안에서 긴 문제를 풀 수는 없습니다. 대신 단어 뜻을 떠올리거나, 공식의 조건을 확인하거나, 오늘 볼 목차를 다시 생각하는 정도는 할 수 있었습니다. 집중이 안 된다고 멈추는 대신 공부의 형태를 바꾼 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 습관은 특히 시험 직전에 도움이 됐습니다. 불안할수록 책상 앞에서 오래 버티려고만 하면 더 지칠 때가 있습니다. 그럴 때 저는 장소를 바꾸고, 해야 할 공부를 아주 작은 단위로 쪼개서 다시 시작했습니다. 결국 중요한 것은 완벽한 하루를 만드는 것이 아니라, 흐트러진 뒤에도 다시 돌아오는 횟수를 늘리는 일이었습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;편입 준비생에게 해주고 싶은 말&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;편입은 외로운 시험입니다. 주변에서는 &quot;그게 가능하냐&quot;, &quot;너무 늦은 것 아니냐&quot;, &quot;경쟁률이 높다&quot;는 말을 할 수도 있습니다. 실제로 준비하다 보면 그런 말이 더 크게 들릴 때가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 점수가 낮게 나온 날이 곧 실패를 의미하지는 않습니다. 처음 기출을 풀었을 때 많이 틀리는 것은 당연합니다. 그것은 내가 부족하다는 증거라기보다, 앞으로 줄여야 할 약점이 드러난 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단어를 외워도 까먹을 수 있습니다. 그건 의지가 약해서가 아니라 반복 방식이 아직 맞지 않는다는 신호일 수 있습니다. 수학 개념을 봐도 문제가 안 풀릴 수 있습니다. 그건 머리가 나빠서가 아니라 개념과 기출이 아직 연결되지 않았다는 뜻일 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리: 제가 효과를 본 편입 공부법&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개념을 모두 끝낸 뒤 문제를 풀려고 하지 말고, 기출로 시험 방향을 먼저 확인한다.&lt;/li&gt;
&lt;li&gt;기출을 맞히기 위해 보는 것이 아니라, 반복 출제 유형과 내 약점을 찾기 위해 본다.&lt;/li&gt;
&lt;li&gt;편입영어 단어는 뜻 하나만 외우지 말고, 이미지와 문맥, 동의어, 기출 문장으로 연결한다.&lt;/li&gt;
&lt;li&gt;편입수학은 개념 이해에서 끝내지 말고, 어떤 문제에서 어떤 개념을 쓰는지 표시한다.&lt;/li&gt;
&lt;li&gt;오답노트에는 정답보다 틀린 이유, 필요한 개념, 빠른 풀이, 다음 키워드를 적는다.&lt;/li&gt;
&lt;li&gt;마지막 한 달에는 새로운 자료를 늘리기보다 매일 반복할 공부 구조를 고정한다.&lt;/li&gt;
&lt;li&gt;학교별 모집요강과 기출을 따로 확인하고, 학교마다 전략을 다르게 세운다.&lt;/li&gt;
&lt;li&gt;집중이 안 될 때는 장소를 바꾸고, 목차와 오답 키워드처럼 짧게 볼 수 있는 공부를 이어간다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;오늘 바로 해볼 수 있는 30분 점검&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글을 읽고 끝내기보다, 오늘 공부에 바로 적용해보면 좋겠습니다. 거창하게 계획을 다시 짤 필요는 없습니다. 저는 공부가 흔들릴 때 아래처럼 짧게 점검하는 것만으로도 방향을 다시 잡는 데 도움이 됐습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;최근 틀린 기출문제 3개를 고릅니다.&lt;/li&gt;
&lt;li&gt;각 문제를 틀린 이유를 개념 부족, 계산 실수, 시간 부족, 선지 판단 실수 중 하나로 나눕니다.&lt;/li&gt;
&lt;li&gt;그 문제를 다시 풀 때 가장 먼저 떠올려야 할 키워드 한 줄을 적습니다.&lt;/li&gt;
&lt;li&gt;오늘 본 개념이 실제 기출의 어느 문제와 연결되는지 하나만 확인합니다.&lt;/li&gt;
&lt;li&gt;내일 다시 볼 문제를 3개만 표시하고 공부를 마무리합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 공부가 막연해지지 않습니다. &quot;열심히 해야 한다&quot;에서 끝나는 것이 아니라, 내일 다시 줄일 약점이 눈에 보입니다. 편입 준비에서 저에게 가장 필요했던 것도 바로 그 구체성이었습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자주 받는 질문&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기출을 먼저 보면 너무 많이 틀려서 불안하지 않나요?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 불안합니다. 저도 그랬습니다. 하지만 초반 기출의 목적은 점수를 확인하는 것이 아니라 시험의 방향을 확인하는 것입니다. 많이 틀렸다면 그만큼 앞으로 줄일 약점이 구체적으로 보인다고 생각하는 편이 좋습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단어장은 몇 회독이 적당한가요?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정답은 없지만, 저는 한 번에 완벽히 외우려 하기보다 빠르게 여러 번 보는 방식이 더 맞았습니다. 1회독은 훑어보기, 2회독은 뜻 떠올리기, 3회독은 동의어 연결, 4회독부터는 기출 문장 확인처럼 목적을 다르게 두면 덜 지칩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시험 한 달 전에도 공부 방법을 바꿔도 되나요?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완전히 새로운 공부를 시작하는 것은 위험할 수 있습니다. 하지만 공부 방향이 잘못됐다는 것이 분명하다면, 더 늦기 전에 구조를 단순하게 바꾸는 것은 필요합니다. 저는 마지막 한 달에 새로운 자료를 늘리기보다 기출, 개념 보완, 다시 기출이라는 반복 구조를 고정한 것이 도움이 됐습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;집중이 안 될 때는 어떻게 했나요?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;억지로 같은 자리에 계속 앉아 있기보다 장소를 바꿨습니다. 도서관에서 안 되면 집으로, 집에서 안 되면 버스 안이나 잠깐 이동하는 시간에 단어와 목차를 보는 식이었습니다. 긴 공부가 안 되는 날에도 짧게 다시 시작할 수 있는 공부를 만들어두는 것이 중요했습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;편입은 무작정 오래 공부한다고 합격하는 시험은 아니었습니다. 하지만 방향을 제대로 잡고, 매일 조금씩 약점을 줄이면 결과를 바꿀 수 있는 시험이기도 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 경희대학교 편입에 합격하고 여러 학교에서 좋은 결과를 얻을 수 있었던 이유는 특별한 재능 하나 때문이 아니었습니다. 마지막까지 공부 순서를 점검했고, 불안할수록 기출로 돌아갔고, 부족한 개념을 다시 채웠기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 편입을 준비하고 있다면 오늘 공부를 이렇게 점검해보면 좋겠습니다. 내가 오늘 본 개념이 어떤 기출과 연결되는지, 내가 오늘 틀린 문제가 다음에는 어떤 키워드로 기억될 수 있는지, 그리고 내 공부가 실제 시험과 가까워지고 있는지 말입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;기출을 보고, 개념을 채우고, 다시 기출로 확인하는 것. 단순하지만 제가 가장 크게 도움을 받은 편입 공부법은 결국 이 순서였습니다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;제가 개인적으로 영어 단어를 암기하면서 기존 책들은 불편한 점이 많아서 어원, 연상 암기법을 동시에 정리한 단어장을 만드느라 고생을 많이했습니다. 아래는 개인적인 리뷰 요청을 하지 않았지만 구매하신 분들이 자발적으로 남기신 후기입니다. 어원과 암기로 외우는 편입 영어 단어장 PDF 뿐만 아니라 동의어, 영단어 테스트지, 영문법 PDF를 무료로 얻으실 수 있습니다! 구매 원하시는 분들은 아래 링크를 참조해주세요! &lt;a href=&quot;https://www.heobrain.store/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.heobrain.store/&lt;/a&gt;&lt;/blockquote&gt;
&lt;/article&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;553&quot; data-origin-height=&quot;187&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNacjT/dJMcadvL43x/jMiKljx1jkCdPD8puj72cK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNacjT/dJMcadvL43x/jMiKljx1jkCdPD8puj72cK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNacjT/dJMcadvL43x/jMiKljx1jkCdPD8puj72cK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNacjT%2FdJMcadvL43x%2FjMiKljx1jkCdPD8puj72cK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;553&quot; height=&quot;187&quot; data-origin-width=&quot;553&quot; data-origin-height=&quot;187&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;213&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJCtdW/dJMcado2sf5/DT4MZFCt235mKBVlqquLX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJCtdW/dJMcado2sf5/DT4MZFCt235mKBVlqquLX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJCtdW/dJMcado2sf5/DT4MZFCt235mKBVlqquLX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJCtdW%2FdJMcado2sf5%2FDT4MZFCt235mKBVlqquLX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;732&quot; height=&quot;213&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;213&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;673&quot; data-origin-height=&quot;197&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CxK8w/dJMcado2sf6/8kQkLjQkMh0yFqcb39pPC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CxK8w/dJMcado2sf6/8kQkLjQkMh0yFqcb39pPC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CxK8w/dJMcado2sf6/8kQkLjQkMh0yFqcb39pPC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCxK8w%2FdJMcado2sf6%2F8kQkLjQkMh0yFqcb39pPC1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;673&quot; height=&quot;197&quot; data-origin-width=&quot;673&quot; data-origin-height=&quot;197&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;805&quot; data-origin-height=&quot;675&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cVUz3d/dJMcaiqoyyH/cYSwmGzTNiOiMqCiFz7x8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cVUz3d/dJMcaiqoyyH/cYSwmGzTNiOiMqCiFz7x8k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cVUz3d/dJMcaiqoyyH/cYSwmGzTNiOiMqCiFz7x8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcVUz3d%2FdJMcaiqoyyH%2FcYSwmGzTNiOiMqCiFz7x8k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;805&quot; height=&quot;675&quot; data-origin-width=&quot;805&quot; data-origin-height=&quot;675&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;680&quot; data-origin-height=&quot;344&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6YcJu/dJMcaiqoyyG/2GYuu0VkC07Gb0eer9plMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6YcJu/dJMcaiqoyyG/2GYuu0VkC07Gb0eer9plMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6YcJu/dJMcaiqoyyG/2GYuu0VkC07Gb0eer9plMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6YcJu%2FdJMcaiqoyyG%2F2GYuu0VkC07Gb0eer9plMK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;680&quot; height=&quot;344&quot; data-origin-width=&quot;680&quot; data-origin-height=&quot;344&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;416&quot; data-origin-height=&quot;115&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwzY5r/dJMcaiqoyyF/S6EceKOFTKgGfgenRCyL5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwzY5r/dJMcaiqoyyF/S6EceKOFTKgGfgenRCyL5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwzY5r/dJMcaiqoyyF/S6EceKOFTKgGfgenRCyL5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwzY5r%2FdJMcaiqoyyF%2FS6EceKOFTKgGfgenRCyL5k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;416&quot; height=&quot;115&quot; data-origin-width=&quot;416&quot; data-origin-height=&quot;115&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;438&quot; data-origin-height=&quot;166&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EFakH/dJMcadvL43z/0ncDxc76I5c1dW1htvBypK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EFakH/dJMcadvL43z/0ncDxc76I5c1dW1htvBypK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EFakH/dJMcadvL43z/0ncDxc76I5c1dW1htvBypK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEFakH%2FdJMcadvL43z%2F0ncDxc76I5c1dW1htvBypK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;438&quot; height=&quot;166&quot; data-origin-width=&quot;438&quot; data-origin-height=&quot;166&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;456&quot; data-origin-height=&quot;217&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5LBBS/dJMcaiqoyyI/BTD2v7QAobavDzLO2YKveK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5LBBS/dJMcaiqoyyI/BTD2v7QAobavDzLO2YKveK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5LBBS/dJMcaiqoyyI/BTD2v7QAobavDzLO2YKveK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5LBBS%2FdJMcaiqoyyI%2FBTD2v7QAobavDzLO2YKveK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;456&quot; height=&quot;217&quot; data-origin-width=&quot;456&quot; data-origin-height=&quot;217&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;401&quot; data-origin-height=&quot;231&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/601Ih/dJMcaaeSDDd/DWTH0M8OnaTSISd1tz96Uk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/601Ih/dJMcaaeSDDd/DWTH0M8OnaTSISd1tz96Uk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/601Ih/dJMcaaeSDDd/DWTH0M8OnaTSISd1tz96Uk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F601Ih%2FdJMcaaeSDDd%2FDWTH0M8OnaTSISd1tz96Uk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;401&quot; height=&quot;231&quot; data-origin-width=&quot;401&quot; data-origin-height=&quot;231&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div class=&quot;ailtchrm-ai-chat&quot; style=&quot;color-scheme: initial; forced-color-adjust: initial; math-depth: initial; position-anchor: initial; text-size-adjust: initial; appearance: initial; color: initial; font: initial; font-palette: initial; font-synthesis: initial; position-area: initial; text-orientation: initial; text-rendering: initial; text-spacing-trim: initial; -webkit-font-smoothing: initial; -webkit-locale: initial; -webkit-text-orientation: initial; -webkit-writing-mode: initial; writing-mode: initial; zoom: initial; accent-color: initial; place-content: initial; place-items: initial; place-self: initial; alignment-baseline: initial; anchor-name: initial; anchor-scope: initial; animation-composition: initial; animation: initial; animation-trigger: initial; app-region: initial; aspect-ratio: initial; backdrop-filter: initial; backface-visibility: initial; background: initial; background-blend-mode: initial; baseline-shift: initial; baseline-source: initial; block-size: initial; border-block: initial; border: initial; border-radius: initial; border-collapse: initial; border-end-end-radius: initial; border-end-start-radius: initial; border-inline: initial; border-shape: initial; border-start-end-radius: initial; border-start-start-radius: initial; box-decoration-break: initial; box-shadow: initial; break-after: initial; break-before: initial; break-inside: initial; buffered-rendering: initial; caption-side: initial; caret-animation: initial; caret-color: initial; caret-shape: initial; clear: initial; clip: initial; clip-path: initial; clip-rule: initial; color-interpolation: initial; color-interpolation-filters: initial; color-rendering: initial; columns: initial; column-fill: initial; gap: initial; rule-break: initial; rule: initial; rule-inset: initial; rule-visibility-items: initial; column-span: initial; contain: initial; contain-intrinsic-block-size: initial; contain-intrinsic-size: initial; contain-intrinsic-inline-size: initial; container: initial; content: initial; content-visibility: initial; corner-shape: initial; corner-block-end-shape: initial; corner-block-start-shape: initial; counter-increment: initial; counter-reset: initial; counter-set: initial; cursor: initial; cx: initial; cy: initial; d: initial; dominant-baseline: initial; dynamic-range-limit: initial; empty-cells: initial; field-sizing: initial; fill: initial; fill-opacity: initial; fill-rule: initial; filter: initial; flex: initial; flex-wrap: initial; float: initial; flood-color: initial; flood-opacity: initial; grid: initial; grid-area: initial; height: initial; hyphenate-character: initial; hyphenate-limit-chars: initial; hyphens: initial; image-orientation: initial; image-rendering: initial; initial-letter: initial; inline-size: initial; inset-block: initial; inset-inline: initial; interactivity: initial; interest-delay: initial; interpolate-size: initial; isolation: initial; left: initial; letter-spacing: initial; lighting-color: initial; line-break: initial; list-style: initial; margin-block: initial; margin: initial; margin-inline: initial; marker: initial; mask: initial; mask-type: initial; math-shift: initial; math-style: initial; max-block-size: initial; max-inline-size: initial; max-width: initial; min-block-size: initial; min-height: initial; min-inline-size: initial; min-width: initial; mix-blend-mode: initial; object-fit: initial; object-position: initial; object-view-box: initial; offset: initial; opacity: initial; order: initial; orphans: initial; outline: initial; outline-offset: initial; overflow-anchor: initial; overflow-block: initial; overflow-clip-margin: initial; overflow-inline: initial; overflow-wrap: initial; overlay: initial; overscroll-behavior-block: initial; overscroll-behavior-inline: initial; overscroll-behavior: initial; padding-block: initial; padding: initial; padding-inline: initial; page: initial; page-orientation: initial; paint-order: initial; perspective: initial; perspective-origin: initial; position-try: initial; position-visibility: initial; print-color-adjust: initial; quotes: initial; r: initial; reading-flow: initial; reading-order: initial; resize: initial; rotate: initial; ruby-align: initial; ruby-position: initial; rule-overlap: initial; rx: initial; ry: initial; scale: initial; scroll-behavior: initial; scroll-initial-target: initial; scroll-margin-block: initial; scroll-margin: initial; scroll-margin-inline: initial; scroll-marker-group: initial; scroll-padding-block: initial; scroll-padding: initial; scroll-padding-inline: initial; scroll-snap-align: initial; scroll-snap-stop: initial; scroll-snap-type: initial; scroll-target-group: initial; scroll-timeline: initial; scrollbar-color: initial; scrollbar-gutter: initial; scrollbar-width: initial; shape-image-threshold: initial; shape-margin: initial; shape-outside: initial; shape-rendering: initial; size: initial; speak: initial; stop-color: initial; stop-opacity: initial; stroke: initial; stroke-dasharray: initial; stroke-dashoffset: initial; stroke-linecap: initial; stroke-linejoin: initial; stroke-miterlimit: initial; stroke-opacity: initial; stroke-width: initial; tab-size: initial; table-layout: initial; text-align: initial; text-align-last: initial; text-anchor: initial; text-autospace: initial; text-box: initial; text-combine-upright: initial; text-decoration: initial; text-decoration-skip-ink: initial; text-emphasis: initial; text-emphasis-position: initial; text-indent: initial; text-justify: initial; text-overflow: initial; text-shadow: initial; text-transform: initial; text-underline-offset: initial; text-underline-position: initial; text-wrap: initial; timeline-scope: initial; timeline-trigger: initial; touch-action: initial; transform: initial; transform-box: initial; transform-origin: initial; transform-style: initial; transition: initial; translate: initial; trigger-scope: initial; user-select: initial; vector-effect: initial; vertical-align: initial; view-timeline: initial; view-transition-class: initial; view-transition-group: initial; view-transition-name: initial; view-transition-scope: initial; visibility: initial; border-spacing: initial; -webkit-box-align: initial; -webkit-box-decoration-break: initial; -webkit-box-direction: initial; -webkit-box-flex: initial; -webkit-box-ordinal-group: initial; -webkit-box-orient: initial; -webkit-box-pack: initial; -webkit-box-reflect: initial; -webkit-line-break: initial; -webkit-line-clamp: initial; -webkit-mask-box-image: initial; -webkit-rtl-ordering: initial; -webkit-ruby-position: initial; -webkit-tap-highlight-color: initial; -webkit-text-combine: initial; -webkit-text-decorations-in-effect: initial; -webkit-text-fill-color: initial; -webkit-text-security: initial; -webkit-text-stroke: initial; -webkit-user-drag: initial; white-space-collapse: initial; widows: initial; width: initial; will-change: initial; word-break: initial; word-spacing: initial; x: initial; y: initial; pointer-events: none !important; display: flex !important; box-sizing: border-box; position: fixed !important; top: 0px !important; right: 0px !important; bottom: 0px !important; max-height: 100% !important; z-index: 2000000000 !important; overflow: hidden; flex-direction: column !important;&quot;&gt;&amp;nbsp;&lt;/div&gt;</description>
      <category>Certification</category>
      <category>경희대학교</category>
      <category>서성한</category>
      <category>수학</category>
      <category>연고대</category>
      <category>영어</category>
      <category>편입</category>
      <category>합격</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/102</guid>
      <comments>https://onethingflow.tistory.com/entry/%ED%8E%B8%EC%9E%85-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0-%EA%B2%BD%ED%9D%AC%EB%8C%80-%ED%95%A9%EA%B2%A9%EA%B9%8C%EC%A7%80-%EB%A7%8C%EB%93%A0-%EB%82%98%EC%9D%98-%ED%8E%B8%EC%9E%85-%EA%B3%B5%EB%B6%80%EB%B2%952024%EB%85%84-%ED%95%A9%EA%B2%A9#entry102comment</comments>
      <pubDate>Sun, 5 Jul 2026 21:41:56 +0900</pubDate>
    </item>
    <item>
      <title>비개발자의 취업 도전의 시작!</title>
      <link>https://onethingflow.tistory.com/entry/%EB%B9%84%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9D%98-%EC%B7%A8%EC%97%85-%EB%8F%84%EC%A0%84%EC%9D%98-%EC%8B%9C%EC%9E%91</link>
      <description>&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀그릿 북 커밋 챌린지로 쓴 글입니다. 읽은 책은 『만약에 내가 지금 신입이라면』입니다. 이 글은 책을 읽고 느낀 감상문이 아니라 직접 내 삶에 적용한 글입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책 링크: &lt;a href=&quot;https://teamgrit.co/store&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://teamgrit.co/store&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;바꾼 기준&lt;/span&gt; &lt;b&gt;절박함을 말이 아니라 시간표로 증명하기&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;채용공고 해석&lt;/span&gt; &lt;b&gt;AI&amp;middot;Cloud&amp;middot;SW로 고객 문제를 끝까지 해결하는 사람&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;나의 증거&lt;/span&gt; &lt;b&gt;운동, 영어, AI 서비스, AWS 프로젝트, 운영 경험&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 막힌 지점: 오래 도전했지만, 오래 멈췄다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 경희대학교 생체의공학과를 졸업한 비전공자다. 지금은 AI 엔지니어 취업을 목표로 준비하고 있다. 돌아보면 코딩과 AI에 관심은 오래 있었다. 하지만 관심이 곧 실력이 되지는 않았다. 여러 번 시작했고, 하지만 꾸준히 못하고 쉽게 포기했다. 게다가 AI가 나와서 AI 의존을 너무 심하게 하였다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 인생에서 가장 힘들었던 순간에 몸이 먼저 무너졌다. 만성 소화불량을 포함한 건강 문제로 컨디션이 흔들렸고, 컨디션이 흔들리니 마음도 쉽게 무너졌다. 어느 순간부터 나는 &amp;ldquo;오늘은 몸이 안 좋으니까&amp;rdquo;, &amp;ldquo;조금만 회복하고 다시 하자&amp;rdquo;라는 말을 자주 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 그 말이 합리적인 판단처럼 느껴졌다. 그런데 시간이 지나고 보니, 그 말은 나를 보호해준 것이 아니라 계속 같은 자리에 묶어두고 있었다. 쉬는 것도 필요하지만, 나는 쉰 것이 아니라 미뤘다. 회복한 것이 아니라 멈춰 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제는 더 이상 미룰 수 없는 나이가 되었다. 내 인생은 내가 책임져야 한다. 누가 대신 방향을 정해주지 않고, 누가 대신 건강을 회복시켜주지 않고, 누가 대신 합격시켜주지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 상태에서 팀그릿『만약에 내가 지금 신입이라면』을 읽었다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 가져온 한 가지: 절박함은 시간표다&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;절박함은 감정이 아니라 시간표다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문장에서 오래 멈췄다. 나는 스스로 절박하다고 생각했다. AI 엔지니어가 되고 싶었고, 좋은 회사에 가고 싶었고, 더 이상 뒤처지고 싶지 않았다. 그런데 내 하루를 보면 절박한 사람의 하루라고 말하기 어려웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;절박하다고 말하면서 늦게 일어났고, 건강을 회복해야 한다고 생각하면서 운동은 미뤘고, 개발자가 되고 싶다고 하면서 실제 사용자가 쓸 수 있는 서비스는 만들지 않았다. 책은 내게 이렇게 묻는 것 같았다.&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;ldquo;네가 진짜 절박한지 말하지 말고, 시간표를 보여줘라.&amp;rdquo;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 나는 먼저 하루를 바꾸기로 했다. 목표를 더 크게 적는 대신, 반복되는 시간을 먼저 바꾸기로 했다. 내 분야에서 최고가 되기 위한 시간표를 짜고, 틈틈히 운동을 하는 것이 나에게 가장 좋은 시간표였다. 쉴 때도 영어 관련 영상이나 ai 관련 영상만 보는 것이 내가 원하는 목표를 달성하기 위한 가장 좋은 시간표였다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 먼저 바꾼 것은 건강이었다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 바꾼 것은 아침이었다. 매일 오전 6시 30분에 일어나기로 했다. 일어나자마자 코어 운동과 스트레칭을 했다. 저녁에는 러닝과 헬스를 넣었다. 하루에 두 번 몸을 움직이는 구조를 만들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 몇 년 동안 몸이 무너지면 공부도 무너진다는 것을 너무 많이 겪었다. 그래서 이번에는 의지로 버티는 방식이 아니라, 몸을 먼저 회복시키는 시스템을 만들었다. 코드를 오래 쓰려면 앉아 있는 시간이 필요하고, 앉아 있는 시간을 버티려면 결국 몸이 필요했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;러닝을 시작한 지 2주 만에 10km 50분 기록을 달성했다. 기록 자체보다 더 중요했던 순간은 4km와 7km 지점이었다. 정말 멈추고 싶었다. 숨이 차고 다리가 무거웠다. 예전의 나였다면 &amp;ldquo;오늘 컨디션이 별로네&amp;rdquo;라고 말하며 멈췄을 것이다. 하지만 나는 절박하고, 이제 시작인데 더이상 포기할 수 없었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그날 그냥 10km를 내가 원하는 목표에 근접하게 달성만 한 것이 아니라, 쉽게 포기하던 나의 오래된 패턴을 끊었다. 그 경험은 개발 공부에도 그대로 이어졌다. 코딩도 결국 매일의 저항을 통과하는 일이다. 에러가 나고, 배포가 깨지고, 원하는 결과가 안 나와도 계속 남아서 원인을 찾는 일이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영어도 마찬가지였다. 오픽 시험을 준비하는데 있어서 쉽게 포기하고, 오픽에서 IM2만 계속 나오며 지쳤던 시기가 있었다. 하지만 포기하지 않고 다시 준비했고, 결국 IH를 달성했다. 이 경험도 내게 같은 메시지를 줬다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;나는 안 되는 사람이 아니라, 반복이 부족했던 사람이다.&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 채용 공고 분석의 시작:&amp;nbsp; LG CNS가 원하는 사람&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책을 읽은 뒤 가장 크게 바뀐 것은 채용공고를 읽는 방식이다. 예전에는 자격요건만 대충 훑었다. &amp;ldquo;Python 가능자&amp;rdquo;, &amp;ldquo;AI 경험 우대&amp;rdquo;, &amp;ldquo;Cloud 이해&amp;rdquo; 같은 단어만 봤다. 그런데 이제는 다르게 읽는다. 채용공고는 단어장이 아니라 회사가 지금 해결하려는 문제의 압축본이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LG CNS의 2026년 상반기 신입 AX/DX Engineer 공고를 보면 핵심은 분명했다. 디지털 금융, 지능형 정부, 고객 맞춤형 서비스, 직접 솔루션과 플랫폼 개발, 새로운 시스템 구축과 안정적 운영, 국내 성공 경험의 해외 확산. 즉 단순히 코드를 치는 사람이 아니라, 산업의 문제를 IT와 AI로 끝까지 풀어내는 사람을 찾고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공고에서 함께하고 싶은 사람으로 제시한 문장도 강했다. 새로운 시도를 즐기는 사람, 문제를 주도적으로 정의하고 해결하는 사람, 신기술을 계속 학습하고 적용하는 사람, 고객의 문제에 귀 기울이고 동료와 해결책을 만드는 사람, 글로벌 IT 전문가로 성장하고 싶은 사람.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 &amp;ldquo;공부를 많이 한 사람&amp;rdquo;보다 &amp;ldquo;문제를 발견하고, 기술로 구현하고, 운영까지 해본 사람&amp;rdquo;에 가깝다.&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;내가 잡은 LG CNS AX/DX Engineer의 핵심 해석&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코딩만 잘하는 것, AI를 잘 아는 말보다, 고객의 문제를 정의하고 AI&amp;middot;Cloud&amp;middot;Software로 구현한 뒤 고객의 문제를 해결하고 안정적으로 운영할 수 있음을 보여줘야 한다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 회사 전략까지 보니, 방향이 더 선명해졌다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.lgcns.com/kr&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.lgcns.com/kr&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1781351266419&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;LG CNS | Korea | LG CNS&quot; data-og-description=&quot;LG CNS는 AX 기반 기술 리더십과 컨설팅 역량으로 고객 비즈니스 혁신을 선도합니다.&quot; data-og-host=&quot;www.lgcns.com&quot; data-og-source-url=&quot;https://www.lgcns.com/kr&quot; data-og-url=&quot;https://www.lgcns.com/content/lgcns/kr.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/2maq6/dJMb9g5jwU0/WjzD11A6W6pI65javv7svK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/TRrjG/dJMb9eTX2lK/9wL7s0KXX0GXXd7BjMGKs0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bF3o9t/dJMb9kmk583/cAOlgqkgBDtF3GEIWvchm0/img.jpg?width=1024&amp;amp;height=576&amp;amp;face=0_0_1024_576&quot;&gt;&lt;a href=&quot;https://www.lgcns.com/kr&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.lgcns.com/kr&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/2maq6/dJMb9g5jwU0/WjzD11A6W6pI65javv7svK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/TRrjG/dJMb9eTX2lK/9wL7s0KXX0GXXd7BjMGKs0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bF3o9t/dJMb9kmk583/cAOlgqkgBDtF3GEIWvchm0/img.jpg?width=1024&amp;amp;height=576&amp;amp;face=0_0_1024_576');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;LG CNS | Korea | LG CNS&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;LG CNS는 AX 기반 기술 리더십과 컨설팅 역량으로 고객 비즈니스 혁신을 선도합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.lgcns.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LG CNS는 회사 소개에서 &amp;ldquo;IT 서비스 전문기업에서 AX No.1 기업으로&amp;rdquo;라는 방향을 내세운다. Digital Business Innovator로서 고객도 몰랐던 비즈니스 가치를 먼저 발견하고, 공공&amp;middot;금융&amp;middot;제조&amp;middot;서비스 등 다양한 산업을 AX로 전환하겠다는 메시지도 반복한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 흐름을 보면 이 방향은 더 구체적이다. 2026년 핵심 추진 과제로 글로벌 AX, RX, 사업 이행 역량 강화, 글로벌 시장 확대가 제시됐다. AX Fair 2026의 주제도 &amp;ldquo;AX, Now in Action&amp;rdquo;이었다. 가능성을 말하는 AI가 아니라 실제 현장에서 성과를 만드는 AI다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenAI와의 협업에서는 ChatGPT Enterprise 도입부터 활용, 운영까지 지원하는 OpenAI Launch Center를 신설했다. Palantir와의 파트너십에서는 FDE 조직을 만들고 제조&amp;middot;에너지&amp;middot;전자&amp;middot;물류 등 산업 전반의 고부가가치 AX 과제를 발굴하고 실행한다고 밝혔다. Cline과의 AIND 관련 발표에서는 요구사항 분석, 설계, 코딩, 테스트와 품질보증까지 AI Agent가 협업하는 엔터프라이즈 개발 플랫폼을 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 자료들을 보며 나는 LG CNS가 원하는 신입을 이렇게 다시 정의했다.&lt;/p&gt;
&lt;div&gt;LG CNS AX/DX Engineer 채용공고 분석과 나의 준비 연결채용공고와 회사 전략의 신호 내가 해석한 의미 내 포트폴리오에서 연결할 증거 앞으로 보완할 실행
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;고객 맞춤형 서비스, 고객 비즈니스 가치&lt;/td&gt;
&lt;td&gt;기술 자체보다 고객 문제를 정의하고 해결해야 한다.&lt;/td&gt;
&lt;td&gt;FluentPath에서 &amp;ldquo;한국 학습자는 말할 기회가 부족하다&amp;rdquo;는 문제를 AI 영어 스피킹 플랫폼으로 구현했다.&lt;/td&gt;
&lt;td&gt;모든 프로젝트 소개를 기능 나열이 아니라 문제-해결-결과 구조로 재작성한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI, Cloud 등 최신 IT 기술 활용 경험 우대&lt;/td&gt;
&lt;td&gt;강의 수강보다 실제 배포와 운영 경험이 중요하다.&lt;/td&gt;
&lt;td&gt;PaperHub에서 AWS Lambda, Bedrock, DynamoDB, CloudFront, CDK 기반 서버리스 AI 논문 플랫폼을 만들었다.&lt;/td&gt;
&lt;td&gt;AWS 아키텍처 다이어그램, 비용, 장애 대응, 테스트 내역을 포트폴리오에 더 명확히 남긴다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;새로운 시스템 구축과 안정적 운영&lt;/td&gt;
&lt;td&gt;로컬 장난감 프로젝트가 아니라 사용자가 접근 가능한 시스템이어야 한다.&lt;/td&gt;
&lt;td&gt;HeoBrain Marketplace, PaperHub, FluentPath, Digital Detox 서비스처럼 배포된 결과물을 만들었다.&lt;/td&gt;
&lt;td&gt;로그, 모니터링, 에러 핸들링, E2E 테스트를 추가해 운영 관점의 증거를 만든다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;공공&amp;middot;금융&amp;middot;제조&amp;middot;서비스 등 산업 AX&lt;/td&gt;
&lt;td&gt;도메인을 이해하고 산업 언어로 문제를 풀어야 한다.&lt;/td&gt;
&lt;td&gt;생체의공학 배경, KAIST 행동분석 AI, AWS 기반 폐질환 멀티모달 CDSS 프로젝트가 있다.&lt;/td&gt;
&lt;td&gt;의료&amp;middot;바이오 경험을 &amp;ldquo;산업 데이터를 이해하는 AI 엔지니어&amp;rdquo; 강점으로 정리한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;문제를 주도적으로 정의하고 해결하는 논리적 사고와 실행력&lt;/td&gt;
&lt;td&gt;시키는 일만 수행하는 사람이 아니라 먼저 구조를 잡는 사람이 필요하다.&lt;/td&gt;
&lt;td&gt;NewsHub Education Agent에서 LangGraph로 라우팅, 병렬 수집, 평가 노드, 퀴즈 생성을 설계했다.&lt;/td&gt;
&lt;td&gt;기술 선택 이유와 트레이드오프를 면접 답변으로 정리한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;해외 프로젝트와 글로벌 성장&lt;/td&gt;
&lt;td&gt;영어와 문서화 능력은 선택이 아니라 확장 가능성의 증거다.&lt;/td&gt;
&lt;td&gt;OPIc IH, 영어 학습 서비스 개발, 영어 포트폴리오 문서 작성 경험이 있다.&lt;/td&gt;
&lt;td&gt;대표 프로젝트 README와 포트폴리오를 영어 버전으로 정리한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AIND, Agentic AI 기반 개발 생산성&lt;/td&gt;
&lt;td&gt;AI를 도구처럼 쓰는 수준을 넘어, 검토와 품질관리까지 할 수 있어야 한다.&lt;/td&gt;
&lt;td&gt;HeoBrain Marketplace에서 AI 보조 개발을 하며 RLS, 통합 오류, 완성 기준을 직접 검토했다.&lt;/td&gt;
&lt;td&gt;AI가 만든 코드도 내가 책임지고 리뷰했다는 사례를 문제해결형으로 정리한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 내 포트폴리오를 다시 보니, 방향은 있었다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포트폴리오를 다시 읽어보니, 내가 해온 것들이 완전히 흩어진 것은 아니었다. 오히려 LG CNS의 방향과 연결할 수 있는 재료가 꽤 있었다. 문제는 그것을 &amp;ldquo;AI 공부했습니다&amp;rdquo; 수준으로 말하면 약해진다는 점이었다.&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;FluentPath &amp;mdash; AI English Speaking Practice Platform&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국 학습자의 &amp;ldquo;말할 기회 부족&amp;rdquo; 문제를 Llama 3.3 기반 AI 대화, OPIc 코치, 문법 교정, 쉐도잉, 롤플레이, 게임화로 해결하려 한 서비스다. 단순 챗봇이 아니라 학습 여정을 제품으로 만든 경험이다.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;PaperHub &amp;mdash; AI 논문 검색&amp;middot;요약&amp;middot;영어학습 플랫폼&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PubMed, arXiv, OpenAlex 검색과 Amazon Bedrock Nova Pro 요약, 에빙하우스 기반 단어장, CloudFront/S3/Lambda/DynamoDB/CDK를 연결한 서버리스 프로젝트다. Cloud와 AI를 &amp;ldquo;배포 가능한 서비스&amp;rdquo;로 묶어본 경험이다.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AI Content Guardian &amp;mdash; Digital Detox Agent&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스마트폰과 브라우저 사용 패턴을 분석해 콘텐츠를 분류하고, 적응형 개입 엔진으로 디지털 중독을 줄이려 한 크로스 플랫폼 서비스다. &amp;ldquo;무엇을 차단할 것인가&amp;rdquo;보다 &amp;ldquo;왜 사용자가 이탈하는가&amp;rdquo;를 먼저 본 프로젝트다.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;NewsHub Education Agent&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LangGraph 기반으로 뉴스와 YouTube RSS를 병렬 수집하고, LLM 요약 후 평가 노드로 품질을 검수하고, 퀴즈로 학습 여부를 확인하는 교육형 뉴스 에이전트다. 그래프 구조 자체가 성능과 신뢰성을 결정한다는 것을 배웠다.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Soo-Pul &amp;mdash; AWS 기반 폐질환 멀티모달 AI CDSS&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흉부 X-ray, Lab, 임상소견을 통합해 일반&amp;middot;희귀 폐질환 후보를 스크리닝하고 RAG 기반 근거 보고서를 생성한 의료 AI 프로젝트다. 나는 RAG 파이프라인, AWS 아키텍처, CloudFront/S3 배포, Lambda/SAM 배포 흐름을 맡았다.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;KAIST 인턴 &amp;mdash; 펜타닐 마우스 행동 자동 분류 AI&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YOLOv5로 마우스 골격 좌표를 추출하고 Transformer로 펜타닐&amp;middot;식염수&amp;middot;금단 상태를 분류한 프로젝트다. 라벨링 도구가 없어 React와 Flask로 직접 만들었고, 제한된 라벨 데이터에서 self-supervised pretraining을 적용했다.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 프로젝트들은 아직 완벽하지 않다. 하지만 공통점은 분명하다. 문제를 찾고, AI와 소프트웨어로 구현하고, 실제 배포와 운영을 생각했다. 앞으로 필요한 것은 프로젝트를 더 많이 만드는 것만이 아니라, 이 경험을 채용공고의 언어로 재정렬하는 일이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 올인원 커리어 전략을 적용한 방식: 자격요건이 아니라 갭을 본다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커리어 자료를 보며 가장 크게 가져온 관점은 &amp;ldquo;내가 가진 것&amp;rdquo;을 먼저 쓰는 것이 아니라 &amp;ldquo;회사가 요구하는 문제&amp;rdquo;에서 거꾸로 내려오는 방식이다. 그래서 이번에는 채용공고를 아래 순서로 읽었다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;회사 전략을 먼저 본다. LG CNS는 지금 AX, RX, AIND, OpenAI&amp;middot;Palantir 협업, 글로벌 스마트팩토리로 움직인다.&lt;/li&gt;
&lt;li&gt;직무 문장을 문제 단위로 쪼갠다. 고객 문제, 산업 도메인, 시스템 구축, 운영 안정성, AI&amp;middot;Cloud 활용으로 나눈다.&lt;/li&gt;
&lt;li&gt;내 경험을 기능이 아니라 증거로 매칭한다. &amp;ldquo;Next.js를 썼다&amp;rdquo;보다 &amp;ldquo;영어 학습 문제를 AI 스피킹 서비스로 해결했다&amp;rdquo;가 더 강하다.&lt;/li&gt;
&lt;li&gt;빈칸을 실행계획으로 바꾼다. 부족한 부분을 불안으로 두지 않고, 이번 주 해야 할 작업으로 바꾼다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식으로 보니 해야 할 일이 선명해졌다. 나는 더 많은 기술 키워드를 외우기보다, 프로젝트마다 문제 정의, 아키텍처, 장애 대응, 운영 지표, 배운 점을 정리해야 한다. 그리고 LG CNS의 AX/DX Engineer 관점에서 &amp;ldquo;고객의 문제를 기술로 해결한 사람&amp;rdquo;이라는 한 줄로 묶어야 한다.&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이력서 방향&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;AI를 공부했습니다&amp;rdquo;가 아니라 &amp;ldquo;고객/사용자 문제를 정의하고, AI 서비스로 구현하고, 배포와 운영 경험으로 증명했습니다&amp;rdquo;로 바꾼다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 달라진 점: 끌려다니는 사람에서 먼저 움직이는 사람으로&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책을 읽기 전의 나는 자주 끌려다녔다. 건강에 끌려다녔고, 감정에 끌려다녔고, 결과가 안 나오는 시간에 끌려다녔다. 남들이 이미 앞서간 것처럼 보이면 주눅 들었고, 대단해 보이는 사람을 보면 나와 다른 세계의 사람처럼 느꼈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 요즘은 생각이 바뀌고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대단해 보이는 사람도 결국 사람이다. 그들도 하루를 쓰고, 루틴을 만들고, 실패를 지나고, 다시 움직였을 뿐이다. 차이는 재능만이 아니라 시스템이다. 시간표다. 그리고 스스로 움직이는 힘이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 아직 완성된 AI 엔지니어가 아니다. 하지만 이제는 예전처럼 쉽게 멈추는 사람이 아니다. 건강을 회복하기 위해 아침과 저녁을 바꾸고 있고, 영어에서 IH를 만들었고, 러닝에서 10km를 끝까지 밀어붙였고, AI 서비스를 만들며 운영 경험을 쌓고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LG CNS에 반드시 합격하겠다는 말은 단순한 다짐이 아니다. 내 시간표를 그 수준에 맞추겠다는 선언이다. 회사가 원하는 사람이 &amp;ldquo;문제를 주도적으로 정의하고 해결하는 사람&amp;rdquo;이라면, 나는 내 삶부터 그렇게 운영해야 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9. 앞으로의 시간표&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글을 쓰고 나서 끝내지 않기 위해, 다음 실행을 시간표로 남긴다.&lt;/p&gt;
&lt;div&gt;LG CNS AX/DX Engineer 준비 시간표영역 매일 또는 매주 할 일 남길 증거
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 168px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;건강&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;오전 6시 30분 기상, 코어 운동과 스트레칭, 저녁 러닝 또는 헬스&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;기상 기록, 러닝 기록, 주간 운동 로그&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 42px;&quot;&gt;
&lt;td style=&quot;height: 42px;&quot;&gt;AI 서비스&lt;/td&gt;
&lt;td style=&quot;height: 42px;&quot;&gt;FluentPath, Digital Detox, HeoBrain 중 하나를 매일 개선 후 서비스 운영&lt;/td&gt;
&lt;td style=&quot;height: 42px;&quot;&gt;커밋 로그, 배포 URL, 변경 전후 스크린샷&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 42px;&quot;&gt;
&lt;td style=&quot;height: 42px;&quot;&gt;Cloud/운영&lt;/td&gt;
&lt;td style=&quot;height: 42px;&quot;&gt;AWS 프로젝트에 로그, 테스트, 비용 기록, 장애 대응 문서 추가&lt;/td&gt;
&lt;td style=&quot;height: 42px;&quot;&gt;아키텍처 다이어그램, CloudWatch 로그, 비용표, 회고 문서&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 42px;&quot;&gt;
&lt;td style=&quot;height: 42px;&quot;&gt;채용공고 분석&lt;/td&gt;
&lt;td style=&quot;height: 42px;&quot;&gt;지원 기업의 전략, 직무, 요구 역량을 표로 분해&lt;/td&gt;
&lt;td style=&quot;height: 42px;&quot;&gt;JD 분석표, 스킬 갭, 프로젝트 매칭표&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;글쓰기&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;읽은 책과 만든 프로젝트를 실제 적용 기록으로 작성&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;블로그 글, 포트폴리오 업데이트, 면접 답변 초안&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘의 변화는 작다. 6시 30분에 일어나고, 스트레칭을 하고, 러닝하고, 채용공고를 분석하고, 글을 남기는 것. 하지만 이 작은 것들이 쌓이면 결국 나를 증명하는 포트폴리오가 된다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;읽은 책은 사라질 수 있다. 하지만 적용한 책은 내 삶에 남는다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 이제 책을 읽은 사람이 아니라, 책을 내 시간표에 커밋한 사람이 되고 싶다. 아니, 이미 그렇게 움직이기 시작했다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고자료&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://linkareer.com/activity/326004&quot;&gt;LG CNS 2026년 상반기 신입사원 수시채용 AX/DX Engineer 공고 요약 - 링커리어&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.lgcns.com/en/careers/recruit-info&quot;&gt;LG CNS 채용 정보 페이지&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.lgcns.com/kr/company/about/lgcns&quot;&gt;LG CNS 회사소개: IT 서비스 전문기업에서 AX No.1 기업으로&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://connect.lgcns.com/language-masters/ko/moa/event/detail.245&quot;&gt;LG CNS AX Fair 2026: AX, Now in Action&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.hellot.net/news/article.html?no=108680&quot;&gt;LG CNS 2026년 3대 과제: AX&amp;middot;RX&amp;middot;사업 이행 역량 강화&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.lgcns.com/en/newsroom/press/detail.aind-2606-1&quot;&gt;LG CNS, Cline과 Agentic AI 기반 엔터프라이즈 개발 플랫폼 발표&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.lgcns.com/kr/newsroom/press/detail.genai-2602-2&quot;&gt;LG CNS, OpenAI 리셀러 파트너 활동 및 OpenAI Launch Center 신설&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.lgcns.com/kr/newsroom/press/detail.enterpriseai-2603-4&quot;&gt;LG CNS, Palantir와 전략적 파트너십 및 FDE 조직 신설&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prnewswire.com/news-releases/lg-cns-expands-north-american-ax-business-supporting-smart-factory-transformation-for-smes-302776791.html&quot;&gt;LG CNS, 북미 제조 AX 시장 확대와 Factova 소개&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/c/lgcnstube/&quot;&gt;https://www.youtube.com/c/lgcnstube/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1781351475999&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;LG CNS Expands North American AX Business, Supporting Smart Factory Transformation for SMEs&quot; data-og-description=&quot;/PRNewswire/ -- LG CNS is accelerating its expansion into the North American manufacturing AX market with advanced AI-powered smart factory solutions....&quot; data-og-host=&quot;www.prnewswire.com&quot; data-og-source-url=&quot;https://www.prnewswire.com/news-releases/lg-cns-expands-north-american-ax-business-supporting-smart-factory-transformation-for-smes-302776791.html&quot; data-og-url=&quot;https://www.prnewswire.com/news-releases/lg-cns-expands-north-american-ax-business-supporting-smart-factory-transformation-for-smes-302776791.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/isgWC/dJMb8Yp3YL4/MV9UyS4IR35032rncm3prk/img.jpg?width=1009&amp;amp;height=675&amp;amp;face=356_414_395_456&quot;&gt;&lt;a href=&quot;https://www.prnewswire.com/news-releases/lg-cns-expands-north-american-ax-business-supporting-smart-factory-transformation-for-smes-302776791.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.prnewswire.com/news-releases/lg-cns-expands-north-american-ax-business-supporting-smart-factory-transformation-for-smes-302776791.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/isgWC/dJMb8Yp3YL4/MV9UyS4IR35032rncm3prk/img.jpg?width=1009&amp;amp;height=675&amp;amp;face=356_414_395_456');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;LG CNS Expands North American AX Business, Supporting Smart Factory Transformation for SMEs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;/PRNewswire/ -- LG CNS is accelerating its expansion into the North American manufacturing AX market with advanced AI-powered smart factory solutions....&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.prnewswire.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#북커밋 #팀그릿 #AI엔지니어 #취업준비 #비전공자개발자 #LGCNS #AXDXEngineer #루틴 #러닝 #오픽IH #포트폴리오&lt;/p&gt;
&lt;div class=&quot;ailtchrm-ai-chat&quot; style=&quot;color-scheme: initial; forced-color-adjust: initial; math-depth: initial; position-anchor: initial; text-size-adjust: initial; appearance: initial; color: initial; font: initial; font-palette: initial; font-synthesis: initial; position-area: initial; text-orientation: initial; text-rendering: initial; text-spacing-trim: initial; -webkit-font-smoothing: initial; -webkit-locale: initial; -webkit-text-orientation: initial; -webkit-writing-mode: initial; writing-mode: initial; zoom: initial; accent-color: initial; place-content: initial; place-items: initial; place-self: initial; alignment-baseline: initial; anchor-name: initial; anchor-scope: initial; animation-composition: initial; animation: initial; animation-trigger: initial; app-region: initial; aspect-ratio: initial; backdrop-filter: initial; backface-visibility: initial; background: initial; background-blend-mode: initial; baseline-shift: initial; baseline-source: initial; block-size: initial; border-block: initial; border: initial; border-radius: initial; border-collapse: initial; border-end-end-radius: initial; border-end-start-radius: initial; border-inline: initial; border-shape: initial; border-start-end-radius: initial; border-start-start-radius: initial; box-decoration-break: initial; box-shadow: initial; break-after: initial; break-before: initial; break-inside: initial; buffered-rendering: initial; caption-side: initial; caret-animation: initial; caret-color: initial; caret-shape: initial; clear: initial; clip: initial; clip-path: initial; clip-rule: initial; color-interpolation: initial; color-interpolation-filters: initial; color-rendering: initial; columns: initial; column-fill: initial; gap: initial; column-rule: initial; column-span: initial; contain: initial; contain-intrinsic-block-size: initial; contain-intrinsic-size: initial; contain-intrinsic-inline-size: initial; container: initial; content: initial; content-visibility: initial; corner-shape: initial; corner-block-end-shape: initial; corner-block-start-shape: initial; counter-increment: initial; counter-reset: initial; counter-set: initial; cursor: initial; cx: initial; cy: initial; d: initial; dominant-baseline: initial; dynamic-range-limit: initial; empty-cells: initial; field-sizing: initial; fill: initial; fill-opacity: initial; fill-rule: initial; filter: initial; flex: initial; flex-wrap: initial; float: initial; flood-color: initial; flood-opacity: initial; grid: initial; grid-area: initial; height: initial; hyphenate-character: initial; hyphenate-limit-chars: initial; hyphens: initial; image-orientation: initial; image-rendering: initial; initial-letter: initial; inline-size: initial; inset-block: initial; inset-inline: initial; interactivity: initial; interest-delay: initial; interpolate-size: initial; isolation: initial; left: initial; letter-spacing: initial; lighting-color: initial; line-break: initial; list-style: initial; margin-block: initial; margin: initial; margin-inline: initial; marker: initial; mask: initial; mask-type: initial; math-shift: initial; math-style: initial; max-block-size: initial; max-inline-size: initial; max-width: initial; min-block-size: initial; min-height: initial; min-inline-size: initial; min-width: initial; mix-blend-mode: initial; object-fit: initial; object-position: initial; object-view-box: initial; offset: initial; opacity: initial; order: initial; orphans: initial; outline: initial; outline-offset: initial; overflow-anchor: initial; overflow-block: initial; overflow-clip-margin: initial; overflow-inline: initial; overflow-wrap: initial; overlay: initial; overscroll-behavior-block: initial; overscroll-behavior-inline: initial; overscroll-behavior: initial; padding-block: initial; padding: initial; padding-inline: initial; page: initial; page-orientation: initial; paint-order: initial; perspective: initial; perspective-origin: initial; position-try: initial; position-visibility: initial; print-color-adjust: initial; quotes: initial; r: initial; reading-flow: initial; reading-order: initial; resize: initial; rotate: initial; ruby-align: initial; ruby-position: initial; rx: initial; ry: initial; scale: initial; scroll-behavior: initial; scroll-initial-target: initial; scroll-margin-block: initial; scroll-margin: initial; scroll-margin-inline: initial; scroll-marker-group: initial; scroll-padding-block: initial; scroll-padding: initial; scroll-padding-inline: initial; scroll-snap-align: initial; scroll-snap-stop: initial; scroll-snap-type: initial; scroll-target-group: initial; scroll-timeline: initial; scrollbar-color: initial; scrollbar-gutter: initial; scrollbar-width: initial; shape-image-threshold: initial; shape-margin: initial; shape-outside: initial; shape-rendering: initial; size: initial; speak: initial; stop-color: initial; stop-opacity: initial; stroke: initial; stroke-dasharray: initial; stroke-dashoffset: initial; stroke-linecap: initial; stroke-linejoin: initial; stroke-miterlimit: initial; stroke-opacity: initial; stroke-width: initial; tab-size: initial; table-layout: initial; text-align: initial; text-align-last: initial; text-anchor: initial; text-autospace: initial; text-box: initial; text-combine-upright: initial; text-decoration: initial; text-decoration-skip-ink: initial; text-emphasis: initial; text-emphasis-position: initial; text-indent: initial; text-justify: initial; text-overflow: initial; text-shadow: initial; text-transform: initial; text-underline-offset: initial; text-underline-position: initial; text-wrap: initial; timeline-scope: initial; timeline-trigger: initial; touch-action: initial; transform: initial; transform-box: initial; transform-origin: initial; transform-style: initial; transition: initial; translate: initial; trigger-scope: initial; user-select: initial; vector-effect: initial; vertical-align: initial; view-timeline: initial; view-transition-class: initial; view-transition-group: initial; view-transition-name: initial; view-transition-scope: initial; visibility: initial; border-spacing: initial; -webkit-box-align: initial; -webkit-box-decoration-break: initial; -webkit-box-direction: initial; -webkit-box-flex: initial; -webkit-box-ordinal-group: initial; -webkit-box-orient: initial; -webkit-box-pack: initial; -webkit-box-reflect: initial; -webkit-line-break: initial; -webkit-line-clamp: initial; -webkit-mask-box-image: initial; -webkit-rtl-ordering: initial; -webkit-ruby-position: initial; -webkit-tap-highlight-color: initial; -webkit-text-combine: initial; -webkit-text-decorations-in-effect: initial; -webkit-text-fill-color: initial; -webkit-text-security: initial; -webkit-text-stroke: initial; -webkit-user-drag: initial; white-space-collapse: initial; widows: initial; width: initial; will-change: initial; word-break: initial; word-spacing: initial; x: initial; y: initial; pointer-events: none !important; display: flex !important; box-sizing: border-box; position: fixed !important; top: 0px !important; right: 0px !important; bottom: 0px !important; max-height: 100% !important; z-index: 2000000000 !important; overflow: hidden; flex-direction: column !important;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;ailtchrm-ai-chat&quot; style=&quot;color-scheme: initial; forced-color-adjust: initial; math-depth: initial; position-anchor: initial; text-size-adjust: initial; appearance: initial; color: initial; font: initial; font-palette: initial; font-synthesis: initial; position-area: initial; text-orientation: initial; text-rendering: initial; text-spacing-trim: initial; -webkit-font-smoothing: initial; -webkit-locale: initial; -webkit-text-orientation: initial; -webkit-writing-mode: initial; writing-mode: initial; zoom: initial; accent-color: initial; place-content: initial; place-items: initial; place-self: initial; alignment-baseline: initial; anchor-name: initial; anchor-scope: initial; animation-composition: initial; animation: initial; animation-trigger: initial; app-region: initial; aspect-ratio: initial; backdrop-filter: initial; backface-visibility: initial; background: initial; background-blend-mode: initial; baseline-shift: initial; baseline-source: initial; block-size: initial; border-block: initial; border: initial; border-radius: initial; border-collapse: initial; border-end-end-radius: initial; border-end-start-radius: initial; border-inline: initial; border-shape: initial; border-start-end-radius: initial; border-start-start-radius: initial; box-decoration-break: initial; box-shadow: initial; break-after: initial; break-before: initial; break-inside: initial; buffered-rendering: initial; caption-side: initial; caret-animation: initial; caret-color: initial; caret-shape: initial; clear: initial; clip: initial; clip-path: initial; clip-rule: initial; color-interpolation: initial; color-interpolation-filters: initial; color-rendering: initial; columns: initial; column-fill: initial; gap: initial; column-rule: initial; column-span: initial; contain: initial; contain-intrinsic-block-size: initial; contain-intrinsic-size: initial; contain-intrinsic-inline-size: initial; container: initial; content: initial; content-visibility: initial; corner-shape: initial; corner-block-end-shape: initial; corner-block-start-shape: initial; counter-increment: initial; counter-reset: initial; counter-set: initial; cursor: initial; cx: initial; cy: initial; d: initial; dominant-baseline: initial; dynamic-range-limit: initial; empty-cells: initial; field-sizing: initial; fill: initial; fill-opacity: initial; fill-rule: initial; filter: initial; flex: initial; flex-wrap: initial; float: initial; flood-color: initial; flood-opacity: initial; grid: initial; grid-area: initial; height: initial; hyphenate-character: initial; hyphenate-limit-chars: initial; hyphens: initial; image-orientation: initial; image-rendering: initial; initial-letter: initial; inline-size: initial; inset-block: initial; inset-inline: initial; interactivity: initial; interest-delay: initial; interpolate-size: initial; isolation: initial; left: initial; letter-spacing: initial; lighting-color: initial; line-break: initial; list-style: initial; margin-block: initial; margin: initial; margin-inline: initial; marker: initial; mask: initial; mask-type: initial; math-shift: initial; math-style: initial; max-block-size: initial; max-inline-size: initial; max-width: initial; min-block-size: initial; min-height: initial; min-inline-size: initial; min-width: initial; mix-blend-mode: initial; object-fit: initial; object-position: initial; object-view-box: initial; offset: initial; opacity: initial; order: initial; orphans: initial; outline: initial; outline-offset: initial; overflow-anchor: initial; overflow-block: initial; overflow-clip-margin: initial; overflow-inline: initial; overflow-wrap: initial; overlay: initial; overscroll-behavior-block: initial; overscroll-behavior-inline: initial; overscroll-behavior: initial; padding-block: initial; padding: initial; padding-inline: initial; page: initial; page-orientation: initial; paint-order: initial; perspective: initial; perspective-origin: initial; position-try: initial; position-visibility: initial; print-color-adjust: initial; quotes: initial; r: initial; reading-flow: initial; reading-order: initial; resize: initial; rotate: initial; ruby-align: initial; ruby-position: initial; rx: initial; ry: initial; scale: initial; scroll-behavior: initial; scroll-initial-target: initial; scroll-margin-block: initial; scroll-margin: initial; scroll-margin-inline: initial; scroll-marker-group: initial; scroll-padding-block: initial; scroll-padding: initial; scroll-padding-inline: initial; scroll-snap-align: initial; scroll-snap-stop: initial; scroll-snap-type: initial; scroll-target-group: initial; scroll-timeline: initial; scrollbar-color: initial; scrollbar-gutter: initial; scrollbar-width: initial; shape-image-threshold: initial; shape-margin: initial; shape-outside: initial; shape-rendering: initial; size: initial; speak: initial; stop-color: initial; stop-opacity: initial; stroke: initial; stroke-dasharray: initial; stroke-dashoffset: initial; stroke-linecap: initial; stroke-linejoin: initial; stroke-miterlimit: initial; stroke-opacity: initial; stroke-width: initial; tab-size: initial; table-layout: initial; text-align: initial; text-align-last: initial; text-anchor: initial; text-autospace: initial; text-box: initial; text-combine-upright: initial; text-decoration: initial; text-decoration-skip-ink: initial; text-emphasis: initial; text-emphasis-position: initial; text-indent: initial; text-justify: initial; text-overflow: initial; text-shadow: initial; text-transform: initial; text-underline-offset: initial; text-underline-position: initial; text-wrap: initial; timeline-scope: initial; timeline-trigger: initial; touch-action: initial; transform: initial; transform-box: initial; transform-origin: initial; transform-style: initial; transition: initial; translate: initial; trigger-scope: initial; user-select: initial; vector-effect: initial; vertical-align: initial; view-timeline: initial; view-transition-class: initial; view-transition-group: initial; view-transition-name: initial; view-transition-scope: initial; visibility: initial; border-spacing: initial; -webkit-box-align: initial; -webkit-box-decoration-break: initial; -webkit-box-direction: initial; -webkit-box-flex: initial; -webkit-box-ordinal-group: initial; -webkit-box-orient: initial; -webkit-box-pack: initial; -webkit-box-reflect: initial; -webkit-line-break: initial; -webkit-line-clamp: initial; -webkit-mask-box-image: initial; -webkit-rtl-ordering: initial; -webkit-ruby-position: initial; -webkit-tap-highlight-color: initial; -webkit-text-combine: initial; -webkit-text-decorations-in-effect: initial; -webkit-text-fill-color: initial; -webkit-text-security: initial; -webkit-text-stroke: initial; -webkit-user-drag: initial; white-space-collapse: initial; widows: initial; width: initial; will-change: initial; word-break: initial; word-spacing: initial; x: initial; y: initial; pointer-events: none !important; display: flex !important; box-sizing: border-box; position: fixed !important; top: 0px !important; right: 0px !important; bottom: 0px !important; max-height: 100% !important; z-index: 2000000000 !important; overflow: hidden; flex-direction: column !important;&quot;&gt;&amp;nbsp;&lt;/div&gt;</description>
      <category>AI</category>
      <category>Ai엔지니어</category>
      <category>AXDX Engineer</category>
      <category>LG CNS</category>
      <category>러닝</category>
      <category>루틴</category>
      <category>북커밋</category>
      <category>비전공자개발자</category>
      <category>오픽IH</category>
      <category>취업준비</category>
      <category>팀그릿</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/101</guid>
      <comments>https://onethingflow.tistory.com/entry/%EB%B9%84%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9D%98-%EC%B7%A8%EC%97%85-%EB%8F%84%EC%A0%84%EC%9D%98-%EC%8B%9C%EC%9E%91#entry101comment</comments>
      <pubDate>Sun, 14 Jun 2026 12:27:18 +0900</pubDate>
    </item>
    <item>
      <title>파이썬 입문 5편 &amp;mdash; 리스트 정렬 완전 정복: sort vs sorted, 그리고 key 하나면 끝</title>
      <link>https://onethingflow.tistory.com/entry/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%85%EB%AC%B8-5%ED%8E%B8-%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EC%A0%95%EB%A0%AC-%EC%99%84%EC%A0%84-%EC%A0%95%EB%B3%B5</link>
      <description>&lt;div class=&quot;hb-post&quot;&gt;
&lt;style&gt;
.hb-post{max-width:780px;margin:0 auto;line-height:1.86;font-size:17px;color:#222;word-break:keep-all;}
.hb-post *{box-sizing:border-box;}
.hb-post h2{margin:2.4em 0 .75em;font-size:1.36em;line-height:1.4;font-weight:800;padding-bottom:.36em;border-bottom:2px solid #edf0f4;color:#111;}
.hb-post h3{margin:1.8em 0 .55em;font-size:1.1em;font-weight:800;color:#182033;}
.hb-post p{margin:0 0 1.12em;}
.hb-post strong{font-weight:800;}
.hb-post a{color:#235ad1;text-decoration:none;border-bottom:1px solid rgba(35,90,200,.3);}
.hb-post code{background:#eef1f6;border-radius:4px;padding:.06em .35em;font-size:.92em;color:#b1004e;font-family:Consolas,monospace;}
.hb-post .hb-lead{font-size:1.08em;color:#343a46;}
.hb-post .hb-hero{margin:0 0 1.6em;padding:1.35em 1.4em;border:1px solid #e1e6ef;border-radius:8px;background:#f8fbff;}
.hb-post .hb-note{background:#f7f9fc;border:1px solid #e3e9f2;border-left:4px solid #3f75ff;border-radius:8px;padding:1.05em 1.2em;margin:1.5em 0;}
.hb-post .hb-warn{background:#fff8f4;border-color:#f1d8cc;border-left-color:#e76f51;}
.hb-post .hb-green{background:#f4fbf8;border-color:#d7eee3;border-left-color:#2a9d8f;}
.hb-post blockquote.hb-pull{margin:1.5em 0;padding:.7em 1.15em;background:#fff9e8;border-left:4px solid #f2b705;border-radius:8px;font-weight:800;color:#584500;}
.hb-post ul,.hb-post ol{margin:0 0 1.18em;padding-left:1.4em;}
.hb-post li{margin:.42em 0;}
.hb-post .hb-tw{overflow-x:auto;margin:1.4em 0;}
.hb-post table{border-collapse:collapse;width:100%;font-size:.93em;}
.hb-post th,.hb-post td{border:1px solid #e3e8ef;padding:.55em .7em;text-align:left;}
.hb-post th{background:#f3f6fb;font-weight:800;}
.hb-post pre.hb-code{background:#0f1729;color:#e6edf3;border-radius:8px;padding:1em 1.15em;margin:1.1em 0;overflow-x:auto;font-size:.9em;line-height:1.7;font-family:Consolas,monospace;white-space:pre;}
.hb-post .hb-toc{background:#f7f9fc;border:1px solid #e6ebf3;border-radius:8px;padding:1em 1.25em;margin:1.5em 0;font-size:.97em;}
&lt;/style&gt;

&lt;div class=&quot;hb-toc&quot;&gt;
&lt;strong&gt;  파이썬 완전 정복 시리즈&lt;/strong&gt; — 입문부터 실전까지, 매일 한 편씩 쌓아 올리는 파이썬 강의입니다. 이 글은 &lt;strong&gt;5편&lt;/strong&gt;이에요. 리스트 자체가 처음이라면 &lt;a href=&quot;https://onethingflow.tistory.com/category/AI/Coding&quot;&gt;4편(리스트 기초)&lt;/a&gt;를 먼저 읽고 오시는 걸 권합니다.
&lt;/div&gt;

&lt;p class=&quot;hb-lead&quot;&gt;리스트에 데이터를 담는 법은 4편에서 끝냈습니다. 그런데 담아만 놓으면 뭐 하나요. 판매량 순으로 줄을 세우고, 가격이 싼 것부터 보여주고, 같은 반 안에서는 키 순서로 다시 줄을 세워야 비로소 &quot;데이터&quot;가 &quot;정보&quot;가 됩니다. 실무 코드에서 정렬이 안 들어가는 프로그램을 거의 본 적이 없어요. 쇼핑몰의 &quot;낮은 가격순&quot;, 게임의 랭킹 보드, 메일함의 최신순 정렬까지 전부 오늘 배울 두 개의 도구, &lt;code&gt;sort()&lt;/code&gt;와 &lt;code&gt;sorted()&lt;/code&gt;로 만들어집니다.&lt;/p&gt;

&lt;div class=&quot;hb-hero&quot;&gt;
&lt;strong&gt;  이번 편에서 가져갈 것&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sort()&lt;/code&gt;와 &lt;code&gt;sorted()&lt;/code&gt;의 차이 — 그리고 초보자의 80%가 한 번은 밟는 &lt;code&gt;None&lt;/code&gt; 함정&lt;/li&gt;
&lt;li&gt;&lt;code&gt;key&lt;/code&gt; 매개변수 하나로 글자 수 순, 가격순, 성적순 등 어떤 기준으로든 정렬하기&lt;/li&gt;
&lt;li&gt;람다(lambda)와 다중 기준 정렬 — &quot;반 오름차순, 같은 반이면 키 내림차순&quot; 같은 요구사항 처리&lt;/li&gt;
&lt;li&gt;파이썬 정렬이 보장하는 &lt;strong&gt;안정 정렬&lt;/strong&gt;이 실무에서 왜 고마운 기능인지&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;h2&gt;1. sort()와 sorted() — 이름은 비슷한데 성격이 다르다&lt;/h2&gt;
&lt;p&gt;편의점 야간 알바를 한다고 상상해 봅시다. 손님 대기 시간을 분 단위로 기록해 둔 리스트가 있어요. 짧은 순서로 줄을 세우고 싶다면 리스트의 &lt;code&gt;sort()&lt;/code&gt; 메서드를 부르면 됩니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code&quot;&gt;wait_times = [12, 3, 27, 8, 15]
wait_times.sort()
print(wait_times)   # [3, 8, 12, 15, 27]&lt;/pre&gt;
&lt;p&gt;간단하죠. 그런데 여기에 파이썬 입문자라면 반드시 한 번은 밟고 지나가는 지뢰가 하나 묻혀 있습니다. &lt;code&gt;sort()&lt;/code&gt;는 &lt;strong&gt;원본 리스트를 직접 바꾸고, 아무것도 돌려주지 않습니다.&lt;/strong&gt; 정확히는 &lt;code&gt;None&lt;/code&gt;을 돌려줘요.&lt;/p&gt;
&lt;pre class=&quot;hb-code&quot;&gt;menu = [&quot;라떼&quot;, &quot;아메리카노&quot;, &quot;콜드브루&quot;]
result = menu.sort()
print(result)   # None  ← !!!
print(menu)     # ['라떼', '아메리카노', '콜드브루']&lt;/pre&gt;
&lt;p&gt;나는 처음 파이썬을 배울 때 이것 때문에 30분을 날렸습니다. &lt;code&gt;result&lt;/code&gt;에 정렬된 리스트가 들어 있을 거라 굳게 믿고 다음 줄에서 &lt;code&gt;result[0]&lt;/code&gt;을 꺼내려다 &lt;code&gt;TypeError&lt;/code&gt; 폭탄을 맞았죠. 파이썬이 일부러 이렇게 설계한 겁니다. &quot;원본을 바꾸는 메서드는 값을 돌려주지 않는다&quot;는 일관된 철학이에요. 원본은 그대로 두고 &lt;strong&gt;정렬된 새 리스트&lt;/strong&gt;를 받고 싶다면 내장 함수 &lt;code&gt;sorted()&lt;/code&gt;를 씁니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code&quot;&gt;orders = [4500, 6000, 3000, 5500]
cheap_first = sorted(orders)
print(cheap_first)   # [3000, 4500, 5500, 6000]
print(orders)        # [4500, 6000, 3000, 5500]  ← 원본은 무사&lt;/pre&gt;
&lt;div class=&quot;hb-tw&quot;&gt;
&lt;table&gt;
&lt;tr&gt;&lt;th&gt;구분&lt;/th&gt;&lt;th&gt;list.sort()&lt;/th&gt;&lt;th&gt;sorted()&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;원본&lt;/td&gt;&lt;td&gt;직접 바꿈 (제자리 정렬)&lt;/td&gt;&lt;td&gt;건드리지 않음&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;반환값&lt;/td&gt;&lt;td&gt;None&lt;/td&gt;&lt;td&gt;정렬된 새 리스트&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;쓸 수 있는 대상&lt;/td&gt;&lt;td&gt;리스트 전용&lt;/td&gt;&lt;td&gt;튜플, 문자열, 딕셔너리 등 반복 가능한 모든 것&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;메모리&lt;/td&gt;&lt;td&gt;절약 (복사본 없음)&lt;/td&gt;&lt;td&gt;새 리스트만큼 추가 사용&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;뭘 써야 할지 고민된다면 기준은 하나입니다. &lt;strong&gt;원본이 다시 필요한가?&lt;/strong&gt; 필요하면 &lt;code&gt;sorted()&lt;/code&gt;, 필요 없으면 &lt;code&gt;sort()&lt;/code&gt;. 실무에서는 원본을 보존하는 습관이 버그를 줄여 주기 때문에 저는 애매하면 &lt;code&gt;sorted()&lt;/code&gt; 쪽을 택합니다.&lt;/p&gt;

&lt;div class=&quot;hb-note hb-warn&quot;&gt;
&lt;strong&gt;⚠️ 흔한 실수 1 — &lt;code&gt;lst = lst.sort()&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
이 한 줄이면 멀쩡한 리스트가 &lt;code&gt;None&lt;/code&gt;으로 증발합니다. &lt;code&gt;sort()&lt;/code&gt;는 반환값이 &lt;code&gt;None&lt;/code&gt;이니까요. 이후 &lt;code&gt;lst[0]&lt;/code&gt;을 시도하는 순간 &lt;code&gt;TypeError: 'NoneType' object is not subscriptable&lt;/code&gt;가 터집니다. 에러 메시지에 &lt;code&gt;NoneType&lt;/code&gt;이 보이면 &quot;아, 어딘가에서 sort()의 반환값을 받았구나&quot;부터 의심하세요.
&lt;/div&gt;

&lt;h2&gt;2. 내림차순 — reverse=True 한 마디면 끝&lt;/h2&gt;
&lt;p&gt;시험 점수를 높은 순으로 줄 세우고 싶을 때, 일단 오름차순으로 정렬한 다음 뒤집어야 하나? 그럴 필요 없습니다. 두 함수 모두 &lt;code&gt;reverse=True&lt;/code&gt; 옵션을 받아요.&lt;/p&gt;
&lt;pre class=&quot;hb-code&quot;&gt;scores = [88, 95, 73, 100, 64]
print(sorted(scores, reverse=True))   # [100, 95, 88, 73, 64]&lt;/pre&gt;
&lt;p&gt;헷갈리기 쉬운 게 하나 있는데, 리스트에는 &lt;code&gt;reverse()&lt;/code&gt;라는 &lt;strong&gt;별개의 메서드&lt;/strong&gt;도 있습니다. 이건 정렬이 아니라 단순히 순서만 뒤집는 거예요. &lt;code&gt;[1, 3, 2]&lt;/code&gt;에 &lt;code&gt;reverse()&lt;/code&gt;를 쓰면 &lt;code&gt;[2, 3, 1]&lt;/code&gt;이 됩니다. 정렬 옵션 &lt;code&gt;reverse=True&lt;/code&gt;와는 완전히 다른 물건이니 이름만 보고 혼동하지 마세요.&lt;/p&gt;

&lt;h2&gt;3. key — 정렬 기준을 통째로 갈아끼우는 매개변수&lt;/h2&gt;
&lt;p&gt;여기서부터가 오늘의 본론입니다. 솔직히 &lt;code&gt;sort()&lt;/code&gt;까지는 누구나 합니다. 실력 차이는 &lt;code&gt;key&lt;/code&gt;에서 갈려요.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;key&lt;/code&gt;에는 &lt;strong&gt;함수&lt;/strong&gt;를 넘깁니다. 파이썬은 정렬 직전에 각 요소를 그 함수에 한 번씩 통과시키고, &lt;strong&gt;함수가 돌려준 값&lt;/strong&gt;을 기준으로 줄을 세웁니다. 예를 들어 채팅방 닉네임을 글자 수 순으로 정렬하고 싶다면, 글자 수를 재는 함수 &lt;code&gt;len&lt;/code&gt;을 그대로 넘기면 됩니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code&quot;&gt;nicknames = [&quot;밤톨이&quot;, &quot;달려라하니&quot;, &quot;곰&quot;, &quot;치즈냥이&quot;]
print(sorted(nicknames, key=len))
# ['곰', '밤톨이', '치즈냥이', '달려라하니']&lt;/pre&gt;
&lt;p&gt;주의할 점: &lt;code&gt;key=len()&lt;/code&gt;이 아니라 &lt;code&gt;key=len&lt;/code&gt;입니다. 괄호를 붙이면 &quot;len을 지금 실행한 결과&quot;가 되어 버려요. 우리는 함수 자체를 건네주고, 실행은 파이썬에게 맡기는 겁니다. 함수를 값처럼 주고받는 이 개념은 6부(함수 편)에서 제대로 다룹니다.&lt;/p&gt;
&lt;p&gt;영어 단어 정렬에서도 &lt;code&gt;key&lt;/code&gt;가 활약합니다. 파이썬 기본 정렬은 대문자를 소문자보다 앞에 둡니다(내부적으로 문자 코드 값을 비교하기 때문). 그래서 사전 순서를 기대하면 결과가 어긋나요.&lt;/p&gt;
&lt;pre class=&quot;hb-code&quot;&gt;words = [&quot;banana&quot;, &quot;Cherry&quot;, &quot;apple&quot;]
print(sorted(words))                  # ['Cherry', 'apple', 'banana']
print(sorted(words, key=str.lower))   # ['apple', 'banana', 'Cherry']&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;key=str.lower&lt;/code&gt;는 &quot;비교할 때만 전부 소문자로 바꿔서 비교해 달라&quot;는 뜻입니다. 원본 데이터는 바뀌지 않는다는 점이 포인트예요. key 함수는 어디까지나 &lt;strong&gt;줄 세우기용 기준값&lt;/strong&gt;만 만들 뿐입니다.&lt;/p&gt;

&lt;h2&gt;4. 람다와 함께 — 진짜 데이터를 정렬해 보자&lt;/h2&gt;
&lt;p&gt;실무 데이터는 숫자 하나짜리 리스트가 아닙니다. 동네 빵집의 오늘 판매 기록이 (빵 이름, 판매 개수) 튜플로 쌓여 있다고 합시다. 많이 팔린 순서로 보고 싶어요.&lt;/p&gt;
&lt;pre class=&quot;hb-code&quot;&gt;sales = [(&quot;크림빵&quot;, 12), (&quot;소금빵&quot;, 31), (&quot;단팥빵&quot;, 7)]
sales.sort(key=lambda item: item[1], reverse=True)
print(sales)
# [('소금빵', 31), ('크림빵', 12), ('단팥빵', 7)]&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;lambda item: item[1]&lt;/code&gt;은 &quot;각 튜플에서 1번 인덱스(판매 개수)를 꺼내 달라&quot;는 일회용 함수입니다. 람다 문법이 낯설다면 지금은 &lt;code&gt;lambda 입력: 기준값&lt;/code&gt; 패턴 하나만 외워 두세요. 어차피 정렬에서 쓰는 람다의 9할은 이 모양입니다.&lt;/p&gt;
&lt;p&gt;딕셔너리가 담긴 리스트도 똑같습니다. 중고거래 앱에 올라온 판매글을 가격순으로 줄 세워 볼게요.&lt;/p&gt;
&lt;pre class=&quot;hb-code&quot;&gt;used_items = [
    {&quot;name&quot;: &quot;자전거&quot;, &quot;price&quot;: 80000},
    {&quot;name&quot;: &quot;모니터&quot;, &quot;price&quot;: 45000},
    {&quot;name&quot;: &quot;키보드&quot;, &quot;price&quot;: 15000},
]
by_price = sorted(used_items, key=lambda d: d[&quot;price&quot;])
print([d[&quot;name&quot;] for d in by_price])
# ['키보드', '모니터', '자전거']&lt;/pre&gt;

&lt;div class=&quot;hb-note hb-green&quot;&gt;
&lt;strong&gt;  실무 팁 — itemgetter는 람다보다 빠르고 깔끔하다&lt;/strong&gt;&lt;br&gt;
인덱스나 키로 꺼내기만 하는 단순한 경우라면 표준 라이브러리 &lt;code&gt;operator.itemgetter&lt;/code&gt;가 람다보다 살짝 빠르고 의도도 분명합니다. &lt;code&gt;from operator import itemgetter&lt;/code&gt; 후에 &lt;code&gt;sorted(sales, key=itemgetter(1))&lt;/code&gt;처럼 씁니다. 외울 필요까지는 없고, 남의 코드에서 만났을 때 &quot;아 그거&quot;라고 알아보면 충분합니다.
&lt;/div&gt;

&lt;h2&gt;5. 다중 기준 정렬 — &quot;반은 오름차순, 키는 내림차순&quot;&lt;/h2&gt;
&lt;p&gt;체육대회 입장 순서를 짠다고 합시다. 1반부터 입장하되, 같은 반 안에서는 키 큰 학생이 앞에 섭니다. 기준이 두 개죠. 이럴 때 key 함수가 &lt;strong&gt;튜플&lt;/strong&gt;을 돌려주게 하면 됩니다. 파이썬은 튜플을 비교할 때 첫 요소부터 차례로 비교하니까, 첫 기준이 같으면 자동으로 두 번째 기준으로 넘어갑니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code&quot;&gt;# (이름, 반, 키)
students = [(&quot;지우&quot;, 2, 165), (&quot;하준&quot;, 1, 172),
            (&quot;서연&quot;, 1, 158), (&quot;민호&quot;, 2, 180)]

students.sort(key=lambda s: (s[1], -s[2]))   # 반 오름차순, 키 내림차순
print(students)
# [('하준', 1, 172), ('서연', 1, 158), ('민호', 2, 180), ('지우', 2, 165)]&lt;/pre&gt;
&lt;p&gt;키 내림차순을 &lt;code&gt;-s[2]&lt;/code&gt;처럼 부호를 뒤집어 처리한 게 보이시나요? 숫자 기준일 때만 통하는 트릭이지만 정말 자주 씁니다. 문자열처럼 부호를 못 붙이는 기준이 섞이면 정렬을 두 번 나눠서 하는데, 그게 가능한 이유가 바로 다음 절의 안정 정렬입니다.&lt;/p&gt;

&lt;h2&gt;6. 안정 정렬 — 파이썬이 조용히 지켜주는 약속&lt;/h2&gt;
&lt;p&gt;파이썬의 정렬은 &lt;strong&gt;안정 정렬(stable sort)&lt;/strong&gt;입니다. 기준값이 같은 요소끼리는 &lt;strong&gt;원래 순서를 그대로 유지&lt;/strong&gt;한다는 뜻이에요.&lt;/p&gt;
&lt;pre class=&quot;hb-code&quot;&gt;data = [(&quot;귤&quot;, 3000), (&quot;배&quot;, 3000), (&quot;감&quot;, 1000)]
print(sorted(data, key=lambda x: x[1]))
# [('감', 1000), ('귤', 3000), ('배', 3000)]  ← 귤·배 순서 유지&lt;/pre&gt;
&lt;p&gt;귤과 배는 둘 다 3,000원이지만, 정렬 후에도 입력 순서(귤 → 배)가 흔들리지 않았습니다. 별것 아닌 듯하지만 이 보증 덕분에 &quot;이름순으로 먼저 정렬하고, 그다음 가격순으로 다시 정렬&quot;하면 &lt;strong&gt;가격이 같은 상품끼리는 이름순&lt;/strong&gt;이 자동으로 유지됩니다. 정렬을 겹겹이 쌓을 수 있는 거죠. 내부적으로는 Timsort라는 알고리즘이 일하는데, 파이썬 개발자 Tim Peters가 만든 거라 이름이 그렇습니다. 현실 데이터에 흔한 &quot;이미 부분적으로 정렬된 구간&quot;을 영리하게 활용해서, 운이 좋으면 거의 다 정렬된 리스트를 눈 깜짝할 새 처리합니다.&lt;/p&gt;

&lt;blockquote class=&quot;hb-pull&quot;&gt;원본을 지키려면 sorted(), 바꿔도 되면 sort(). 기준을 바꾸고 싶으면 key에 함수를. 기준이 여러 개면 key가 튜플을 돌려주게. 이 네 문장이 오늘의 전부다.&lt;/blockquote&gt;

&lt;h2&gt;7. 정렬에서 자주 터지는 에러와 함정&lt;/h2&gt;
&lt;p&gt;마지막으로, 정렬하다 만나는 대표적인 사고 두 가지를 미리 겪어 봅시다.&lt;/p&gt;
&lt;pre class=&quot;hb-code&quot;&gt;sorted([3, &quot;1&quot;, 2])
# TypeError: '&amp;lt;' not supported between instances of 'str' and 'int'&lt;/pre&gt;
&lt;p&gt;숫자와 문자열은 누가 큰지 비교할 수 없으니 파이썬이 정직하게 거부합니다. 엑셀이나 CSV에서 읽어 온 데이터에 숫자와 문자가 섞여 있을 때 단골로 만나는 에러예요. 그리고 더 교묘한 함정이 하나 있습니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code&quot;&gt;print(sorted([&quot;10&quot;, &quot;9&quot;, &quot;100&quot;, &quot;2&quot;]))
# ['10', '100', '2', '9']  ← 어딘가 이상하다?

print(sorted([&quot;10&quot;, &quot;9&quot;, &quot;100&quot;, &quot;2&quot;], key=int))
# ['2', '9', '10', '100']  ← 이게 원하던 결과&lt;/pre&gt;
&lt;div class=&quot;hb-note hb-warn&quot;&gt;
&lt;strong&gt;⚠️ 흔한 실수 2 — 문자열 숫자는 &quot;사전순&quot;으로 정렬된다&lt;/strong&gt;&lt;br&gt;
&quot;10&quot;이 &quot;9&quot;보다 앞에 오는 이유는 문자열 비교가 첫 글자부터 한 자씩 이뤄지기 때문입니다. '1'이 '9'보다 코드값이 작으니 &quot;100&quot;도 &quot;2&quot;보다 앞이 되죠. 파일에서 읽은 데이터는 전부 문자열이라는 사실을 잊으면 정렬 결과가 통째로 어긋납니다. &lt;code&gt;key=int&lt;/code&gt; 한 마디로 해결됩니다.
&lt;/div&gt;
&lt;p&gt;덤으로 하나 더. &lt;code&gt;min()&lt;/code&gt;과 &lt;code&gt;max()&lt;/code&gt;도 &lt;code&gt;key&lt;/code&gt;를 받습니다. 10km 기록(분)에서 가장 빠른 러너를 찾을 때 정렬까지 할 필요 없이 &lt;code&gt;min(runners, key=lambda r: r[1])&lt;/code&gt; 한 줄이면 끝나요. &quot;1등 하나만 필요한데 전체를 정렬하고 있다면&quot; 신호입니다. min/max로 바꾸세요.&lt;/p&gt;

&lt;h2&gt;8. 연습문제&lt;/h2&gt;
&lt;p&gt;손으로 풀어 보고 정답을 확인하세요. 답을 보기 전에 머리로 결과를 예측하는 게 핵심입니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;카페 주문 금액 &lt;code&gt;[4500, 6000, 3000, 5500]&lt;/code&gt;을 &lt;strong&gt;원본을 유지한 채&lt;/strong&gt; 비싼 순으로 정렬한 새 리스트를 만드세요.&lt;/li&gt;
&lt;li&gt;튜플 리스트 &lt;code&gt;[(&quot;포도&quot;, 7), (&quot;사과&quot;, 7), (&quot;딸기&quot;, 2)]&lt;/code&gt;를 개수 오름차순으로 정렬하면 포도와 사과의 순서는 어떻게 될까요? 이유까지 설명해 보세요.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;names = [&quot;bob&quot;, &quot;Alice&quot;, &quot;carol&quot;]&lt;/code&gt;을 대소문자 구분 없이 사전순으로 정렬하세요.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;정답과 해설&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;hb-code&quot;&gt;# 1번
prices = [4500, 6000, 3000, 5500]
expensive_first = sorted(prices, reverse=True)
# [6000, 5500, 4500, 3000] — sorted()라서 원본 보존

# 2번: [('딸기', 2), ('포도', 7), ('사과', 7)]
# 개수가 같은 포도·사과는 안정 정렬 덕분에 입력 순서 유지

# 3번
names = [&quot;bob&quot;, &quot;Alice&quot;, &quot;carol&quot;]
print(sorted(names, key=str.lower))
# ['Alice', 'bob', 'carol']&lt;/pre&gt;

&lt;h2&gt;더 공부할 거리&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/ko/3/howto/sorting.html&quot; target=&quot;_blank&quot;&gt;파이썬 공식 정렬 HOW TO (한국어)&lt;/a&gt; — key, 안정 정렬, 다중 기준까지 공식 문서가 의외로 친절합니다.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/ko/3/library/functions.html#sorted&quot; target=&quot;_blank&quot;&gt;sorted() 내장 함수 레퍼런스&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wikidocs.net/14&quot; target=&quot;_blank&quot;&gt;점프 투 파이썬 — 리스트 자료형&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/python-sort/&quot; target=&quot;_blank&quot;&gt;Real Python — How to Use sorted() and .sort() (영어)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;다음 편 예고&lt;/h2&gt;
&lt;p&gt;6편에서는 리스트의 사촌, &lt;strong&gt;튜플(tuple)&lt;/strong&gt;을 다룹니다. &quot;바꿀 수 없는 리스트가 왜 필요하지?&quot;라는 당연한 의문부터, 함수가 값을 여러 개 돌려줄 때 일어나는 패킹/언패킹의 비밀까지. 리스트만 쓰던 분들이 튜플을 익히면 코드가 한 단계 단단해집니다. 내일 만나요.&lt;/p&gt;
&lt;/div&gt;</description>
      <category>AI/Coding</category>
      <category>Lambda</category>
      <category>PYTHON</category>
      <category>sorted</category>
      <category>리스트정렬</category>
      <category>코딩입문</category>
      <category>파이썬</category>
      <category>파이썬입문</category>
      <category>파이썬정렬</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/100</guid>
      <comments>https://onethingflow.tistory.com/entry/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%85%EB%AC%B8-5%ED%8E%B8-%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EC%A0%95%EB%A0%AC-%EC%99%84%EC%A0%84-%EC%A0%95%EB%B3%B5#entry100comment</comments>
      <pubDate>Fri, 12 Jun 2026 08:20:08 +0900</pubDate>
    </item>
    <item>
      <title>파이썬 입문 4편 &amp;mdash; 리스트(list) 완전 정복: 추가&amp;middot;삭제&amp;middot;정렬부터 복사 함정까지</title>
      <link>https://onethingflow.tistory.com/entry/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%85%EB%AC%B8-4%ED%8E%B8-%E2%80%94-%EB%A6%AC%EC%8A%A4%ED%8A%B8list-%EC%99%84%EC%A0%84-%EC%A0%95%EB%B3%B5-%EC%B6%94%EA%B0%80%C2%B7%EC%82%AD%EC%A0%9C%C2%B7%EC%A0%95%EB%A0%AC%EB%B6%80%ED%84%B0-%EB%B3%B5%EC%82%AC-%ED%95%A8%EC%A0%95%EA%B9%8C%EC%A7%80</link>
      <description>&lt;div class=&quot;hb-post&quot;&gt;
&lt;style&gt;
.hb-post{max-width:780px;margin:0 auto;line-height:1.86;font-size:17px;color:#222;word-break:keep-all;}
.hb-post *{box-sizing:border-box;}
.hb-post h2{margin:2.4em 0 .75em;font-size:1.36em;line-height:1.4;font-weight:800;padding-bottom:.36em;border-bottom:2px solid #edf0f4;color:#111;}
.hb-post h3{margin:1.8em 0 .55em;font-size:1.1em;font-weight:800;color:#182033;}
.hb-post p{margin:0 0 1.12em;}
.hb-post strong{font-weight:800;}
.hb-post a{color:#235ad1;text-decoration:none;border-bottom:1px solid rgba(35,90,200,.3);}
.hb-post code{background:#eef1f6;border-radius:4px;padding:.06em .35em;font-size:.92em;color:#b1004e;font-family:Consolas,monospace;}
.hb-post .hb-lead{font-size:1.08em;color:#343a46;}
.hb-post .hb-hero{margin:0 0 1.6em;padding:1.35em 1.4em;border:1px solid #e1e6ef;border-radius:8px;background:#f8fbff;}
.hb-post .hb-note{background:#f7f9fc;border:1px solid #e3e9f2;border-left:4px solid #3f75ff;border-radius:8px;padding:1.05em 1.2em;margin:1.5em 0;}
.hb-post .hb-warn{background:#fff8f4;border-color:#f1d8cc;border-left-color:#e76f51;}
.hb-post .hb-green{background:#f4fbf8;border-color:#d7eee3;border-left-color:#2a9d8f;}
.hb-post blockquote.hb-pull{margin:1.5em 0;padding:.7em 1.15em;background:#fff9e8;border-left:4px solid #f2b705;border-radius:8px;font-weight:800;color:#584500;}
.hb-post ul,.hb-post ol{margin:0 0 1.18em;padding-left:1.4em;}
.hb-post li{margin:.42em 0;}
.hb-post .hb-tw{overflow-x:auto;margin:1.4em 0;}
.hb-post table{border-collapse:collapse;width:100%;font-size:.93em;}
.hb-post th,.hb-post td{border:1px solid #e3e8ef;padding:.55em .7em;text-align:left;}
.hb-post th{background:#f3f6fb;font-weight:800;}
.hb-post pre.hb-code{background:#0f1729;color:#e6edf3;border-radius:8px;padding:1em 1.15em;margin:1.1em 0;overflow-x:auto;font-size:.9em;line-height:1.7;font-family:Consolas,monospace;white-space:pre;}
.hb-post .hb-toc{background:#f7f9fc;border:1px solid #e6ebf3;border-radius:8px;padding:1em 1.25em;margin:1.5em 0;font-size:.97em;}
&lt;/style&gt;
&lt;div class=&quot;hb-hero&quot;&gt;
&lt;p style=&quot;margin: 0 0 .5em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  「파이썬 완전 정복」 시리즈 4편&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;3편까지 우리는 숫자와 문자열, 그러니까 &quot;값 하나&quot;를 다루는 법을 익혔습니다. 그런데 실제 프로그램은 값 하나로 굴러가지 않죠. 장바구니에 담긴 물건 열 개, 반 학생 서른 명, 한 달 가계부 내역 수백 줄&amp;hellip; 이번 편의 주인공은 이렇게 &lt;b&gt;여러 값을 한 바구니에 담는 리스트(list)&lt;/b&gt;입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;p class=&quot;hb-lead&quot; data-ke-size=&quot;size16&quot;&gt;솔직히 말하면, 파이썬에서 가장 많이 쓰는 자료형을 딱 하나만 꼽으라면 저는 망설임 없이 리스트를 고릅니다. 그만큼 자주 쓰고, 그만큼 초보자가 자주 헷갈리는 녀석이기도 합니다. 오늘 한 편으로 리스트를 만들고, 넣고, 빼고, 정렬하고, 마지막으로 &lt;b&gt;초보자 열에 아홉이 당하는 &quot;복사 함정&quot;&lt;/b&gt;까지 깔끔하게 끝내 봅시다.&lt;/p&gt;
&lt;div class=&quot;hb-hero&quot;&gt;
&lt;p style=&quot;margin: 0 0 .4em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 편에서 배우는 것&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;① 리스트를 만들고 꺼내 쓰기 &amp;nbsp; ② 값 추가 &amp;mdash; &lt;code&gt;append&lt;/code&gt; &amp;middot; &lt;code&gt;insert&lt;/code&gt; &amp;middot; &lt;code&gt;extend&lt;/code&gt; &amp;nbsp; ③ 값 삭제 &amp;mdash; &lt;code&gt;remove&lt;/code&gt; &amp;middot; &lt;code&gt;pop&lt;/code&gt; &amp;middot; &lt;code&gt;del&lt;/code&gt; &amp;nbsp; ④ 찾기&amp;middot;세기&amp;middot;정렬 &amp;mdash; &lt;code&gt;index&lt;/code&gt; &amp;middot; &lt;code&gt;count&lt;/code&gt; &amp;middot; &lt;code&gt;sort&lt;/code&gt; &amp;middot; &lt;code&gt;sorted&lt;/code&gt; &amp;nbsp; ⑤ 반복문과 리스트 컴프리헨션 &amp;nbsp; ⑥ 가장 많이 당하는 복사&amp;middot;참조 함정&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 변수 서른 개를 만들 건가요?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잠깐 상상해 봅시다. 반 학생 서른 명의 점수를 저장해야 합니다. 변수로 한다면 &lt;code&gt;score1&lt;/code&gt;, &lt;code&gt;score2&lt;/code&gt;, &amp;hellip; &lt;code&gt;score30&lt;/code&gt;? 생각만 해도 아찔합니다. 평균이라도 내려면 서른 개를 일일이 더해야 하고요. 이럴 때 값들을 &lt;b&gt;대괄호 &lt;code&gt;[ ]&lt;/code&gt; 하나에 쉼표로 묶어&lt;/b&gt; 담는 것이 리스트입니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code routeros&quot;&gt;&lt;code&gt;cart = [&quot;우유&quot;, &quot;달걀&quot;, &quot;식빵&quot;]
print(cart)          # ['우유', '달걀', '식빵']
print(len(cart))     # 3  (담긴 항목 개수)
print(cart[0])       # 우유   (0번부터 시작)
print(cart[-1])      # 식빵   (음수는 뒤에서부터)

# 리스트 안에는 자료형을 섞어 담을 수도 있습니다
mixed = [1, &quot;둘&quot;, 3.0, True]
print(mixed)         # [1, '둘', 3.0, True]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인덱싱과 슬라이싱은 3편에서 문자열로 연습한 그 문법 그대로입니다. 문자열이 &quot;글자들의 줄&quot;이었다면, 리스트는 &quot;값들의 줄&quot;일 뿐이에요. 그래서 슬라이싱도 똑같이 통합니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code angelscript&quot;&gt;&lt;code&gt;nums = [10, 20, 30, 40, 50]
print(nums[1:4])   # [20, 30, 40]
print(nums[:3])    # [10, 20, 30]
print(nums[::-1])  # [50, 40, 30, 20, 10]  (뒤집기)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 값 넣기 &amp;mdash; append, insert, extend의 미묘한 차이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리스트에 값을 넣는 방법은 크게 세 가지인데, 이 셋을 헷갈리면 엉뚱한 결과가 나옵니다. 하나씩 봅시다.&lt;/p&gt;
&lt;pre class=&quot;hb-code autoit&quot;&gt;&lt;code&gt;todo = [&quot;청소&quot;]

todo.append(&quot;빨래&quot;)        # 맨 뒤에 하나 추가
print(todo)                # ['청소', '빨래']

todo.insert(0, &quot;설거지&quot;)    # 0번 자리에 끼워 넣기
print(todo)                # ['설거지', '청소', '빨래']

todo.extend([&quot;장보기&quot;, &quot;운동&quot;])  # 다른 리스트를 통째로 이어 붙이기
print(todo)                # ['설거지', '청소', '빨래', '장보기', '운동']&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 초보자가 가장 많이 하는 실수 하나. &lt;code&gt;append&lt;/code&gt;에 리스트를 넣으면 어떻게 될까요? &lt;code&gt;[&quot;장보기&quot;, &quot;운동&quot;]&lt;/code&gt;을 &lt;code&gt;append&lt;/code&gt;하면 리스트 안에 리스트가 통째로 한 칸으로 들어갑니다. &quot;이어 붙이기&quot;를 원했다면 &lt;code&gt;extend&lt;/code&gt;가 정답이에요. 저도 입문 때 이걸로 한참 헤맸습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 값 빼기 &amp;mdash; remove, pop, del&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넣었으면 뺄 줄도 알아야죠. 삭제도 상황에 따라 도구가 다릅니다. &lt;b&gt;값으로 지울지, 위치로 지울지&lt;/b&gt;를 먼저 생각하면 헷갈리지 않습니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code lsl&quot;&gt;&lt;code&gt;nums = [10, 20, 30, 20, 40]

nums.remove(20)    # &quot;값&quot; 20을 지움 (처음 만난 하나만!)
print(nums)        # [10, 30, 20, 40]

last = nums.pop()  # 맨 뒤를 꺼내면서 그 값을 돌려줌
print(last, nums)  # 40 [10, 30, 20]

second = nums.pop(1)  # 1번 위치를 꺼내 돌려줌
print(second, nums)   # 30 [10, 20]

del nums[0]        # 0번 위치를 그냥 삭제
print(nums)        # [20]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 가지 짚고 갈 점. &lt;code&gt;remove&lt;/code&gt;는 중복된 값이 여러 개여도 &lt;b&gt;가장 앞에 있는 것 하나만&lt;/b&gt; 지웁니다. 위 예제에서 20이 두 개였지만 하나만 사라졌죠. 전부 지우고 싶다면 반복문이나 컴프리헨션을 써야 하는데, 그건 잠시 뒤에 나옵니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 찾고, 세고, 정렬하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무에서 리스트를 쓰는 이유의 절반은 &quot;정렬&quot;과 &quot;검색&quot; 때문입니다. 시험 점수를 예로 들어 보죠.&lt;/p&gt;
&lt;pre class=&quot;hb-code angelscript&quot;&gt;&lt;code&gt;scores = [88, 92, 75, 92, 60]

print(scores.index(92))  # 1     (92가 처음 등장하는 위치)
print(scores.count(92))  # 2     (92가 몇 번 나오는지)
print(92 in scores)      # True  (있는지 없는지)
print(max(scores), min(scores), sum(scores))  # 92 60 407

scores.sort()            # 원본을 오름차순으로 정렬
print(scores)            # [60, 75, 88, 92, 92]

scores.sort(reverse=True)  # 내림차순
print(scores)            # [92, 92, 88, 75, 60]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 꼭 구분해야 할 짝이 있습니다. &lt;code&gt;sort()&lt;/code&gt;는 &lt;b&gt;원본 리스트 자체를 바꿔 버리고&lt;/b&gt;, &lt;code&gt;sorted()&lt;/code&gt;는 &lt;b&gt;원본은 그대로 두고 정렬된 새 리스트를 돌려줍니다.&lt;/b&gt; 원본을 지켜야 한다면 후자를 쓰세요.&lt;/p&gt;
&lt;pre class=&quot;hb-code routeros&quot;&gt;&lt;code&gt;words = [&quot;banana&quot;, &quot;apple&quot;, &quot;cherry&quot;]
print(sorted(words))   # ['apple', 'banana', 'cherry']
print(words)           # ['banana', 'apple', 'cherry']  (원본 그대로!)&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;hb-tw&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;하고 싶은 것&lt;/th&gt;
&lt;th&gt;메서드&lt;/th&gt;
&lt;th&gt;원본이 바뀌나?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;맨 뒤에 추가&lt;/td&gt;
&lt;td&gt;&lt;code&gt;append(x)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;예&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;중간에 끼우기&lt;/td&gt;
&lt;td&gt;&lt;code&gt;insert(i, x)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;예&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;값으로 삭제&lt;/td&gt;
&lt;td&gt;&lt;code&gt;remove(x)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;예&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;위치로 꺼내기&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pop(i)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;예 (값 반환)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;원본째 정렬&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sort()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;예&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;새 리스트로 정렬&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sorted(li)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;아니오&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 리스트와 반복문, 그리고 컴프리헨션&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리스트는 &lt;code&gt;for&lt;/code&gt; 반복문과 짝꿍입니다. 항목을 하나씩 꺼내 처리할 때 &lt;code&gt;enumerate&lt;/code&gt;를 곁들이면 번호까지 자동으로 매겨 줍니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code python&quot;&gt;&lt;code&gt;basket = [&quot;사과&quot;, &quot;바나나&quot;, &quot;포도&quot;]
for i, fruit in enumerate(basket, 1):   # 1번부터 번호 매기기
    print(f&quot;{i}번: {fruit}&quot;)
# 1번: 사과
# 2번: 바나나
# 3번: 포도&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 파이썬을 파이썬답게 만드는 문법, &lt;b&gt;리스트 컴프리헨션&lt;/b&gt;이 있습니다. &quot;1부터 5까지 각각 제곱한 리스트를 만들어라&quot; 같은 작업을 한 줄로 끝냅니다. 처음엔 낯설어도 익숙해지면 이만큼 편한 게 없어요.&lt;/p&gt;
&lt;pre class=&quot;hb-code lsl&quot;&gt;&lt;code&gt;squares = [n * n for n in range(1, 6)]
print(squares)   # [1, 4, 9, 16, 25]

# 뒤에 조건을 붙이면 &quot;걸러내기&quot;도 됩니다
evens = [n for n in range(10) if n % 2 == 0]
print(evens)     # [0, 2, 4, 6, 8]&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 가장 많이 당하는 함정 &amp;mdash; 복사와 참조&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자, 오늘의 하이라이트입니다. 이걸 모르면 언젠가 반드시 한 번은 크게 데입니다. 다음 코드의 결과를 예상해 보세요.&lt;/p&gt;
&lt;pre class=&quot;hb-code lsl&quot;&gt;&lt;code&gt;a = [1, 2, 3]
b = a          # &quot;복사&quot;한 것 같지만&amp;hellip;
b.append(4)
print(a)       # [1, 2, 3, 4]  (?!) a까지 바뀌었다&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;hb-note hb-warn&quot;&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;⚠️ 흔한 실수 &amp;mdash; &lt;code&gt;b = a&lt;/code&gt;는 복사가 아닙니다&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;margin: .5em 0 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;b = a&lt;/code&gt;는 같은 리스트에 이름표를 하나 더 붙이는 것뿐입니다. 택배 상자 하나에 운송장만 두 장 붙인 셈이죠. &lt;code&gt;b&lt;/code&gt;를 건드리면 같은 상자인 &lt;code&gt;a&lt;/code&gt;도 당연히 바뀝니다. &lt;b&gt;진짜 복사&lt;/b&gt;가 필요하면 &lt;code&gt;a.copy()&lt;/code&gt; 또는 &lt;code&gt;a[:]&lt;/code&gt;를 쓰세요.&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;hb-code angelscript&quot;&gt;&lt;code&gt;a = [1, 2, 3, 4]
c = a.copy()   # 내용물을 새 상자에 옮겨 담기
c.append(5)
print(a)       # [1, 2, 3, 4]      (영향 없음)
print(c)       # [1, 2, 3, 4, 5]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 함정은 &lt;b&gt;2차원 리스트(리스트의 리스트)&lt;/b&gt;에서 한 번 더 변형되어 나타납니다. 격자판을 곱셈으로 만들려다 모두가 한 번씩 당하는 코드예요.&lt;/p&gt;
&lt;pre class=&quot;hb-code angelscript&quot;&gt;&lt;code&gt;grid = [[0] * 3] * 2   # 0이 셋인 줄을 2개?
grid[0][0] = 9
print(grid)            # [[9, 0, 0], [9, 0, 0]]  (둘 다 바뀐다!)

# 올바른 방법 &amp;mdash; 컴프리헨션으로 매번 새 줄을 만든다
grid2 = [[0] * 3 for _ in range(2)]
grid2[0][0] = 9
print(grid2)           # [[9, 0, 0], [0, 0, 0]]&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;hb-note hb-green&quot;&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  실무 팁&lt;/b&gt; &amp;mdash; 리스트를 보기 좋게 출력할 땐 &lt;code&gt;join&lt;/code&gt;이 최고입니다. &lt;code&gt;print(&quot;, &quot;.join([&quot;사과&quot;,&quot;바나나&quot;,&quot;포도&quot;]))&lt;/code&gt; &amp;rarr; &lt;code&gt;사과, 바나나, 포도&lt;/code&gt;. 단, &lt;code&gt;join&lt;/code&gt;은 문자열 리스트에만 통하니 숫자 리스트는 먼저 문자열로 바꿔야 한다는 점만 기억하세요.&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote class=&quot;hb-pull&quot; data-ke-style=&quot;style1&quot;&gt;리스트의 90%는 이 문장으로 요약됩니다 &amp;mdash; 대괄호로 묶고, append로 넣고, pop으로 빼고, sort로 줄 세우고, for로 훑는다. 그리고 b = a는 복사가 아니다.&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리 &amp;amp; 연습문제 (정답 포함)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;눈으로만 읽으면 다음 날 절반은 날아갑니다. 꼭 직접 쳐 보세요.&lt;/p&gt;
&lt;pre class=&quot;hb-code lsl&quot;&gt;&lt;code&gt;# 문제 1) 점수 리스트에서 최고점과 평균 구하기
scores = [88, 92, 75, 60, 95]
print(max(scores))                    # 95
print(sum(scores) / len(scores))      # 82.0

# 문제 2) 리스트에서 짝수만 골라 새 리스트로
nums = [1, 2, 3, 4, 5, 6]
print([n for n in nums if n % 2 == 0])   # [2, 4, 6]

# 문제 3) 이름 리스트를 가나다순으로 정렬해 한 줄로 출력
names = [&quot;지민&quot;, &quot;가영&quot;, &quot;다은&quot;, &quot;나리&quot;]
names.sort()
print(&quot;, &quot;.join(names))               # 가영, 나리, 다은, 지민&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;더 공부할 거리&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/ko/3/tutorial/datastructures.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;파이썬 공식 튜토리얼 &amp;mdash; 자료 구조(리스트 메서드 전체)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/ko/3/library/stdtypes.html#lists&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;공식 레퍼런스 &amp;mdash; list 타입&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wikidocs.net/14&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;점프 투 파이썬 &amp;mdash; 리스트 자료형&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;hb-hero&quot;&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다음 편 예고 &amp;mdash; 5편 &amp;middot; 리스트 정렬의 모든 것&lt;/b&gt;&lt;br /&gt;이번 편에서 맛만 본 &lt;code&gt;sort&lt;/code&gt;와 &lt;code&gt;sorted&lt;/code&gt;를 제대로 파고듭니다. &lt;code&gt;key&lt;/code&gt; 옵션으로 &quot;길이순&quot;, &quot;두 번째 글자순&quot;, &quot;성적 높은 순&quot; 같은 나만의 정렬 기준을 만드는 법까지 &amp;mdash; 실무에서 진짜 쓰는 정렬 기술을 배웁니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>AI/Coding</category>
      <category>PYTHON</category>
      <category>리스트</category>
      <category>컴프리헨션</category>
      <category>코딩입문</category>
      <category>파이썬</category>
      <category>파이썬리스트</category>
      <category>파이썬입문</category>
      <category>파이썬자료구조</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/99</guid>
      <comments>https://onethingflow.tistory.com/entry/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%85%EB%AC%B8-4%ED%8E%B8-%E2%80%94-%EB%A6%AC%EC%8A%A4%ED%8A%B8list-%EC%99%84%EC%A0%84-%EC%A0%95%EB%B3%B5-%EC%B6%94%EA%B0%80%C2%B7%EC%82%AD%EC%A0%9C%C2%B7%EC%A0%95%EB%A0%AC%EB%B6%80%ED%84%B0-%EB%B3%B5%EC%82%AC-%ED%95%A8%EC%A0%95%EA%B9%8C%EC%A7%80#entry99comment</comments>
      <pubDate>Thu, 11 Jun 2026 14:11:06 +0900</pubDate>
    </item>
    <item>
      <title>파이썬 입문 3편 &amp;mdash; 문자열 완전 정복: 인덱싱&amp;middot;슬라이싱부터 f-string&amp;middot;인코딩까지</title>
      <link>https://onethingflow.tistory.com/entry/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%85%EB%AC%B8-3%ED%8E%B8-%E2%80%94-%EB%AC%B8%EC%9E%90%EC%97%B4-%EC%99%84%EC%A0%84-%EC%A0%95%EB%B3%B5-%EC%9D%B8%EB%8D%B1%EC%8B%B1%C2%B7%EC%8A%AC%EB%9D%BC%EC%9D%B4%EC%8B%B1%EB%B6%80%ED%84%B0-f-string%C2%B7%EC%9D%B8%EC%BD%94%EB%94%A9%EA%B9%8C%EC%A7%80</link>
      <description>&lt;div class=&quot;hb-post&quot;&gt;
&lt;style&gt;
.hb-post{max-width:780px;margin:0 auto;line-height:1.86;font-size:17px;color:#222;word-break:keep-all;}
.hb-post *{box-sizing:border-box;}
.hb-post h2{margin:2.4em 0 .75em;font-size:1.36em;line-height:1.4;font-weight:800;padding-bottom:.36em;border-bottom:2px solid #edf0f4;color:#111;}
.hb-post h3{margin:1.8em 0 .55em;font-size:1.1em;font-weight:800;color:#182033;}
.hb-post p{margin:0 0 1.12em;}
.hb-post strong{font-weight:800;}
.hb-post a{color:#235ad1;text-decoration:none;border-bottom:1px solid rgba(35,90,200,.3);}
.hb-post code{background:#eef1f6;border-radius:4px;padding:.06em .35em;font-size:.92em;color:#b1004e;font-family:Consolas,monospace;}
.hb-post .hb-lead{font-size:1.08em;color:#343a46;}
.hb-post .hb-hero{margin:0 0 1.6em;padding:1.35em 1.4em;border:1px solid #e1e6ef;border-radius:8px;background:#f8fbff;}
.hb-post .hb-note{background:#f7f9fc;border:1px solid #e3e9f2;border-left:4px solid #3f75ff;border-radius:8px;padding:1.05em 1.2em;margin:1.5em 0;}
.hb-post .hb-warn{background:#fff8f4;border-color:#f1d8cc;border-left-color:#e76f51;}
.hb-post .hb-green{background:#f4fbf8;border-color:#d7eee3;border-left-color:#2a9d8f;}
.hb-post blockquote.hb-pull{margin:1.5em 0;padding:.7em 1.15em;background:#fff9e8;border-left:4px solid #f2b705;border-radius:8px;font-weight:800;color:#584500;}
.hb-post ul,.hb-post ol{margin:0 0 1.18em;padding-left:1.4em;}
.hb-post li{margin:.42em 0;}
.hb-post .hb-tw{overflow-x:auto;margin:1.4em 0;}
.hb-post table{border-collapse:collapse;width:100%;font-size:.93em;}
.hb-post th,.hb-post td{border:1px solid #e3e8ef;padding:.55em .7em;text-align:left;}
.hb-post th{background:#f3f6fb;font-weight:800;}
.hb-post pre.hb-code{background:#0f1729;color:#e6edf3;border-radius:8px;padding:1em 1.15em;margin:1.1em 0;overflow-x:auto;font-size:.9em;line-height:1.7;font-family:Consolas,monospace;white-space:pre;}
.hb-post .hb-toc{background:#f7f9fc;border:1px solid #e6ebf3;border-radius:8px;padding:1em 1.25em;margin:1.5em 0;font-size:.97em;}
&lt;/style&gt;
&lt;div class=&quot;hb-hero&quot;&gt;
&lt;p style=&quot;margin: 0 0 .5em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  「파이썬 완전 정복」 시리즈 3편&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;2편에서는 모든 계산의 바탕인 &lt;b&gt;숫자형&lt;/b&gt;을 다뤘습니다. 이번 편의 주인공은 우리가 화면에 띄우고, 입력받고, 저장하는 거의 모든 데이터의 모습인 &lt;b&gt;문자열(string)&lt;/b&gt;입니다. (앞 편을 안 보셨다면 먼저 읽고 오시길 권합니다.)&lt;/p&gt;
&lt;/div&gt;
&lt;p class=&quot;hb-lead&quot; data-ke-size=&quot;size16&quot;&gt;이름, 주소, 메시지, 파일 경로, 웹페이지의 글자 한 줄까지 &amp;mdash; 프로그램이 다루는 데이터의 절반 이상은 문자열입니다. 그래서 문자열을 &lt;b&gt;자유자재로 자르고, 붙이고, 바꾸고, 모양을 다듬는&lt;/b&gt; 능력은 파이썬 실력의 기본기입니다. 이번 편에서 문자열의 거의 모든 것을 한 번에 정리합니다.&lt;/p&gt;
&lt;div class=&quot;hb-hero&quot;&gt;
&lt;p style=&quot;margin: 0 0 .4em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 편에서 배우는 것&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;① 문자열을 만드는 세 가지 따옴표 &amp;nbsp; ② 인덱싱과 슬라이싱으로 잘라 쓰기 &amp;nbsp; ③ 자주 쓰는 메서드 총정리 &amp;nbsp; ④ 포매팅 3종 &amp;mdash; &lt;code&gt;%&lt;/code&gt;, &lt;code&gt;format()&lt;/code&gt;, &lt;code&gt;f-string&lt;/code&gt; &amp;nbsp; ⑤ 이스케이프&amp;middot;원시문자열&amp;middot;멀티라인 &amp;nbsp; ⑥ 유니코드와 인코딩(encode/decode)&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 문자열을 만드는 법 &amp;mdash; 따옴표 세 가지&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬에서 문자열은 &lt;b&gt;작은따옴표(&lt;code&gt;'&lt;/code&gt;)&lt;/b&gt;나 &lt;b&gt;큰따옴표(&lt;code&gt;&quot;&lt;/code&gt;)&lt;/b&gt;로 감싸 만듭니다. 둘은 기능이 같지만, 문장 안에 따옴표가 들어갈 때 서로 번갈아 쓰면 편합니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code python&quot;&gt;&lt;code&gt;print('파이썬은 &quot;재미있다&quot;고 말했다')
print(&quot;그녀의 이름은 O'Brien&quot;)

# 세 따옴표는 여러 줄 문자열에 사용
menu = &quot;&quot;&quot;오늘의 메뉴
- 김밥
- 라면&quot;&quot;&quot;
print(menu)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 인덱싱과 슬라이싱 &amp;mdash; 문자열 잘라 쓰기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자열은 글자들이 순서대로 늘어선 &lt;b&gt;시퀀스&lt;/b&gt;입니다. 그래서 위치 번호(인덱스)로 한 글자를 꺼내거나, 범위를 지정해 여러 글자를 잘라낼 수 있습니다. 인덱스는 &lt;b&gt;0부터&lt;/b&gt; 시작하고, 음수는 뒤에서부터 셉니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code gauss&quot;&gt;&lt;code&gt;s = &quot;Python&quot;
print(s[0], s[5], s[-1])   # P n n

# 슬라이싱: s[시작:끝]  (끝 인덱스는 포함하지 않음)
print(s[0:3])   # Pyt
print(s[3:])    # hon
print(s[:2])    # Py
print(s[::-1])  # nohtyP  (뒤집기)
print(s[::2])   # Pto     (두 칸씩 건너뛰기)&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;hb-tw&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;표현식&lt;/th&gt;
&lt;th&gt;의미&lt;/th&gt;
&lt;th&gt;결과(&quot;Python&quot;)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;s[0]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;첫 글자&lt;/td&gt;
&lt;td&gt;P&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;s[-1]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;마지막 글자&lt;/td&gt;
&lt;td&gt;n&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;s[1:4]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1번부터 3번까지&lt;/td&gt;
&lt;td&gt;yth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;s[::-1]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;전체 뒤집기&lt;/td&gt;
&lt;td&gt;nohtyP&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-note hb-warn&quot;&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;⚠️ 흔한 실수 &amp;mdash; 문자열은 바꿀 수 없습니다(불변/immutable)&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;margin: .5em 0 0;&quot; data-ke-size=&quot;size16&quot;&gt;한 글자만 바꾸려고 &lt;code&gt;s[0] = &quot;J&quot;&lt;/code&gt;처럼 쓰면 &lt;code&gt;TypeError: 'str' object does not support item assignment&lt;/code&gt; 오류가 납니다. 문자열은 한 번 만들면 내용을 고칠 수 없습니다. 대신 &lt;b&gt;새 문자열을 만들어&lt;/b&gt; 대입하세요: &lt;code&gt;s = &quot;J&quot; + s[1:]&lt;/code&gt; &amp;rarr; &lt;code&gt;Jython&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 자주 쓰는 문자열 메서드 총정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메서드는 문자열 뒤에 점을 찍고 호출하는 기능입니다. 가장 자주 쓰는 것만 추려도 실무의 대부분을 처리할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code routeros&quot;&gt;&lt;code&gt;t = &quot;  Hello, World  &quot;
print(t.strip())                    # 'Hello, World' (양쪽 공백 제거)
print(&quot;hello&quot;.upper())              # HELLO
print(&quot;WORLD&quot;.lower())              # world
print(&quot;hello world&quot;.replace(&quot;world&quot;, &quot;python&quot;))  # hello python
print(&quot;a,b,c&quot;.split(&quot;,&quot;))           # ['a', 'b', 'c']
print(&quot;-&quot;.join([&quot;2026&quot;, &quot;06&quot;, &quot;11&quot;]))  # 2026-06-11
print(&quot;python&quot;.startswith(&quot;py&quot;))    # True
print(&quot;data.csv&quot;.endswith(&quot;.csv&quot;))  # True
print(&quot;hello world&quot;.find(&quot;world&quot;))  # 6  (없으면 -1)
print(&quot;Hello&quot;.count(&quot;l&quot;))           # 2&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 문자열 포매팅 &amp;mdash; %, format(), f-string&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수 값을 문자열 안에 끼워 넣는 것을 &lt;b&gt;포매팅&lt;/b&gt;이라고 합니다. 파이썬에는 세 가지 방식이 있는데, 지금 새로 배운다면 &lt;b&gt;f-string&lt;/b&gt;만 익혀도 충분합니다. 가장 짧고 읽기 쉽기 때문입니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code python&quot;&gt;&lt;code&gt;name, age = &quot;지민&quot;, 20

print(&quot;%s님은 %d살&quot; % (name, age))      # 옛날 방식
print(&quot;{}님은 {}살&quot;.format(name, age))   # format() 방식
print(f&quot;{name}님은 {age}살&quot;)             # f-string (추천!)

# f-string은 서식 지정도 강력합니다
print(f&quot;{3.14159:.2f}&quot;)    # 3.14      (소수점 둘째 자리)
print(f&quot;{255:08d}&quot;)        # 00000255  (8칸, 0으로 채움)
print(f&quot;{1000000:,}&quot;)      # 1,000,000 (천 단위 콤마)
print(f&quot;{age=}&quot;)           # age=20    (디버깅에 편리)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 이스케이프 문자와 원시 문자열, 멀티라인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;줄바꿈이나 탭처럼 눈에 보이지 않는 특수 문자는 &lt;b&gt;역슬래시(&lt;code&gt;\&lt;/code&gt;)&lt;/b&gt;로 표현합니다. 이를 이스케이프 문자라고 합니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code python&quot;&gt;&lt;code&gt;print(&quot;줄1\n줄2\t탭&quot;)   # \n 줄바꿈, \t 탭

# 윈도우 경로처럼 역슬래시가 많으면 r&quot;&quot; (원시 문자열)이 편리
print(r&quot;C:\new\test&quot;)   # C:\new\test  (그대로 출력)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자주 쓰는 이스케이프: &lt;code&gt;\n&lt;/code&gt;(줄바꿈), &lt;code&gt;\t&lt;/code&gt;(탭), &lt;code&gt;\\&lt;/code&gt;(역슬래시 자체), &lt;code&gt;\&quot;&lt;/code&gt;(큰따옴표).&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 유니코드와 인코딩 (encode / decode)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬3의 문자열은 모두 &lt;b&gt;유니코드&lt;/b&gt;라서 한글&amp;middot;이모지&amp;middot;외국어를 자연스럽게 다룹니다. 다만 파일에 저장하거나 네트워크로 보낼 때는 &lt;b&gt;바이트(bytes)&lt;/b&gt;로 바꿔야 하는데, 이 변환이 &lt;code&gt;encode()&lt;/code&gt;와 &lt;code&gt;decode()&lt;/code&gt;입니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code routeros&quot;&gt;&lt;code&gt;b = &quot;한글&quot;.encode(&quot;utf-8&quot;)
print(b)                  # b'\xed\x95\x9c\xea\xb8\x80'
print(b.decode(&quot;utf-8&quot;))  # 한글
print(len(&quot;한글&quot;.encode(&quot;utf-8&quot;)))  # 6  (한글 한 글자 = UTF-8에서 3바이트)&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;hb-note hb-green&quot;&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  한 줄 정리&lt;/b&gt; &amp;mdash; 사람이 읽는 글자는 &lt;b&gt;str(유니코드)&lt;/b&gt;, 컴퓨터가 저장&amp;middot;전송하는 형태는 &lt;b&gt;bytes&lt;/b&gt;. 거의 모든 상황에서 인코딩은 &lt;code&gt;utf-8&lt;/code&gt;을 쓰면 됩니다.&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote class=&quot;hb-pull&quot; data-ke-style=&quot;style1&quot;&gt;문자열은 ① 따옴표로 만들고 ② 인덱싱&amp;middot;슬라이싱으로 자르며 ③ 메서드로 다듬고 ④ f-string으로 모양을 잡고 ⑤ encode/decode로 바이트와 오간다 &amp;mdash; 이 다섯 가지가 문자열의 전부입니다.&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리 &amp;amp; 연습문제 (정답 포함)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직접 손으로 쳐 보며 익혀 보세요. 머리로 아는 것과 손이 아는 것은 다릅니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code makefile&quot;&gt;&lt;code&gt;# 문제 1) 이메일에서 아이디(@ 앞부분)만 뽑아내기
email = &quot;hello@python.org&quot;
print(email.split(&quot;@&quot;)[0])        # hello

# 문제 2) 이름을 입력받아 &quot;OOO님 환영합니다&quot; 출력하기
name = input(&quot;이름: &quot;)
print(f&quot;{name}님 환영합니다&quot;)

# 문제 3) 문장을 거꾸로 뒤집어 출력하기
text = &quot;stressed&quot;
print(text[::-1])                 # desserts&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;더 공부할 거리&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/ko/3/library/stdtypes.html#text-sequence-type-str&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;파이썬 공식 문서 &amp;mdash; 문자열(str) 타입과 전체 메서드 목록&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/ko/3/tutorial/inputoutput.html#fancier-output-formatting&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;공식 튜토리얼 &amp;mdash; f-string과 출력 포매팅&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wikidocs.net/13&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;점프 투 파이썬 &amp;mdash; 문자열 자료형&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;hb-hero&quot;&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다음 편 예고 &amp;mdash; 4편 &amp;middot; 자료구조(리스트)&lt;/b&gt;&lt;br /&gt;여러 개의 값을 한 곳에 담는 &lt;b&gt;리스트(list)&lt;/b&gt;를 배웁니다. 추가&amp;middot;삭제&amp;middot;정렬부터 슬라이싱 응용까지, 파이썬에서 가장 많이 쓰는 자료구조를 정복합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>AI/Coding</category>
      <category>FString</category>
      <category>PYTHON</category>
      <category>문자열</category>
      <category>슬라이싱</category>
      <category>코딩입문</category>
      <category>파이썬</category>
      <category>파이썬문자열</category>
      <category>파이썬입문</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/98</guid>
      <comments>https://onethingflow.tistory.com/entry/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%85%EB%AC%B8-3%ED%8E%B8-%E2%80%94-%EB%AC%B8%EC%9E%90%EC%97%B4-%EC%99%84%EC%A0%84-%EC%A0%95%EB%B3%B5-%EC%9D%B8%EB%8D%B1%EC%8B%B1%C2%B7%EC%8A%AC%EB%9D%BC%EC%9D%B4%EC%8B%B1%EB%B6%80%ED%84%B0-f-string%C2%B7%EC%9D%B8%EC%BD%94%EB%94%A9%EA%B9%8C%EC%A7%80#entry98comment</comments>
      <pubDate>Thu, 11 Jun 2026 09:34:33 +0900</pubDate>
    </item>
    <item>
      <title>파이썬 입문 2편 &amp;mdash; 숫자형 완전 정복: 정수&amp;middot;실수, 두 가지 나눗셈과 부동소수점 오차까지</title>
      <link>https://onethingflow.tistory.com/entry/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%85%EB%AC%B8-2%ED%8E%B8-%E2%80%94-%EC%88%AB%EC%9E%90%ED%98%95-%EC%99%84%EC%A0%84-%EC%A0%95%EB%B3%B5-%EC%A0%95%EC%88%98%C2%B7%EC%8B%A4%EC%88%98-%EB%91%90-%EA%B0%80%EC%A7%80-%EB%82%98%EB%88%97%EC%85%88%EA%B3%BC-%EB%B6%80%EB%8F%99%EC%86%8C%EC%88%98%EC%A0%90-%EC%98%A4%EC%B0%A8%EA%B9%8C%EC%A7%80</link>
      <description>&lt;div class=&quot;hb-post&quot;&gt;
&lt;style&gt;
.hb-post{max-width:780px;margin:0 auto;line-height:1.86;font-size:17px;color:#222;word-break:keep-all;}
.hb-post *{box-sizing:border-box;}
.hb-post h2{margin:2.4em 0 .75em;font-size:1.36em;line-height:1.4;font-weight:800;padding-bottom:.36em;border-bottom:2px solid #edf0f4;color:#111;}
.hb-post h3{margin:1.8em 0 .55em;font-size:1.1em;line-height:1.45;font-weight:800;color:#182033;}
.hb-post p{margin:0 0 1.12em;}
.hb-post strong{font-weight:800;}
.hb-post a{color:#235ad1;text-decoration:none;border-bottom:1px solid rgba(35,90,200,.3);}
.hb-post code{background:#eef1f6;border-radius:4px;padding:.06em .35em;font-size:.92em;color:#b1004e;font-family:Consolas,monospace;}
.hb-post .hb-lead{font-size:1.08em;color:#343a46;}
.hb-post .hb-hero{margin:0 0 1.6em;padding:1.35em 1.4em;border:1px solid #e1e6ef;border-radius:8px;background:#f8fbff;}
.hb-post .hb-hero p:last-child{margin-bottom:0;}
.hb-post .hb-note{background:#f7f9fc;border:1px solid #e3e9f2;border-left:4px solid #3f75ff;border-radius:8px;padding:1.05em 1.2em;margin:1.5em 0;}
.hb-post .hb-note p{margin:0 0 .55em;}
.hb-post .hb-note p:last-child{margin-bottom:0;}
.hb-post .hb-warn{background:#fff8f4;border-color:#f1d8cc;border-left-color:#e76f51;}
.hb-post .hb-green{background:#f4fbf8;border-color:#d7eee3;border-left-color:#2a9d8f;}
.hb-post blockquote.hb-pull{margin:1.5em 0;padding:.7em 1.15em;background:#fff9e8;border-left:4px solid #f2b705;border-radius:8px;font-size:1.05em;font-weight:800;color:#584500;}
.hb-post ul,.hb-post ol{margin:0 0 1.18em;padding-left:1.4em;}
.hb-post li{margin:.42em 0;}
.hb-post .hb-tw{overflow-x:auto;margin:1.4em 0;}
.hb-post table{border-collapse:collapse;width:100%;font-size:.93em;}
.hb-post th,.hb-post td{border:1px solid #e3e8ef;padding:.55em .7em;text-align:left;}
.hb-post th{background:#f3f6fb;font-weight:800;}
.hb-post pre.hb-code{background:#0f1729;color:#e6edf3;border-radius:8px;padding:1em 1.15em;margin:1.1em 0;overflow-x:auto;font-size:.9em;line-height:1.7;font-family:Consolas,monospace;white-space:pre;}
.hb-post .hb-toc{background:#f7f9fc;border:1px solid #e6ebf3;border-radius:8px;padding:1em 1.25em;margin:1.5em 0;font-size:.97em;}
.hb-post .hb-toc b{display:block;margin-bottom:.4em;}
&lt;/style&gt;
&lt;div class=&quot;hb-toc&quot;&gt;&lt;b&gt;  「파이썬 완전 정복」 시리즈 2편&lt;/b&gt;1편에서 우리는 변수와 자료형의 큰 그림을 봤습니다. 이번 편부터는 자료형을 하나씩 깊이 팝니다. 첫 주인공은 모든 계산의 바탕인 &lt;b&gt;숫자형&lt;/b&gt;입니다. (1편을 안 보셨다면 먼저 읽고 오시길 권합니다.)&lt;/div&gt;
&lt;p class=&quot;hb-lead&quot; data-ke-size=&quot;size16&quot;&gt;&quot;파이썬으로 계산쯤이야 쉽지&quot; 싶지만, 막상 해보면 &lt;code&gt;10 / 3&lt;/code&gt;은 왜 &lt;code&gt;3.3333&amp;hellip;&lt;/code&gt;이 되고 &lt;code&gt;10 // 3&lt;/code&gt;은 왜 &lt;code&gt;3&lt;/code&gt;인지, &lt;code&gt;0.1 + 0.2&lt;/code&gt;가 왜 정확히 &lt;code&gt;0.3&lt;/code&gt;이 아닌지에서 다들 한 번씩 멈칫합니다. 이번 편에서 숫자형의 모든 것 &amp;mdash; 정수와 실수, 일곱 가지 연산자, 두 종류의 나눗셈, 그리고 그 악명 높은 부동소수점 오차까지 &amp;mdash; 확실히 정리합니다.&lt;/p&gt;
&lt;div class=&quot;hb-hero&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 편에서 배우는 것&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;① 정수(int)와 실수(float)의 차이 ② 산술 연산자 7가지와 우선순위 ③ &lt;code&gt;/&lt;/code&gt;&amp;middot;&lt;code&gt;//&lt;/code&gt;&amp;middot;&lt;code&gt;%&lt;/code&gt; 나눗셈 삼총사 ④ 부동소수점 오차의 원인과 해결(round&amp;middot;decimal) ⑤ 숫자 관련 내장 함수와 math 모듈 맛보기&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 정수(int) &amp;mdash; 끝없이 커지는 수&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소수점이 없는 수가 &lt;b&gt;정수(int)&lt;/b&gt;입니다. 파이썬의 정수는 다른 많은 언어와 달리 &lt;b&gt;자리수 제한이 없습니다.&lt;/b&gt; 메모리가 허락하는 한 얼마든지 큰 수도 정확히 계산합니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code angelscript&quot;&gt;&lt;code&gt;print(2 ** 100)   # 2의 100승도 오차 없이
# 1267650600228229401496703205376

big = 1_000_000   # 밑줄로 자릿수를 구분해 읽기 쉽게 (값은 1000000)
print(big)        # 1000000&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진법도 표현할 수 있습니다. 2진수는 &lt;code&gt;0b&lt;/code&gt;, 8진수는 &lt;code&gt;0o&lt;/code&gt;, 16진수는 &lt;code&gt;0x&lt;/code&gt;를 앞에 붙입니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code maxima&quot;&gt;&lt;code&gt;print(0b1010)   # 10  (2진수)
print(0xff)     # 255 (16진수)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 실수(float) &amp;mdash; 소수점이 있는 수&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소수점이 있으면 &lt;b&gt;실수(float)&lt;/b&gt;입니다. 아주 크거나 작은 수는 지수 표기(&lt;code&gt;e&lt;/code&gt;)로도 씁니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code gauss&quot;&gt;&lt;code&gt;pi = 3.14
print(type(pi))   # &amp;lt;class 'float'&amp;gt;
print(1.5e3)      # 1500.0  (1.5 &amp;times; 10^3)
print(2e-2)       # 0.02&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;hb-note&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  정수와 실수를 함께 연산하면 결과는 &lt;b&gt;실수&lt;/b&gt;가 됩니다. &lt;code&gt;3 + 0.0&lt;/code&gt;의 결과는 &lt;code&gt;3.0&lt;/code&gt;입니다. 더 넓은 쪽(실수)으로 자동으로 맞춰지기 때문입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 산술 연산자 7가지&lt;/h2&gt;
&lt;div class=&quot;hb-tw&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;연산자&lt;/th&gt;
&lt;th&gt;의미&lt;/th&gt;
&lt;th&gt;예시&lt;/th&gt;
&lt;th&gt;결과&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;+&lt;/td&gt;
&lt;td&gt;덧셈&lt;/td&gt;
&lt;td&gt;7 + 3&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;뺄셈&lt;/td&gt;
&lt;td&gt;7 - 3&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;곱셈&lt;/td&gt;
&lt;td&gt;7 * 3&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/&lt;/td&gt;
&lt;td&gt;나눗셈(실수)&lt;/td&gt;
&lt;td&gt;7 / 3&lt;/td&gt;
&lt;td&gt;2.333&amp;hellip;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//&lt;/td&gt;
&lt;td&gt;몫(버림)&lt;/td&gt;
&lt;td&gt;7 // 3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;%&lt;/td&gt;
&lt;td&gt;나머지&lt;/td&gt;
&lt;td&gt;7 % 3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;**&lt;/td&gt;
&lt;td&gt;거듭제곱&lt;/td&gt;
&lt;td&gt;7 ** 2&lt;/td&gt;
&lt;td&gt;49&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;가장 헷갈리는 나눗셈 삼총사 &amp;mdash; /, //, %&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬에는 나눗셈이 사실상 세 종류입니다. 이 셋의 구분이 입문의 단골 함정입니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code gauss&quot;&gt;&lt;code&gt;print(10 / 3)    # 3.3333333333333335  (/는 항상 실수)
print(10 // 3)   # 3    (//는 몫만, 소수점 버림)
print(10 % 3)    # 1    (%는 나머지)

# 활용: 초를 분과 초로 나누기
total = 137
print(total // 60, &quot;분&quot;, total % 60, &quot;초&quot;)   # 2 분 17 초&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote class=&quot;hb-pull&quot; data-ke-style=&quot;style1&quot;&gt;/ 는 나눈 값(실수), // 는 정수 몫, % 는 나머지. &quot;짝수 판별(n % 2 == 0)&quot;과 &quot;자릿수 분리&quot;에 // 와 % 가 단골로 등장합니다.&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 연산자 우선순위와 복합 할당&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수학처럼 &lt;code&gt;**&lt;/code&gt; &amp;gt; &lt;code&gt;* / // %&lt;/code&gt; &amp;gt; &lt;code&gt;+ -&lt;/code&gt; 순으로 먼저 계산됩니다. 헷갈리면 &lt;b&gt;괄호로 묶는 것이 정답&lt;/b&gt;입니다. 가독성도 좋아집니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code angelscript&quot;&gt;&lt;code&gt;print(2 + 3 * 4)     # 14  (곱셈 먼저)
print((2 + 3) * 4)   # 20  (괄호 먼저)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수 자신을 갱신할 때는 &lt;code&gt;+=&lt;/code&gt;, &lt;code&gt;-=&lt;/code&gt;, &lt;code&gt;*=&lt;/code&gt;, &lt;code&gt;//=&lt;/code&gt; 같은 &lt;b&gt;복합 할당 연산자&lt;/b&gt;가 편리합니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code fortran&quot;&gt;&lt;code&gt;count = 10
count += 5    # count = count + 5 와 같음
print(count)  # 15&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 악명 높은 부동소수점 오차&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 결과를 보면 처음엔 누구나 당황합니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code angelscript&quot;&gt;&lt;code&gt;print(0.1 + 0.2)          # 0.30000000000000004 (?!)
print(0.1 + 0.2 == 0.3)   # False&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버그가 아닙니다. 컴퓨터는 모든 수를 2진수로 저장하는데, &lt;code&gt;0.1&lt;/code&gt; 같은 십진 소수는 2진수로 &lt;b&gt;정확히 표현되지 않아&lt;/b&gt; 아주 미세한 오차가 생깁니다. 이는 파이썬만의 문제가 아니라 거의 모든 언어가 공유하는 &lt;a href=&quot;https://docs.python.org/ko/3/tutorial/floatingpoint.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;부동소수점의 본질적 한계&lt;/a&gt;입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;① 비교는 반올림하거나 오차 범위로:&lt;/b&gt; 화면 표시는 &lt;code&gt;round()&lt;/code&gt;로 충분합니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code gauss&quot;&gt;&lt;code&gt;print(round(0.1 + 0.2, 2))   # 0.3
print(round(3.14159, 2))     # 3.14&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;② 돈 계산처럼 정확도가 중요하면 &lt;code&gt;decimal&lt;/code&gt; 모듈을 씁니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;hb-code pgsql&quot;&gt;&lt;code&gt;from decimal import Decimal
print(Decimal(&quot;0.1&quot;) + Decimal(&quot;0.2&quot;))   # 0.3  (정확!)&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;hb-note hb-warn&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;⚠️ 흔한 실수&lt;/b&gt; &amp;mdash; 두 실수가 같은지 &lt;code&gt;==&lt;/code&gt;로 직접 비교하지 마세요. &lt;code&gt;round()&lt;/code&gt;로 자리수를 맞추거나, &lt;code&gt;abs(a - b) &amp;lt; 1e-9&lt;/code&gt;처럼 &quot;충분히 가까운가&quot;로 판단하는 것이 안전합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 숫자 관련 내장 함수 &amp;amp; math 모듈&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자주 쓰는 숫자 함수는 설치 없이 바로 쓸 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code angelscript&quot;&gt;&lt;code&gt;print(abs(-7))        # 7    (절댓값)
print(round(3.567, 1))# 3.6  (반올림)
print(pow(2, 10))     # 1024 (거듭제곱, 2**10과 동일)
print(divmod(17, 5))  # (3, 2)  (몫과 나머지를 한 번에)
print(max(3, 9, 1), min(3, 9, 1))  # 9 1
print(sum([1, 2, 3, 4]))           # 10&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 깊은 수학 함수는 &lt;code&gt;math&lt;/code&gt; 모듈에 있습니다. (모듈은 9부에서 자세히 다룹니다.)&lt;/p&gt;
&lt;pre class=&quot;hb-code gauss&quot;&gt;&lt;code&gt;import math
print(math.sqrt(16))   # 4.0   (제곱근)
print(math.pi)         # 3.141592653589793
print(math.ceil(3.1))  # 4     (올림)
print(math.floor(3.9)) # 3     (내림)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리 &amp;amp; 연습문제 (정답 포함)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 편에서는 정수와 실수, 7가지 산술 연산자, 나눗셈 삼총사(&lt;code&gt;/ // %&lt;/code&gt;), 우선순위와 복합 할당, 부동소수점 오차와 해결법, 그리고 숫자 내장 함수까지 다뤘습니다. 아래 문제로 손에 익혀 보세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제 1.&lt;/b&gt; 초 단위 정수를 입력받아 &quot;○분 ○초&quot;로 출력하기.&lt;br /&gt;&lt;b&gt;문제 2.&lt;/b&gt; 어떤 수가 짝수인지 홀수인지 출력하기.&lt;br /&gt;&lt;b&gt;문제 3.&lt;/b&gt; 원화 금액을 입력받아 부가세(10%)를 더한 최종 금액을 원 단위로 반올림해 출력하기.&lt;/p&gt;
&lt;div class=&quot;hb-note hb-green&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅ 정답 예시&lt;/b&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;hb-code hsp&quot;&gt;&lt;code&gt;# 문제 1
sec = int(input(&quot;초: &quot;))
print(sec // 60, &quot;분&quot;, sec % 60, &quot;초&quot;)

# 문제 2
n = int(input(&quot;숫자: &quot;))
print(&quot;짝수&quot; if n % 2 == 0 else &quot;홀수&quot;)

# 문제 3
price = int(input(&quot;금액: &quot;))
print(&quot;최종:&quot;, round(price * 1.1))&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;더 공부할 거리&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;  &lt;a href=&quot;https://docs.python.org/ko/3/library/stdtypes.html#numeric-types-int-float-complex&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;공식 문서 &amp;mdash; 숫자형(int&amp;middot;float&amp;middot;complex)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;  &lt;a href=&quot;https://docs.python.org/ko/3/tutorial/floatingpoint.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;공식 문서 &amp;mdash; 부동소수점 산술의 함정&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;  &lt;a href=&quot;https://wikidocs.net/12&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;점프 투 파이썬 &amp;mdash; 숫자형&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 &lt;b&gt;3편&lt;/b&gt;에서는 또 하나의 핵심 자료형 &lt;b&gt;문자열(str)&lt;/b&gt;을 정복합니다. 글자를 자르는 슬라이싱, 수십 가지 문자열 메서드, 그리고 실무에서 매일 쓰는 &lt;code&gt;f-string&lt;/code&gt; 포매팅까지 &amp;mdash; 텍스트를 자유자재로 다루는 기술을 익힙니다.  &lt;/p&gt;
&lt;/div&gt;</description>
      <category>AI/Coding</category>
      <category>PYTHON</category>
      <category>부동소수점</category>
      <category>코딩입문</category>
      <category>파이썬</category>
      <category>파이썬독학</category>
      <category>파이썬숫자형</category>
      <category>파이썬연산자</category>
      <category>파이썬입문</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/97</guid>
      <comments>https://onethingflow.tistory.com/entry/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%85%EB%AC%B8-2%ED%8E%B8-%E2%80%94-%EC%88%AB%EC%9E%90%ED%98%95-%EC%99%84%EC%A0%84-%EC%A0%95%EB%B3%B5-%EC%A0%95%EC%88%98%C2%B7%EC%8B%A4%EC%88%98-%EB%91%90-%EA%B0%80%EC%A7%80-%EB%82%98%EB%88%97%EC%85%88%EA%B3%BC-%EB%B6%80%EB%8F%99%EC%86%8C%EC%88%98%EC%A0%90-%EC%98%A4%EC%B0%A8%EA%B9%8C%EC%A7%80#entry97comment</comments>
      <pubDate>Thu, 11 Jun 2026 08:06:49 +0900</pubDate>
    </item>
    <item>
      <title>파이썬 입문 1편 &amp;mdash; 프로그래밍이 처음이어도 괜찮습니다: 설치부터 첫 코드, 변수&amp;middot;자료형까지</title>
      <link>https://onethingflow.tistory.com/entry/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%85%EB%AC%B8-1%ED%8E%B8-%E2%80%94-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%B4-%EC%B2%98%EC%9D%8C%EC%9D%B4%EC%96%B4%EB%8F%84-%EA%B4%9C%EC%B0%AE%EC%8A%B5%EB%8B%88%EB%8B%A4-%EC%84%A4%EC%B9%98%EB%B6%80%ED%84%B0-%EC%B2%AB-%EC%BD%94%EB%93%9C-%EB%B3%80%EC%88%98%C2%B7%EC%9E%90%EB%A3%8C%ED%98%95%EA%B9%8C%EC%A7%80</link>
      <description>&lt;div class=&quot;hb-post&quot;&gt;
&lt;style&gt;
.hb-post{max-width:780px;margin:0 auto;line-height:1.86;font-size:17px;color:#222;word-break:keep-all;}
.hb-post *{box-sizing:border-box;}
.hb-post h2{margin:2.4em 0 .75em;font-size:1.36em;line-height:1.4;font-weight:800;padding-bottom:.36em;border-bottom:2px solid #edf0f4;color:#111;}
.hb-post h3{margin:1.8em 0 .55em;font-size:1.1em;line-height:1.45;font-weight:800;color:#182033;}
.hb-post p{margin:0 0 1.12em;}
.hb-post strong{font-weight:800;}
.hb-post a{color:#235ad1;text-decoration:none;border-bottom:1px solid rgba(35,90,200,.3);}
.hb-post code{background:#eef1f6;border-radius:4px;padding:.06em .35em;font-size:.92em;color:#b1004e;font-family:Consolas,monospace;}
.hb-post .hb-lead{font-size:1.08em;color:#343a46;}
.hb-post .hb-hero{margin:0 0 1.6em;padding:1.35em 1.4em;border:1px solid #e1e6ef;border-radius:8px;background:#f8fbff;}
.hb-post .hb-hero p:last-child{margin-bottom:0;}
.hb-post .hb-kpi{display:grid;grid-template-columns:repeat(3,1fr);gap:.7em;margin:1.4em 0;}
.hb-post .hb-kpi div{border:1px solid #e5e8ee;border-radius:8px;background:#fbfcfd;padding:.9em;text-align:center;}
.hb-post .hb-kpi span{display:block;font-size:.8em;color:#687182;margin-bottom:.3em;}
.hb-post .hb-kpi b{display:block;font-size:1.04em;color:#10141b;line-height:1.35;font-weight:800;}
.hb-post .hb-note{background:#f7f9fc;border:1px solid #e3e9f2;border-left:4px solid #3f75ff;border-radius:8px;padding:1.05em 1.2em;margin:1.5em 0;}
.hb-post .hb-note p{margin:0 0 .55em;}
.hb-post .hb-note p:last-child{margin-bottom:0;}
.hb-post .hb-warn{background:#fff8f4;border-color:#f1d8cc;border-left-color:#e76f51;}
.hb-post .hb-green{background:#f4fbf8;border-color:#d7eee3;border-left-color:#2a9d8f;}
.hb-post blockquote.hb-pull{margin:1.5em 0;padding:.7em 1.15em;background:#fff9e8;border-left:4px solid #f2b705;border-radius:8px;font-size:1.05em;font-weight:800;color:#584500;}
.hb-post ul,.hb-post ol{margin:0 0 1.18em;padding-left:1.4em;}
.hb-post li{margin:.42em 0;}
.hb-post .hb-tw{overflow-x:auto;margin:1.4em 0;}
.hb-post table{border-collapse:collapse;width:100%;font-size:.93em;}
.hb-post th,.hb-post td{border:1px solid #e3e8ef;padding:.55em .7em;text-align:left;}
.hb-post th{background:#f3f6fb;font-weight:800;}
.hb-post pre.hb-code{background:#0f1729;color:#e6edf3;border-radius:8px;padding:1em 1.15em;margin:1.1em 0;overflow-x:auto;font-size:.9em;line-height:1.7;font-family:Consolas,monospace;white-space:pre;}
.hb-post figure.hb-fig{margin:0 0 1.5em;text-align:center;}
.hb-post figure.hb-fig img{max-width:62%;height:auto;}
.hb-post figure.hb-fig figcaption{font-size:.83em;color:#8a93a3;margin-top:.5em;}
.hb-post .hb-toc{background:#f7f9fc;border:1px solid #e6ebf3;border-radius:8px;padding:1em 1.25em;margin:1.5em 0;font-size:.97em;}
.hb-post .hb-toc b{display:block;margin-bottom:.4em;}
&lt;/style&gt;
&lt;figure class=&quot;hb-fig&quot;&gt;&lt;img src=&quot;https://www.python.org/static/community_logos/python-logo-master-v3-TM.png&quot; alt=&quot;파이썬 공식 로고&quot; /&gt;
&lt;figcaption&gt;이미지 출처: 파이썬 공식 사이트(python.org) 로고&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p class=&quot;hb-lead&quot; data-ke-size=&quot;size16&quot;&gt;&quot;개발자도 아닌데 파이썬을 왜 배워?&quot; 한 번쯤 이런 생각, 해보셨을 겁니다. 그런데 요즘은 사무직, 마케터, 기획자, 회계 담당자, 대학생까지 파이썬을 배웁니다. 이유는 단순합니다. &lt;b&gt;반복되는 일을 컴퓨터에게 대신 시킬 수 있기 때문&lt;/b&gt;입니다. 엑셀 수천 줄을 1초 만에 정리하고, 매일 같은 보고서를 자동으로 만들고, 웹사이트에서 데이터를 긁어옵니다. 이 글은 프로그래밍을 한 번도 안 해본 분을 기준으로, 설치부터 첫 코드 실행, 그리고 입문에서 가장 헷갈리는 변수와 자료형까지 &lt;b&gt;하나도 빠짐없이&lt;/b&gt; 정리합니다. 천천히 따라오시면 됩니다.&lt;/p&gt;
&lt;div class=&quot;hb-toc&quot;&gt;&lt;b&gt;  이 글은 「파이썬 완전 정복」 시리즈 1편입니다&lt;/b&gt;매일 한 편씩, 기초 문법부터 객체지향&amp;middot;표준 라이브러리&amp;middot;실전 프로젝트까지 파이썬의 모든 것을 다룹니다. 이번 편만 끝내도 &quot;내가 코드를 실행했다&quot;는 경험을 갖게 됩니다.&lt;/div&gt;
&lt;div class=&quot;hb-hero&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 글을 끝내면 이런 걸 할 수 있어요&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;① 내 컴퓨터에 파이썬 3.14를 직접 설치하고 ② 첫 프로그램을 실행하고 ③ 변수에 값을 담아 출력하고 ④ &lt;code&gt;&quot;3&quot; + &quot;5&quot;&lt;/code&gt;가 왜 &lt;code&gt;8&lt;/code&gt;이 아니라 &lt;code&gt;35&lt;/code&gt;가 되는지 설명하고 ⑤ 흔한 에러 메시지를 읽고 스스로 고칠 수 있게 됩니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-kpi&quot;&gt;
&lt;div&gt;&lt;span&gt;문법&lt;/span&gt;&lt;b&gt;사람 말과 가깝다&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;활용 범위&lt;/span&gt;&lt;b&gt;분석&amp;middot;AI&amp;middot;자동화&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;사용자 수&lt;/span&gt;&lt;b&gt;전 세계 최상위&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 프로그래밍이 뭐고, 왜 하필 파이썬일까&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그래밍을 어렵게 생각할 필요 없습니다. 한 문장으로 줄이면 &lt;b&gt;&quot;아주 성실하지만 융통성은 전혀 없는 신입에게 일을 시키는 것&quot;&lt;/b&gt;입니다. 컴퓨터는 엄청나게 빠르지만 스스로 판단하지 못합니다. 시킨 일만, 시킨 순서대로, 토씨 하나 안 틀리고 처리합니다. 그래서 우리가 &quot;이걸 이렇게, 그다음 저렇게 하라&quot;고 정확히 적어줘야 하는데, 그 지시서를 &lt;b&gt;코드(code)&lt;/b&gt;라 하고, 코드를 적는 규칙을 &lt;b&gt;프로그래밍 언어&lt;/b&gt;라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세상에는 수백 개의 언어가 있습니다. 같은 &quot;안녕하세요 출력하기&quot;를 비교해 볼까요.&lt;/p&gt;
&lt;pre class=&quot;hb-code routeros&quot;&gt;&lt;code&gt;# 파이썬
print(&quot;안녕하세요&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;hb-code arduino&quot;&gt;&lt;code&gt;// 자바 &amp;mdash; 똑같은 일을 하는 코드
public class Main {
    public static void main(String[] args) {
        System.out.println(&quot;안녕하세요&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과는 똑같습니다. 하지만 파이썬은 단 한 줄이면 끝납니다. 문법이 사람 말에 가깝고 군더더기가 없어서, &quot;어떻게 쓰지?&quot;가 아니라 &quot;&lt;b&gt;무엇을 만들지?&lt;/b&gt;&quot;에 집중할 수 있습니다. 입문자에게 이건 결정적인 장점입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게다가 파이썬은 활용 범위가 압도적으로 넓습니다. 데이터 분석(pandas), 인공지능(PyTorch), 웹 서버(Django&amp;middot;FastAPI), 업무 자동화, 크롤링까지 거의 모든 분야에 잘 만들어진 도구(라이브러리)가 준비돼 있습니다. 또 사용자가 워낙 많아서, 막혔을 때 검색하면 답이 거의 항상 나옵니다. 공식 소개는 &lt;a href=&quot;https://www.python.org/about/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;python.org 소개 페이지&lt;/a&gt;에서 볼 수 있습니다.&lt;/p&gt;
&lt;blockquote class=&quot;hb-pull&quot; data-ke-style=&quot;style1&quot;&gt;프로그래밍 = 컴퓨터에게 정확한 순서로 일을 시키는 것. 파이썬 = 그 지시를 사람 말에 가장 가깝게 적을 수 있는 언어.&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 개발 환경 설치 &amp;mdash; 파이썬 3.14와 VS Code&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요리에 비유하면 &lt;b&gt;파이썬(인터프리터)은 주방&lt;/b&gt;, &lt;b&gt;코드 편집기는 주문서를 쓰는 펜&lt;/b&gt;입니다. 둘 다 준비해야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;① 파이썬 설치하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식 다운로드 페이지 &lt;a href=&quot;https://www.python.org/downloads/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;python.org/downloads&lt;/a&gt;에 접속하면 내 운영체제를 자동으로 인식해 최신 버전 버튼을 보여줍니다. 이 글은 2026년 최신 안정판인 &lt;b&gt;파이썬 3.14&lt;/b&gt;를 기준으로 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;윈도우(Windows)&lt;/b&gt;라면 받은 설치 파일을 실행하고, &lt;b&gt;맥(macOS)&lt;/b&gt;이라면 &lt;code&gt;.pkg&lt;/code&gt; 파일을 더블클릭해 안내대로 진행하면 됩니다.&lt;/p&gt;
&lt;div class=&quot;hb-note hb-warn&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;⚠️ 윈도우 사용자 필독 &amp;mdash; 가장 많이 막히는 1번 지점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 첫 화면 맨 아래의 &lt;b&gt;&quot;Add python.exe to PATH&quot;&lt;/b&gt; 체크박스를 &lt;b&gt;반드시 켜고&lt;/b&gt; 설치하세요. 이걸 놓치면 터미널에서 &lt;code&gt;python&lt;/code&gt; 명령을 입력했을 때 &lt;i&gt;&quot;'python'은(는) 내부 또는 외부 명령... 이 아닙니다&quot;&lt;/i&gt; 오류가 납니다. 이미 체크 없이 설치했다면, 설치 파일을 다시 실행해 &quot;Modify&quot;로 PATH만 추가하면 됩니다.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치가 끝났는지 확인하려면 터미널을 엽니다. &lt;b&gt;윈도우&lt;/b&gt;는 시작 메뉴에서 &quot;PowerShell&quot;, &lt;b&gt;맥&lt;/b&gt;은 Spotlight(⌘+Space)에서 &quot;터미널&quot;을 검색해 실행합니다. 그리고 아래를 입력하세요.&lt;/p&gt;
&lt;pre class=&quot;hb-code vim&quot;&gt;&lt;code&gt;python --version&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Python 3.14.x&lt;/code&gt;처럼 버전이 찍히면 성공입니다. (맥&amp;middot;리눅스에서는 &lt;code&gt;python3 --version&lt;/code&gt;으로 입력해야 할 수 있습니다. 맥은 시스템에 옛 파이썬이 섞여 있을 수 있어 &lt;code&gt;python3&lt;/code&gt; 사용을 권장합니다.)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;② 코드 편집기 &amp;mdash; VS Code 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모장으로도 코드를 쓸 수 있지만, 전문 편집기를 쓰면 오타를 잡아주고 색을 입혀 읽기 쉽게 해줍니다. 무료이면서 가장 널리 쓰이는 &lt;a href=&quot;https://code.visualstudio.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Visual Studio Code(VS Code)&lt;/a&gt;를 추천합니다. 설치한 뒤, 왼쪽 사이드바의 &lt;b&gt;확장(Extensions, 네모 4개 아이콘)&lt;/b&gt; 탭에서 &quot;Python&quot;을 검색해 마이크로소프트 공식 확장을 설치하면 자동완성&amp;middot;실행&amp;middot;디버깅이 모두 켜집니다.&lt;/p&gt;
&lt;div class=&quot;hb-note&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  설치가 번거롭거나 회사 PC라 설치가 막힌다면, 구글 계정만 있으면 되는 &lt;a href=&quot;https://colab.research.google.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Google Colab&lt;/a&gt;에서 브라우저만으로 코드를 실행할 수 있습니다. 다만 이 시리즈는 내 컴퓨터에 직접 환경을 갖추는 방식을 기준으로 설명합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 첫 프로그램과 대화형 셸&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;대화형 셸(REPL) &amp;mdash; 즉시 답이 오는 계산기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터미널에 &lt;code&gt;python&lt;/code&gt;(맥은 &lt;code&gt;python3&lt;/code&gt;)만 입력하고 엔터를 치면 &lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt; 표시가 뜨는 &lt;b&gt;대화형 셸&lt;/b&gt;이 열립니다. 여기서는 한 줄 입력할 때마다 컴퓨터가 즉시 답합니다. 새 문법을 시험할 때 최고입니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code lsl&quot;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; 1 + 1
2
&amp;gt;&amp;gt;&amp;gt; 10 * 3
30
&amp;gt;&amp;gt;&amp;gt; 2 ** 10        # **는 거듭제곱, 2의 10승
1024
&amp;gt;&amp;gt;&amp;gt; print(&quot;Hello, Python!&quot;)
Hello, Python!&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셸을 빠져나오려면 &lt;code&gt;exit()&lt;/code&gt;를 입력하거나 윈도우는 &lt;code&gt;Ctrl+Z&lt;/code&gt;+Enter, 맥은 &lt;code&gt;Ctrl+D&lt;/code&gt;를 누릅니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;파일로 프로그램 만들기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 프로그램은 파일에 저장해 실행합니다. VS Code에서 &lt;code&gt;hello.py&lt;/code&gt; 파일을 만들고 아래를 적어봅시다. (&lt;code&gt;.py&lt;/code&gt;는 파이썬 파일의 확장자입니다.)&lt;/p&gt;
&lt;pre class=&quot;hb-code stylus&quot;&gt;&lt;code&gt;print(&quot;안녕하세요, 파이썬!&quot;)
print(&quot;제 첫 프로그램입니다.&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장한 뒤, 터미널에서 파일이 있는 폴더로 이동해 실행합니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code vim&quot;&gt;&lt;code&gt;python hello.py&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 줄의 인사말이 출력되면, 당신은 방금 첫 프로그램을 만든 겁니다.  &lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;print() 조금 더 알기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;print()&lt;/code&gt;는 괄호 안의 내용을 화면에 출력하는 &lt;b&gt;내장 함수&lt;/b&gt;입니다. 쉼표로 여러 값을 한 번에 출력할 수 있고, 값 사이는 기본적으로 한 칸 띄어집니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code routeros&quot;&gt;&lt;code&gt;print(&quot;나이는&quot;, 20, &quot;살입니다.&quot;)   # 나이는 20 살입니다.
print(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, sep=&quot;-&quot;)     # a-b-c   (sep=구분자)
print(&quot;줄바꿈 없음&quot;, end=&quot; &quot;)       # 끝에 줄바꿈 대신 공백&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 변수 &amp;mdash; 값을 담는 이름표&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램은 값을 저장해 뒀다가 나중에 꺼내 씁니다. 값을 담는 그릇에 이름을 붙인 것이 &lt;b&gt;변수(variable)&lt;/b&gt;입니다. 등호 &lt;code&gt;=&lt;/code&gt;는 수학의 '같다'가 아니라 &lt;b&gt;&quot;오른쪽 값을 왼쪽 이름에 넣어라&quot;&lt;/b&gt;라는 '대입' 기호입니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code makefile&quot;&gt;&lt;code&gt;name = &quot;거대웅&quot;
age = 20
print(name, &quot;님은&quot;, age, &quot;살입니다.&quot;)   # 거대웅 님은 20 살입니다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수의 값은 언제든 바꿀 수 있고, 자기 자신을 이용해 갱신할 수도 있습니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code makefile&quot;&gt;&lt;code&gt;age = 20
age = age + 1     # 기존 20에 1을 더해 다시 age에 넣음
print(age)        # 21&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬은 한 줄에 여러 변수를 동시에 대입하거나, 두 변수의 값을 한 줄로 맞바꿀 수도 있습니다. 다른 언어에서는 번거로운 일이 파이썬에선 직관적입니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code gml&quot;&gt;&lt;code&gt;x, y = 10, 20      # 동시에 대입
x, y = y, x        # 값 맞바꾸기(swap)
print(x, y)        # 20 10&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 자료형 &amp;mdash; 값에도 종류가 있다 (입문의 진짜 고비)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 &quot;3&quot;이라도 숫자 3과 글자 '3'은 컴퓨터에게 전혀 다릅니다. 이렇게 값의 종류를 &lt;b&gt;자료형(data type)&lt;/b&gt;이라고 합니다. 입문 단계에서 꼭 알아야 할 기본 자료형은 넷입니다.&lt;/p&gt;
&lt;div class=&quot;hb-tw&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;자료형&lt;/th&gt;
&lt;th&gt;이름&lt;/th&gt;
&lt;th&gt;예시&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;정수&lt;/td&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;10, -3, 0&lt;/td&gt;
&lt;td&gt;소수점 없는 수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;실수&lt;/td&gt;
&lt;td&gt;float&lt;/td&gt;
&lt;td&gt;3.14, -0.5&lt;/td&gt;
&lt;td&gt;소수점 있는 수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;문자열&lt;/td&gt;
&lt;td&gt;str&lt;/td&gt;
&lt;td&gt;&quot;안녕&quot;, 'a'&lt;/td&gt;
&lt;td&gt;따옴표로 감싼 글자&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;불&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;True, False&lt;/td&gt;
&lt;td&gt;참 / 거짓&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 값의 자료형이 궁금하면 &lt;code&gt;type()&lt;/code&gt;으로 확인합니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code lisp&quot;&gt;&lt;code&gt;print(type(10))        # &amp;lt;class 'int'&amp;gt;
print(type(3.14))      # &amp;lt;class 'float'&amp;gt;
print(type(&quot;hello&quot;))   # &amp;lt;class 'str'&amp;gt;
print(type(True))      # &amp;lt;class 'bool'&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이것만은 꼭 &amp;mdash; &quot;3&quot; + &quot;5&quot;는 8이 아니다&lt;/h3&gt;
&lt;pre class=&quot;hb-code bash&quot;&gt;&lt;code&gt;print(3 + 5)        # 8   (숫자끼리의 덧셈)
print(&quot;3&quot; + &quot;5&quot;)    # 35  (문자열끼리는 이어붙이기!)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;눈에는 똑같은 3과 5지만, 따옴표가 있고 없고에 따라 결과가 완전히 달라집니다. 숫자는 더해지고(&lt;code&gt;+&lt;/code&gt;는 덧셈), 문자열은 이어붙습니다(&lt;code&gt;+&lt;/code&gt;는 연결). 이 차이를 이해하는 것이 입문의 첫 고비이자 핵심입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;형 변환 &amp;mdash; 자료형 바꾸기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요하면 &lt;code&gt;int()&lt;/code&gt;, &lt;code&gt;float()&lt;/code&gt;, &lt;code&gt;str()&lt;/code&gt;로 자료형을 서로 바꿀 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code lsl&quot;&gt;&lt;code&gt;int(&quot;10&quot;) + 5      # 15   (문자열 &quot;10&quot;을 숫자로)
str(2026) + &quot;년&quot;   # '2026년' (숫자를 문자열로)
float(&quot;3.14&quot;)      # 3.14&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;hb-note hb-warn&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;⚠️ 흔한 실수 &amp;mdash; 키보드 입력은 항상 문자열&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키보드로 값을 받는 &lt;code&gt;input()&lt;/code&gt;의 결과는 &lt;b&gt;항상 문자열&lt;/b&gt;입니다. 그래서 입력받은 두 수를 그냥 더하면 이어붙기가 됩니다. 숫자로 계산하려면 &lt;code&gt;int()&lt;/code&gt;로 바꿔야 합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;hb-code hsp&quot;&gt;&lt;code&gt;a = input(&quot;첫 번째 수: &quot;)   # &quot;3&quot;이라고 입력해도 문자열
b = input(&quot;두 번째 수: &quot;)   # &quot;5&quot;
print(a + b)               # 35  (덧셈이 아니라 이어붙이기!)
print(int(a) + int(b))     # 8   (숫자로 바꾼 뒤 더하기)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 변수 이름 짓기 &amp;amp; 주석&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 이름은 코드를 읽기 쉽게 만듭니다. 규칙과 관례는 이렇습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;영문자&amp;middot;숫자&amp;middot;밑줄(_)을 쓸 수 있지만 &lt;b&gt;숫자로 시작할 수 없습니다.&lt;/b&gt; (&lt;code&gt;2name&lt;/code&gt; ✗, &lt;code&gt;name2&lt;/code&gt; ○)&lt;/li&gt;
&lt;li&gt;공백 대신 밑줄로 단어를 잇습니다. 예: &lt;code&gt;user_name&lt;/code&gt; (이를 스네이크 케이스라 합니다)&lt;/li&gt;
&lt;li&gt;대소문자를 구별합니다. &lt;code&gt;age&lt;/code&gt;와 &lt;code&gt;Age&lt;/code&gt;는 다른 변수입니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;print&lt;/code&gt;, &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt; 같은 예약어&amp;middot;내장 함수 이름은 변수로 쓰지 마세요.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;보다 &lt;code&gt;price&lt;/code&gt;, &lt;code&gt;total&lt;/code&gt;처럼 뜻이 드러나는 이름이 훨씬 좋습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 명명 관례는 파이썬 공식 스타일 가이드 &lt;a href=&quot;https://peps.python.org/pep-0008/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PEP 8&lt;/a&gt;에 정리돼 있습니다(13부에서 자세히 다룹니다). 또 &lt;code&gt;#&lt;/code&gt; 뒤의 내용은 &lt;b&gt;주석&lt;/b&gt;으로, 실행되지 않고 사람을 위한 메모입니다.&lt;/p&gt;
&lt;pre class=&quot;hb-code ini&quot;&gt;&lt;code&gt;# 이 줄은 주석입니다. 실행되지 않아요.
price = 1500   # 한 줄 끝에도 주석을 달 수 있습니다&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 흔한 에러 메시지 읽는 법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에러는 실패가 아니라 &lt;b&gt;컴퓨터가 주는 힌트&lt;/b&gt;입니다. 입문자가 자주 만나는 네 가지를 미리 익혀 두면 당황하지 않습니다.&lt;/p&gt;
&lt;div class=&quot;hb-tw&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;에러&lt;/th&gt;
&lt;th&gt;언제&lt;/th&gt;
&lt;th&gt;해결&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SyntaxError&lt;/td&gt;
&lt;td&gt;괄호&amp;middot;따옴표를 안 닫음&lt;/td&gt;
&lt;td&gt;짝이 맞는지 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NameError&lt;/td&gt;
&lt;td&gt;없는 변수를 사용&lt;/td&gt;
&lt;td&gt;오타&amp;middot;정의 여부 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TypeError&lt;/td&gt;
&lt;td&gt;숫자와 문자열을 더함&lt;/td&gt;
&lt;td&gt;int()/str()로 변환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IndentationError&lt;/td&gt;
&lt;td&gt;들여쓰기가 안 맞음&lt;/td&gt;
&lt;td&gt;공백 4칸으로 통일&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;pre class=&quot;hb-code vim&quot;&gt;&lt;code&gt;print(&quot;안녕)          # SyntaxError: 따옴표를 안 닫음
print(nmae)          # NameError: name 'nmae'... (오타)
print(&quot;나이:&quot; + 20)  # TypeError: can only concatenate str&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맨 아래 줄(&lt;code&gt;NameError&lt;/code&gt; 등)이 핵심입니다. 메시지를 그대로 검색하면 대부분 해결책이 나옵니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리 &amp;amp; 연습문제 (정답 포함)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 우리는 파이썬 3.14와 VS Code를 설치하고, 대화형 셸과 파일 두 방식으로 코드를 실행했으며, 변수&amp;middot;자료형(정수&amp;middot;실수&amp;middot;문자열&amp;middot;불)&amp;middot;형 변환, 그리고 흔한 에러까지 배웠습니다. 프로그래밍은 눈으로 읽어서 늘지 않습니다. 아래 세 문제는 꼭 직접 쳐보세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제 1.&lt;/b&gt; 자기 이름과 나이를 변수에 담아 &quot;○○님은 △△살입니다.&quot; 형태로 출력하기.&lt;br /&gt;&lt;b&gt;문제 2.&lt;/b&gt; &lt;code&gt;input()&lt;/code&gt;으로 두 숫자를 받아 합을 올바르게(숫자로) 출력하기.&lt;br /&gt;&lt;b&gt;문제 3.&lt;/b&gt; &lt;code&gt;type()&lt;/code&gt;으로 &lt;code&gt;10&lt;/code&gt;, &lt;code&gt;10.0&lt;/code&gt;, &lt;code&gt;&quot;10&quot;&lt;/code&gt;, &lt;code&gt;True&lt;/code&gt;의 자료형을 각각 확인하기.&lt;/p&gt;
&lt;div class=&quot;hb-note hb-green&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅ 정답 예시&lt;/b&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;hb-code hsp&quot;&gt;&lt;code&gt;# 문제 1
name = &quot;거대웅&quot;
age = 20
print(name + &quot;님은 &quot; + str(age) + &quot;살입니다.&quot;)

# 문제 2
a = int(input(&quot;첫 번째 수: &quot;))
b = int(input(&quot;두 번째 수: &quot;))
print(&quot;합:&quot;, a + b)

# 문제 3
for v in [10, 10.0, &quot;10&quot;, True]:
    print(v, type(v))&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;더 공부할 거리 (공식&amp;middot;추천 자료)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;  &lt;a href=&quot;https://docs.python.org/ko/3/tutorial/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;파이썬 공식 튜토리얼 (한국어)&lt;/a&gt; &amp;mdash; 가장 정확한 1차 자료&lt;/li&gt;
&lt;li&gt;  &lt;a href=&quot;https://wikidocs.net/book/1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;점프 투 파이썬 (위키독스, 무료)&lt;/a&gt; &amp;mdash; 한국어 입문 명저&lt;/li&gt;
&lt;li&gt;  &lt;a href=&quot;https://realpython.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Real Python&lt;/a&gt; &amp;mdash; 주제별 심화 영어 튜토리얼&lt;/li&gt;
&lt;li&gt;  &lt;a href=&quot;https://www.python.org/downloads/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;파이썬 공식 다운로드&lt;/a&gt; &amp;mdash; 항상 최신 버전&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 &lt;b&gt;2편&lt;/b&gt;에서는 자료형의 첫 주인공 &lt;b&gt;숫자형(int&amp;middot;float)&lt;/b&gt;을 깊이 파고듭니다. 정수와 실수의 차이, 나눗셈이 두 종류인 이유(&lt;code&gt;/&lt;/code&gt;와 &lt;code&gt;//&lt;/code&gt;), 부동소수점 오차가 왜 생기는지까지 &amp;mdash; 계산을 다루는 진짜 기초가 펼쳐집니다. 천천히, 그러나 끝까지 함께 가봅시다.  &lt;/p&gt;
&lt;/div&gt;</description>
      <category>AI/Coding</category>
      <category>PYTHON</category>
      <category>변수와자료형</category>
      <category>코딩입문</category>
      <category>파이썬</category>
      <category>파이썬3.14</category>
      <category>파이썬독학</category>
      <category>파이썬입문</category>
      <category>프로그래밍기초</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/96</guid>
      <comments>https://onethingflow.tistory.com/entry/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%85%EB%AC%B8-1%ED%8E%B8-%E2%80%94-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%B4-%EC%B2%98%EC%9D%8C%EC%9D%B4%EC%96%B4%EB%8F%84-%EA%B4%9C%EC%B0%AE%EC%8A%B5%EB%8B%88%EB%8B%A4-%EC%84%A4%EC%B9%98%EB%B6%80%ED%84%B0-%EC%B2%AB-%EC%BD%94%EB%93%9C-%EB%B3%80%EC%88%98%C2%B7%EC%9E%90%EB%A3%8C%ED%98%95%EA%B9%8C%EC%A7%80#entry96comment</comments>
      <pubDate>Wed, 10 Jun 2026 12:19:03 +0900</pubDate>
    </item>
    <item>
      <title>러닝 이어폰 추천 총정리 2026: 오픈이어&amp;middot;골전도&amp;middot;헬스장 겸용까지 가성비 비교</title>
      <link>https://onethingflow.tistory.com/entry/%EB%9F%AC%EB%8B%9D-%EC%9D%B4%EC%96%B4%ED%8F%B0-%EC%B6%94%EC%B2%9C-%EC%B4%9D%EC%A0%95%EB%A6%AC-2026-%EC%98%A4%ED%94%88%EC%9D%B4%EC%96%B4%C2%B7%EA%B3%A8%EC%A0%84%EB%8F%84%C2%B7%ED%97%AC%EC%8A%A4%EC%9E%A5-%EA%B2%B8%EC%9A%A9%EA%B9%8C%EC%A7%80-%EA%B0%80%EC%84%B1%EB%B9%84-%EB%B9%84%EA%B5%90</link>
      <description>&lt;!--
Tistory existing title to keep:
러닝 이어폰 추천 총정리 2026: 오픈이어·골전도·헬스장 겸용까지 가성비 비교

Updated inner title:
러닝 오픈이어 이어폰 추천 2026 업데이트: 오픈닷·집게형·귀걸이형·골전도·방수 직구까지 객관 비교

Tags:
러닝이어폰, 운동이어폰, 오픈이어이어폰, 골전도이어폰, 방수이어폰, 집게형이어폰, 귀걸이형이어폰, 샥즈오픈닷, 사운드코어, 이어폰직구
--&gt;

&lt;style&gt;
.hb-post{max-width:780px;margin:0 auto;line-height:1.86;font-size:17px;color:#222;word-break:keep-all;}
.hb-post *{box-sizing:border-box;}
.hb-post h1{margin:0 0 .7em;font-size:2em;line-height:1.28;font-weight:800;color:#111;}
.hb-post h2{margin:2.55em 0 .78em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.38em;border-bottom:2px solid #edf0f4;color:#111;}
.hb-post h3{margin:1.9em 0 .55em;font-size:1.08em;line-height:1.45;font-weight:800;color:#182033;}
.hb-post p{margin:0 0 1.12em;}
.hb-post a{color:#235ad1;text-decoration:none;border-bottom:1px solid rgba(35,90,209,.25);}
.hb-post a:hover{border-bottom-color:#235ad1;}
.hb-post strong{font-weight:800;}
.hb-post .hb-lead{font-size:1.08em;color:#343a46;}
.hb-post .hb-hero{margin:0 0 1.6em;padding:1.35em 1.4em;border:1px solid #e1e6ef;border-radius:8px;background:#f8fbff;}
.hb-post .hb-hero p:last-child{margin-bottom:0;}
.hb-post .hb-kpi{display:grid;grid-template-columns:repeat(3,1fr);gap:.85em;margin:1.4em 0;}
.hb-post .hb-kpi div{border:1px solid #e5e8ee;border-radius:8px;background:#fbfcfd;padding:1em;}
.hb-post .hb-kpi span{display:block;font-size:.82em;color:#687182;margin-bottom:.25em;}
.hb-post .hb-kpi strong{display:block;font-size:1.06em;color:#10141b;line-height:1.35;}
.hb-post .hb-note-box{background:#f7f9fc;border:1px solid #e3e9f2;border-left:4px solid #3f75ff;border-radius:8px;padding:1.1em 1.25em;margin:1.55em 0;}
.hb-post .hb-note-box p{margin:0 0 .58em;}
.hb-post .hb-note-box p:last-child{margin-bottom:0;}
.hb-post .hb-warn{background:#fff8f4;border-color:#f1d8cc;border-left-color:#e76f51;}
.hb-post .hb-green{background:#f4fbf8;border-color:#d7eee3;border-left-color:#2a9d8f;}
.hb-post blockquote.hb-pull{margin:1.55em 0;padding:.95em 1.15em;background:#fff9e8;border-left:4px solid #f2b705;border-radius:8px;font-size:1.04em;font-weight:800;color:#584500;}
.hb-post ul,.hb-post ol{margin:0 0 1.18em;padding-left:1.38em;}
.hb-post li{margin:.38em 0;}
.hb-post .hb-table-wrap{overflow-x:auto;margin:1.45em 0;-webkit-overflow-scrolling:touch;}
.hb-post table{border-collapse:collapse;width:100%;font-size:.92em;min-width:880px;}
.hb-post th,.hb-post td{border:1px solid #e1e5eb;padding:.72em .82em;text-align:left;vertical-align:top;}
.hb-post thead th{background:#f1f4f8;font-weight:800;color:#172033;}
.hb-post tbody tr:nth-child(even){background:#fafbfc;}
.hb-post caption{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);}
.hb-post .hb-badges{display:flex;flex-wrap:wrap;gap:.5em;margin:1em 0 1.4em;}
.hb-post .hb-badge{display:inline-flex;align-items:center;border:1px solid #dfe5ee;border-radius:999px;padding:.28em .68em;background:#fff;font-size:.84em;font-weight:700;color:#303846;}
.hb-post .hb-product-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:.9em;margin:1.45em 0;}
.hb-post .hb-product-card{border:1px solid #e1e6ef;border-radius:8px;background:#fff;overflow:hidden;}
.hb-post .hb-product-card img{display:block;width:100%;aspect-ratio:4/3;object-fit:contain;background:#fbfcfd;padding:.75em;}
.hb-post .hb-product-card div{padding:.9em 1em;}
.hb-post .hb-product-card strong{display:block;margin-bottom:.28em;color:#172033;}
.hb-post .hb-product-card p{margin:0;font-size:.9em;color:#566173;line-height:1.62;}
.hb-post .hb-pill{display:inline-block;border-radius:999px;background:#eef3ff;color:#1e3a8a;font-size:.82em;font-weight:800;padding:.12em .55em;margin-right:.25em;}
.hb-post .hb-small{font-size:.9em;color:#626b7a;}
.hb-post .hb-source{margin-top:2.7em;padding-top:1.2em;border-top:1px solid #edf0f4;font-size:.92em;color:#4b5565;}
.hb-post .hb-disclaimer{margin-top:1.6em;font-size:.88em;color:#7a8290;}
@media (max-width:640px){
  .hb-post{font-size:16px;}
  .hb-post h1{font-size:1.58em;}
  .hb-post .hb-kpi,.hb-post .hb-product-grid{grid-template-columns:1fr;}
  .hb-post table{font-size:.9em;min-width:980px;}
}
&lt;/style&gt;

&lt;article class=&quot;hb-post&quot;&gt;
  &lt;div class=&quot;hb-hero&quot;&gt;
    &lt;h1&gt;러닝 오픈이어 이어폰 추천 2026 업데이트&lt;/h1&gt;
    &lt;p class=&quot;hb-lead&quot;&gt;러닝 이어폰은 &quot;음질 좋은 제품&quot;만 고르면 꽤 높은 확률로 실패한다. 뛰는 동안 흔들리지 않는지, 안경이나 고글과 부딪히는지, 비와 땀을 버티는지, 도로에서 주변 소리를 들을 수 있는지가 실제 만족도를 가른다.&lt;/p&gt;
    &lt;p&gt;이번 업데이트는 기존 글의 결론을 다시 넓혔다. Shokz OpenRun Pro 2, Soundcore C50i, AeroFit 2만 보는 식이 아니라 &lt;strong&gt;오픈닷 같은 집게형, 귀걸이형 오픈이어, 넥밴드형 골전도, 수영형 MP3, 헬스장용 커널형 스포츠 이어버드&lt;/strong&gt;까지 후보군을 나눠서 비교했다. 가격과 스펙은 2026년 7월 12일 확인 기준이며, 할인과 재고는 계속 바뀔 수 있다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;div class=&quot;hb-kpi&quot;&gt;
    &lt;div&gt;
      &lt;span&gt;도로 러닝 안정성&lt;/span&gt;
      &lt;strong&gt;Shokz OpenRun Pro 2&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div&gt;
      &lt;span&gt;집게형 프리미엄&lt;/span&gt;
      &lt;strong&gt;Shokz OpenDots 2&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div&gt;
      &lt;span&gt;직구 가성비&lt;/span&gt;
      &lt;strong&gt;AeroFit 2 · C50i · TOZO&lt;/strong&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;blockquote class=&quot;hb-pull&quot;&gt;한 줄 결론을 하나로 줄이면 오히려 부정확하다. 러닝 안정성은 넥밴드형, 안경 간섭은 집게형, 일상 겸용은 귀걸이형, 수영은 MP3 내장 수영형, 헬스장 소음 차단은 커널형 스포츠 제품이 유리하다.&lt;/blockquote&gt;

  &lt;div class=&quot;hb-badges&quot;&gt;
    &lt;span class=&quot;hb-badge&quot;&gt;2026년 7월 업데이트&lt;/span&gt;
    &lt;span class=&quot;hb-badge&quot;&gt;공식 스펙 우선&lt;/span&gt;
    &lt;span class=&quot;hb-badge&quot;&gt;형태별 비교&lt;/span&gt;
    &lt;span class=&quot;hb-badge&quot;&gt;직구·AS 분리&lt;/span&gt;
  &lt;/div&gt;

  &lt;h2&gt;먼저 형태부터 고르자&lt;/h2&gt;
  &lt;p&gt;오픈이어 이어폰은 같은 &quot;귀를 막지 않는 이어폰&quot;이어도 구조가 꽤 다르다. 그래서 제품명을 먼저 고르기보다 내 운동 환경에 맞는 형태를 먼저 고르는 편이 낫다.&lt;/p&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;오픈이어 이어폰 형태별 장단점&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;형태&lt;/th&gt;
          &lt;th&gt;대표 제품&lt;/th&gt;
          &lt;th&gt;강점&lt;/th&gt;
          &lt;th&gt;주의점&lt;/th&gt;
          &lt;th&gt;잘 맞는 사람&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;넥밴드형 골전도·오픈이어&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Shokz OpenRun Pro 2, OpenSwim Pro, Mojawa Run Plus&lt;/td&gt;
          &lt;td&gt;흔들림이 가장 예측 가능하다. 좌우가 연결되어 분실 위험도 낮고 장거리 러닝에 안정적이다.&lt;/td&gt;
          &lt;td&gt;모자, 후드, 누워서 사용에는 불편할 수 있다. 음악 몰입감은 커널형보다 약하다.&lt;/td&gt;
          &lt;td&gt;도로 러닝, 장거리 러닝, 대회 훈련&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;귀걸이형 오픈이어&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Shokz OpenFit 2+, OpenFit Pro, Soundcore AeroFit 2, AeroFit Pro, Nothing Ear(open)&lt;/td&gt;
          &lt;td&gt;일상과 운동을 같이 쓰기 좋다. 배터리와 사운드 튜닝이 강한 제품이 많다.&lt;/td&gt;
          &lt;td&gt;안경 다리와 간섭이 생길 수 있고, 격한 인터벌에서는 개인 귀 모양 영향을 받는다.&lt;/td&gt;
          &lt;td&gt;러닝과 출퇴근을 한 제품으로 해결하고 싶은 사람&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;집게형·이어클립형&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Shokz OpenDots 2, OpenDots Air, Bose Ultra Open, Soundcore AeroClip, C50i, Huawei FreeClip, TOZO Open EarRing&lt;/td&gt;
          &lt;td&gt;안경과 같이 쓰기 비교적 쉽고, 착용감이 가볍다. 최근 신제품이 가장 많이 나오는 형태다.&lt;/td&gt;
          &lt;td&gt;귓바퀴를 집는 압박감은 사람마다 다르다. 러닝 중 고정력은 제품과 귀 모양 차이가 크다.&lt;/td&gt;
          &lt;td&gt;안경 착용자, 일상 겸용, 가벼운 조깅&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;커널형 스포츠 이어버드&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Powerbeats Pro 2, Jabra Elite 8 Active Gen 2&lt;/td&gt;
          &lt;td&gt;헬스장 소음 차단, 저음, ANC, 고정력이 좋다.&lt;/td&gt;
          &lt;td&gt;도로 러닝에서는 주변 소리 인지가 떨어질 수 있다. 투명 모드를 켜도 완전한 오픈이어와는 다르다.&lt;/td&gt;
          &lt;td&gt;러닝머신, 웨이트, HIIT, 실내 운동&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;수영형 MP3&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Shokz OpenSwim Pro, Mojawa Run Plus, Suunto Aqua Light&lt;/td&gt;
          &lt;td&gt;수영 용도를 제조사가 명시한 제품군이다. 물속에서는 MP3 내장 재생이 중요하다.&lt;/td&gt;
          &lt;td&gt;일반 IP55/IPX5 오픈이어는 수영용이 아니다. 블루투스는 물속에서 안정적으로 전달되기 어렵다.&lt;/td&gt;
          &lt;td&gt;수영, 철인 3종, 비 오는 장거리 훈련&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;평가 기준&lt;/h2&gt;
  &lt;p&gt;이번 글에서는 &quot;제가 하나만 산다면&quot; 같은 감각적인 결론보다, 제품을 비교할 때 실제로 체크할 항목을 먼저 세웠다. 착용감은 개인차가 커서 가짜 총점으로 포장하지 않고, 항목별로 강점과 주의점을 나눴다.&lt;/p&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;러닝 이어폰 평가 기준&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;기준&lt;/th&gt;
          &lt;th&gt;비중&lt;/th&gt;
          &lt;th&gt;확인 내용&lt;/th&gt;
          &lt;th&gt;이유&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;운동 중 고정력&lt;/td&gt;
          &lt;td&gt;20%&lt;/td&gt;
          &lt;td&gt;넥밴드, 귀걸이, 집게 구조와 조작 방식&lt;/td&gt;
          &lt;td&gt;러닝 중 한 번씩 흔들리기 시작하면 음악보다 스트레스가 먼저 온다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;장시간 착용감과 간섭&lt;/td&gt;
          &lt;td&gt;20%&lt;/td&gt;
          &lt;td&gt;무게, 안경·고글·모자 간섭, 압박 위치&lt;/td&gt;
          &lt;td&gt;30분은 괜찮아도 2시간 러닝에서는 작은 압박이 크게 느껴진다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;야외 주변 인지&lt;/td&gt;
          &lt;td&gt;15%&lt;/td&gt;
          &lt;td&gt;오픈이어 구조, 투명 모드 의존 여부&lt;/td&gt;
          &lt;td&gt;차량, 자전거, 보행자 소리는 도로 러닝에서 실제 안전 정보다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;땀·비·내구성&lt;/td&gt;
          &lt;td&gt;15%&lt;/td&gt;
          &lt;td&gt;IP 등급, 케이스 방수 여부, 수영 가능 여부&lt;/td&gt;
          &lt;td&gt;이어버드보다 충전 케이스와 충전 단자가 먼저 문제 되는 경우가 많다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;실구매가와 AS&lt;/td&gt;
          &lt;td&gt;15%&lt;/td&gt;
          &lt;td&gt;국내 정품, 직구 총액, 공식 판매처, 보증 제외 여부&lt;/td&gt;
          &lt;td&gt;스펙이 좋아도 반품과 AS가 불안하면 실제 가성비가 떨어진다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;배터리와 조작&lt;/td&gt;
          &lt;td&gt;10%&lt;/td&gt;
          &lt;td&gt;단독 재생 시간, 급속 충전, 물리 버튼 또는 터치&lt;/td&gt;
          &lt;td&gt;장거리 러닝과 장갑 착용 시에는 케이스 포함 시간보다 단독 시간이 중요하다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;음질·통화·앱&lt;/td&gt;
          &lt;td&gt;5%&lt;/td&gt;
          &lt;td&gt;코덱, 마이크, EQ, 멀티포인트&lt;/td&gt;
          &lt;td&gt;오픈이어는 구조상 차음과 저음에 한계가 있어 보조 기준으로 봤다.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;전체 후보군과 결론&lt;/h2&gt;
  &lt;p&gt;아래 표는 &quot;본문에서 자세히 비교할 제품&quot;과 &quot;좋지만 이번 글에서 주력 추천으로는 밀린 제품&quot;을 함께 넣었다. 세상에 제품은 많지만, 블로그 글에서는 공식 스펙과 구매 경로가 확인되는 후보를 중심으로 좁혀야 독자가 실제로 살 수 있다.&lt;/p&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;러닝 오픈이어 후보군 정리&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;분류&lt;/th&gt;
          &lt;th&gt;제품&lt;/th&gt;
          &lt;th&gt;판단&lt;/th&gt;
          &lt;th&gt;이유&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;넥밴드형&lt;/td&gt;
          &lt;td&gt;Shokz OpenRun Pro 2&lt;/td&gt;
          &lt;td&gt;&lt;span class=&quot;hb-pill&quot;&gt;주력 추천&lt;/span&gt;&lt;/td&gt;
          &lt;td&gt;도로 러닝 안정성과 주변 인지 기준으로 여전히 가장 안전한 선택지다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;집게형&lt;/td&gt;
          &lt;td&gt;Shokz OpenDots 2&lt;/td&gt;
          &lt;td&gt;&lt;span class=&quot;hb-pill&quot;&gt;주력 추천&lt;/span&gt;&lt;/td&gt;
          &lt;td&gt;OpenDots ONE보다 방수와 마이크 구성이 올라갔다. 집게형 프리미엄 후보로 반드시 넣어야 한다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;집게형&lt;/td&gt;
          &lt;td&gt;Shokz OpenDots Air&lt;/td&gt;
          &lt;td&gt;&lt;span class=&quot;hb-pill&quot;&gt;가성비 후보&lt;/span&gt;&lt;/td&gt;
          &lt;td&gt;OpenDots 2보다 저렴하고 9시간·36시간 배터리, IP55라 가벼운 조깅과 일상용에 맞다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;귀걸이형&lt;/td&gt;
          &lt;td&gt;Soundcore AeroFit 2 A3874&lt;/td&gt;
          &lt;td&gt;&lt;span class=&quot;hb-pill&quot;&gt;직구 가성비&lt;/span&gt;&lt;/td&gt;
          &lt;td&gt;10시간·42시간, IP55, LDAC, 조절식 이어후크 구성이라 가격이 내려가면 강하다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;집게형&lt;/td&gt;
          &lt;td&gt;Soundcore C50i D1101&lt;/td&gt;
          &lt;td&gt;&lt;span class=&quot;hb-pill&quot;&gt;국내 가성비&lt;/span&gt;&lt;/td&gt;
          &lt;td&gt;5.5g, IP55, 7시간·28시간, 버튼 조작. 국내 정품 가격이 좋으면 입문용으로 좋다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;집게형&lt;/td&gt;
          &lt;td&gt;Soundcore AeroClip A3388&lt;/td&gt;
          &lt;td&gt;&lt;span class=&quot;hb-pill&quot;&gt;중급 후보&lt;/span&gt;&lt;/td&gt;
          &lt;td&gt;8시간 배터리와 IP55, 가벼운 클립형. C50i보다 고급형, OpenDots 2보다 가격 방어가 관건이다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;귀걸이형&lt;/td&gt;
          &lt;td&gt;Shokz OpenFit 2+ / OpenFit Pro&lt;/td&gt;
          &lt;td&gt;&lt;span class=&quot;hb-pill&quot;&gt;프리미엄 후보&lt;/span&gt;&lt;/td&gt;
          &lt;td&gt;편안함과 브랜드 신뢰도는 좋지만 국내 가격이 높아 가성비 표에서는 불리하다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;귀걸이형&lt;/td&gt;
          &lt;td&gt;Soundcore AeroFit Pro&lt;/td&gt;
          &lt;td&gt;&lt;span class=&quot;hb-pill&quot;&gt;구형 할인 후보&lt;/span&gt;&lt;/td&gt;
          &lt;td&gt;14시간·46시간과 탈착식 넥밴드는 장점. 다만 AeroFit 2와 가격 차이를 보고 골라야 한다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;집게형&lt;/td&gt;
          &lt;td&gt;Bose Ultra Open Earbuds&lt;/td&gt;
          &lt;td&gt;&lt;span class=&quot;hb-pill&quot;&gt;음질·디자인 후보&lt;/span&gt;&lt;/td&gt;
          &lt;td&gt;착용감과 오픈이어 사운드가 강점이지만 IPX4와 가격 때문에 러닝 가성비 1순위는 아니다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;집게형&lt;/td&gt;
          &lt;td&gt;Huawei FreeClip / FreeClip 2&lt;/td&gt;
          &lt;td&gt;보류&lt;/td&gt;
          &lt;td&gt;제품 자체는 경쟁력이 있지만 국내 정식 유통, 앱, AS, 지역 모델 확인이 먼저다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;집게형&lt;/td&gt;
          &lt;td&gt;TOZO Open EarRing&lt;/td&gt;
          &lt;td&gt;초저가 직구 후보&lt;/td&gt;
          &lt;td&gt;가격은 매력적이다. 대신 반품·AS·정품 경로 리스크를 감수하는 제품이다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;커널형 스포츠&lt;/td&gt;
          &lt;td&gt;Powerbeats Pro 2, Jabra Elite 8 Active Gen 2&lt;/td&gt;
          &lt;td&gt;헬스장 별도 후보&lt;/td&gt;
          &lt;td&gt;오픈이어는 아니지만 실내 운동과 소음 차단 목적이면 더 잘 맞을 수 있다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;수영형&lt;/td&gt;
          &lt;td&gt;Shokz OpenSwim Pro, Mojawa Run Plus, Suunto Aqua Light&lt;/td&gt;
          &lt;td&gt;수영 별도 후보&lt;/td&gt;
          &lt;td&gt;수영은 IP55 오픈이어가 아니라 제조사가 수영 용도를 명시한 제품으로 봐야 한다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;신규·루머&lt;/td&gt;
          &lt;td&gt;Samsung Galaxy Able 등 미출시 제품&lt;/td&gt;
          &lt;td&gt;제외&lt;/td&gt;
          &lt;td&gt;2026년 7월 12일 기준 공식 출시 전 루머 제품은 추천 표에 넣지 않는다.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;공식 스펙 비교표&lt;/h2&gt;
  &lt;p&gt;스펙표만 보면 AeroFit 2나 C50i가 꽤 세게 보인다. 하지만 스펙과 실제 추천은 다르다. 러닝 안정성은 구조의 영향을 크게 받고, 직구 제품은 AS까지 더해야 진짜 가격이 된다.&lt;/p&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;주요 제품 공식 스펙 비교&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;제품&lt;/th&gt;
          &lt;th&gt;형태&lt;/th&gt;
          &lt;th&gt;무게&lt;/th&gt;
          &lt;th&gt;방수&lt;/th&gt;
          &lt;th&gt;배터리&lt;/th&gt;
          &lt;th&gt;조작&lt;/th&gt;
          &lt;th&gt;가격 기준&lt;/th&gt;
          &lt;th&gt;추천 판단&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Shokz OpenRun Pro 2&lt;/td&gt;
          &lt;td&gt;넥밴드형 골전도+공기전도&lt;/td&gt;
          &lt;td&gt;약 30.3g&lt;/td&gt;
          &lt;td&gt;IP55&lt;/td&gt;
          &lt;td&gt;최대 12시간&lt;/td&gt;
          &lt;td&gt;물리 버튼&lt;/td&gt;
          &lt;td&gt;국내 공식 249,000원&lt;/td&gt;
          &lt;td&gt;도로 러닝 안정성 기준 1순위&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Shokz OpenDots 2&lt;/td&gt;
          &lt;td&gt;집게형 오픈이어&lt;/td&gt;
          &lt;td&gt;이어버드 6.4g±0.2g&lt;/td&gt;
          &lt;td&gt;IP57&lt;/td&gt;
          &lt;td&gt;10시간 / 케이스 포함 40시간&lt;/td&gt;
          &lt;td&gt;탭+핀치&lt;/td&gt;
          &lt;td&gt;미국 공식 $199.95&lt;/td&gt;
          &lt;td&gt;집게형 프리미엄 추천&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Shokz OpenDots Air&lt;/td&gt;
          &lt;td&gt;집게형 오픈이어&lt;/td&gt;
          &lt;td&gt;이어버드 6.3g±0.2g&lt;/td&gt;
          &lt;td&gt;IP55&lt;/td&gt;
          &lt;td&gt;9시간 / 케이스 포함 36시간&lt;/td&gt;
          &lt;td&gt;탭+핀치&lt;/td&gt;
          &lt;td&gt;미국 공식 $129.95&lt;/td&gt;
          &lt;td&gt;Shokz 집게형 가성비&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Shokz OpenFit 2+&lt;/td&gt;
          &lt;td&gt;귀걸이형 오픈이어&lt;/td&gt;
          &lt;td&gt;이어버드 9.4g±0.2g&lt;/td&gt;
          &lt;td&gt;IP55&lt;/td&gt;
          &lt;td&gt;11시간 / 케이스 포함 48시간&lt;/td&gt;
          &lt;td&gt;버튼+터치&lt;/td&gt;
          &lt;td&gt;국내 공식 289,000원&lt;/td&gt;
          &lt;td&gt;일상 겸용 프리미엄&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Shokz OpenFit Pro&lt;/td&gt;
          &lt;td&gt;귀걸이형 오픈이어&lt;/td&gt;
          &lt;td&gt;이어버드 12.3g±0.2g&lt;/td&gt;
          &lt;td&gt;IP55&lt;/td&gt;
          &lt;td&gt;노이즈 리덕션 off 12시간 / 50시간&lt;/td&gt;
          &lt;td&gt;물리 버튼&lt;/td&gt;
          &lt;td&gt;미국 공식 $249.95&lt;/td&gt;
          &lt;td&gt;고급형이나 가격 부담 큼&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Soundcore AeroFit 2 A3874&lt;/td&gt;
          &lt;td&gt;귀걸이형 오픈이어&lt;/td&gt;
          &lt;td&gt;10g&lt;/td&gt;
          &lt;td&gt;IP55&lt;/td&gt;
          &lt;td&gt;10시간 / 케이스 포함 42시간&lt;/td&gt;
          &lt;td&gt;터치&lt;/td&gt;
          &lt;td&gt;미국 공식 $129.99&lt;/td&gt;
          &lt;td&gt;직구 귀걸이형 가성비&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Soundcore C50i D1101&lt;/td&gt;
          &lt;td&gt;집게형 오픈이어&lt;/td&gt;
          &lt;td&gt;5.5g&lt;/td&gt;
          &lt;td&gt;IP55&lt;/td&gt;
          &lt;td&gt;7시간 / 케이스 포함 28시간&lt;/td&gt;
          &lt;td&gt;버튼&lt;/td&gt;
          &lt;td&gt;미국 공식 $69.99, 국내 정품 별도 확인&lt;/td&gt;
          &lt;td&gt;저가 집게형 입문 추천&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Soundcore AeroClip A3388&lt;/td&gt;
          &lt;td&gt;집게형 오픈이어&lt;/td&gt;
          &lt;td&gt;약 6g급&lt;/td&gt;
          &lt;td&gt;IP55&lt;/td&gt;
          &lt;td&gt;약 8시간&lt;/td&gt;
          &lt;td&gt;터치&lt;/td&gt;
          &lt;td&gt;판매처와 할인 시점에 따라 변동&lt;/td&gt;
          &lt;td&gt;C50i보다 고급형, 가격이 관건&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Bose Ultra Open Earbuds&lt;/td&gt;
          &lt;td&gt;집게형·커프형 오픈이어&lt;/td&gt;
          &lt;td&gt;약 6g대&lt;/td&gt;
          &lt;td&gt;IPX4&lt;/td&gt;
          &lt;td&gt;최대 7시간 / 케이스 추가 약 19.5시간&lt;/td&gt;
          &lt;td&gt;버튼&lt;/td&gt;
          &lt;td&gt;미국 공식 세일 $199&lt;/td&gt;
          &lt;td&gt;음질·디자인은 좋지만 러닝 가성비는 보통&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;TOZO Open EarRing&lt;/td&gt;
          &lt;td&gt;집게형 오픈이어&lt;/td&gt;
          &lt;td&gt;5.1g&lt;/td&gt;
          &lt;td&gt;IPX5&lt;/td&gt;
          &lt;td&gt;10시간 / 케이스 포함 40시간&lt;/td&gt;
          &lt;td&gt;터치&lt;/td&gt;
          &lt;td&gt;공식 $49.99&lt;/td&gt;
          &lt;td&gt;초저가 직구 후보&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;제품 이미지와 링크&lt;/h2&gt;

  &lt;div class=&quot;hb-product-grid&quot;&gt;
    &lt;figure class=&quot;hb-product-card&quot;&gt;
      &lt;a href=&quot;https://shokz.co.kr/shop/openrun-pro2&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;
        &lt;img src=&quot;https://shokz.com/cdn/shop/files/OpenRun_Pro_2-OG-1.webp?v=1772616674&amp;amp;width=1000&quot; alt=&quot;Shokz OpenRun Pro 2 공식 제품 이미지&quot; loading=&quot;lazy&quot;&gt;
      &lt;/a&gt;
      &lt;div&gt;
        &lt;strong&gt;Shokz OpenRun Pro 2&lt;/strong&gt;
        &lt;p&gt;도로 러닝과 장거리 훈련 기준. 국내 공식 가격과 2년 AS 조건 확인.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/figure&gt;
    &lt;figure class=&quot;hb-product-card&quot;&gt;
      &lt;a href=&quot;https://shokz.com/products/opendots-2&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;
        &lt;img src=&quot;https://shokz.com/cdn/shop/files/opendots2-white.webp?width=1000&quot; alt=&quot;Shokz OpenDots 2 공식 제품 이미지&quot; loading=&quot;lazy&quot;&gt;
      &lt;/a&gt;
      &lt;div&gt;
        &lt;strong&gt;Shokz OpenDots 2&lt;/strong&gt;
        &lt;p&gt;집게형 프리미엄 후보. IP57, 10시간·40시간, 블루투스 6.1.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/figure&gt;
    &lt;figure class=&quot;hb-product-card&quot;&gt;
      &lt;a href=&quot;https://shokz.co.kr/shop/openfit2plus&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;
        &lt;img src=&quot;https://shokz.com/cdn/shop/files/openfit2-Black.webp?v=1735287107&amp;amp;width=1000&quot; alt=&quot;Shokz OpenFit 2 Plus 공식 제품 이미지&quot; loading=&quot;lazy&quot;&gt;
      &lt;/a&gt;
      &lt;div&gt;
        &lt;strong&gt;Shokz OpenFit 2+&lt;/strong&gt;
        &lt;p&gt;귀걸이형 프리미엄. 일상 겸용과 편안함을 우선할 때 비교.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/figure&gt;
    &lt;figure class=&quot;hb-product-card&quot;&gt;
      &lt;a href=&quot;https://www.soundcore.com/products/a3874-aerofit-2-open-earbuds&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;
        &lt;img src=&quot;https://cdn.shopify.com/s/files/1/0516/3761/6830/files/A3874_TD01_V1_1200x.webp?width=1000&quot; alt=&quot;Soundcore AeroFit 2 공식 제품 이미지&quot; loading=&quot;lazy&quot;&gt;
      &lt;/a&gt;
      &lt;div&gt;
        &lt;strong&gt;Soundcore AeroFit 2 A3874&lt;/strong&gt;
        &lt;p&gt;직구 귀걸이형 가성비 후보. 국내 모델 A3874X와 혼동하지 말 것.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/figure&gt;
    &lt;figure class=&quot;hb-product-card&quot;&gt;
      &lt;a href=&quot;https://www.soundcore.com/products/d1101-c50i-comfortable-clip-on-earbuds&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;
        &lt;img src=&quot;https://cdn.shopify.com/s/files/1/0516/3761/6830/files/D1101_TD01_V1_1200x.webp?width=1000&quot; alt=&quot;Soundcore C50i 공식 제품 이미지&quot; loading=&quot;lazy&quot;&gt;
      &lt;/a&gt;
      &lt;div&gt;
        &lt;strong&gt;Soundcore C50i D1101&lt;/strong&gt;
        &lt;p&gt;5만원대 전후 국내 정품 가격이 좋으면 입문용으로 강한 제품.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/figure&gt;
    &lt;figure class=&quot;hb-product-card&quot;&gt;
      &lt;a href=&quot;https://www.soundcore.com/products/aerofit-pro-a3871011&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;
        &lt;img src=&quot;https://cdn.shopify.com/s/files/1/0516/3761/6830/files/A3871Z12_TD01_V1_1200x_5fbff9b8-d10f-477e-9c6d-d2a8b4eb4725.webp?v=1749638468&quot; alt=&quot;Soundcore AeroFit Pro 공식 제품 이미지&quot; loading=&quot;lazy&quot;&gt;
      &lt;/a&gt;
      &lt;div&gt;
        &lt;strong&gt;Soundcore AeroFit Pro&lt;/strong&gt;
        &lt;p&gt;구형 할인 후보. 14시간 단독 배터리와 탈착식 넥밴드가 장점.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/figure&gt;
    &lt;figure class=&quot;hb-product-card&quot;&gt;
      &lt;a href=&quot;https://www.bose.com/p/earbuds/bose-ultra-open-earbuds/ULT-HEADPHONEOPN.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;
        &lt;img src=&quot;https://assets.bosecreative.com/transform/7c05ef9a-9753-4b72-8589-3f9b2e00f325/UOEBLE26-MoonlightGrey_SF_PDP_E-Comm-Gallery_1_1632x1224?format=avif&amp;amp;io=width%3A816%2Cheight%3A667%2Ctransform%3Afit&amp;amp;quality=95&quot; alt=&quot;Bose Ultra Open Earbuds 공식 제품 이미지&quot; loading=&quot;lazy&quot;&gt;
      &lt;/a&gt;
      &lt;div&gt;
        &lt;strong&gt;Bose Ultra Open Earbuds&lt;/strong&gt;
        &lt;p&gt;음질과 디자인 중시형. 러닝 전용보다는 일상 겸용 프리미엄에 가깝다.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/figure&gt;
    &lt;figure class=&quot;hb-product-card&quot;&gt;
      &lt;a href=&quot;https://www.beatsbydre.com/earbuds/powerbeats-pro-2&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;
        &lt;img src=&quot;https://www.beatsbydre.com/content/dam/beats/web/product/earbuds/powerbeats-pro-2/pdp/pbpro2-in-the-box.png.large.2x.png&quot; alt=&quot;Powerbeats Pro 2 공식 제품 이미지&quot; loading=&quot;lazy&quot;&gt;
      &lt;/a&gt;
      &lt;div&gt;
        &lt;strong&gt;Powerbeats Pro 2&lt;/strong&gt;
        &lt;p&gt;오픈이어는 아니지만 헬스장과 러닝머신 겸용이면 강력한 대안.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/figure&gt;
  &lt;/div&gt;

&lt;h2&gt;상황별 추천&lt;/h2&gt;
  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;상황별 러닝 이어폰 추천&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;상황&lt;/th&gt;
          &lt;th&gt;1순위&lt;/th&gt;
          &lt;th&gt;대안&lt;/th&gt;
          &lt;th&gt;이유&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;도로 러닝, 장거리, 대회 훈련&lt;/td&gt;
          &lt;td&gt;Shokz OpenRun Pro 2&lt;/td&gt;
          &lt;td&gt;OpenRun, OpenSwim Pro&lt;/td&gt;
          &lt;td&gt;넥밴드형은 흔들림이 가장 예측 가능하고 주변 소리 인지도 좋다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;안경 착용자, 집게형 선호&lt;/td&gt;
          &lt;td&gt;Shokz OpenDots 2&lt;/td&gt;
          &lt;td&gt;Bose Ultra Open, Soundcore AeroClip, C50i&lt;/td&gt;
          &lt;td&gt;귀 뒤를 크게 덮는 귀걸이형보다 안경 간섭이 적을 가능성이 높다. 다만 귓바퀴 압박은 실착 확인이 필요하다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;귀걸이형 직구 가성비&lt;/td&gt;
          &lt;td&gt;Soundcore AeroFit 2 A3874&lt;/td&gt;
          &lt;td&gt;AeroFit Pro 할인, OpenFit Air&lt;/td&gt;
          &lt;td&gt;스펙과 가격 균형이 좋다. 단, 국내 AS를 포기하는 가격 차이가 충분해야 직구 의미가 있다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;5만원대 전후 입문&lt;/td&gt;
          &lt;td&gt;Soundcore C50i D1101&lt;/td&gt;
          &lt;td&gt;TOZO Open EarRing&lt;/td&gt;
          &lt;td&gt;버튼 조작, IP55, 5.5g, 국내 정품 가능성이 장점이다. TOZO는 더 싸지만 AS 리스크가 크다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;일상·출퇴근·가벼운 조깅&lt;/td&gt;
          &lt;td&gt;Shokz OpenFit 2+&lt;/td&gt;
          &lt;td&gt;Nothing Ear(open), Bose Ultra Open&lt;/td&gt;
          &lt;td&gt;착용감과 앱, 통화, 배터리의 균형이 중요하다. 가격 부담이 크면 Soundcore 쪽으로 내려오면 된다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;헬스장, 러닝머신, 웨이트&lt;/td&gt;
          &lt;td&gt;Powerbeats Pro 2&lt;/td&gt;
          &lt;td&gt;Jabra Elite 8 Active Gen 2&lt;/td&gt;
          &lt;td&gt;실내 운동은 주변 인지보다 고정력, ANC, 저음, 통화가 더 중요할 수 있다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;수영&lt;/td&gt;
          &lt;td&gt;Shokz OpenSwim Pro&lt;/td&gt;
          &lt;td&gt;Mojawa Run Plus, Suunto Aqua Light&lt;/td&gt;
          &lt;td&gt;수영은 생활 방수 오픈이어가 아니라 MP3 내장 수영형으로 가야 한다.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;오픈닷은 왜 넣어야 하나&lt;/h2&gt;
  &lt;p&gt;사용자가 &quot;오픈닷도 있는데 왜 빠졌냐&quot;고 느끼는 건 당연하다. Shokz OpenDots 2와 OpenDots Air는 2026년 기준 집게형 오픈이어에서 중요한 후보가 됐다. 특히 OpenDots 2는 공식 비교표 기준 IP57, 10시간 단독 재생, 케이스 포함 40시간, 6.4g급 무게, 블루투스 6.1, 탭과 핀치 조작을 갖췄다.&lt;/p&gt;
  &lt;p&gt;다만 &quot;집게형이 무조건 러닝 최강&quot;은 아니다. 집게형은 안경 간섭이 적고 가볍지만, 귓바퀴를 집는 위치가 사람마다 달라서 압박감과 고정력이 크게 갈린다. 빠른 페이스의 인터벌, 땀이 많은 여름, 귀가 작은 사람은 반드시 반품 가능한 곳에서 사는 게 낫다.&lt;/p&gt;

  &lt;div class=&quot;hb-note-box&quot;&gt;
    &lt;p&gt;&lt;strong&gt;OpenDots 선택법:&lt;/strong&gt; 가격이 같거나 차이가 작으면 OpenDots 2가 낫다. 가격을 낮추고 싶으면 OpenDots Air, 구형 OpenDots ONE은 큰 할인이 있을 때만 비교하면 된다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2&gt;AeroFit 2 vs AeroFit Pro&lt;/h2&gt;
  &lt;p&gt;PDF의 시작 질문처럼 Soundcore AeroFit 2와 AeroFit Pro를 헷갈리기 쉽다. 이름만 보면 Pro가 무조건 위처럼 보이지만, 현재 기준으로는 용도가 조금 다르다.&lt;/p&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;Soundcore AeroFit 2와 AeroFit Pro 비교&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;항목&lt;/th&gt;
          &lt;th&gt;AeroFit 2 A3874&lt;/th&gt;
          &lt;th&gt;AeroFit Pro A3871&lt;/th&gt;
          &lt;th&gt;판단&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;형태&lt;/td&gt;
          &lt;td&gt;조절식 귀걸이형&lt;/td&gt;
          &lt;td&gt;귀걸이형 + 탈착식 넥밴드&lt;/td&gt;
          &lt;td&gt;격한 운동은 Pro의 넥밴드가 유리할 수 있다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;배터리&lt;/td&gt;
          &lt;td&gt;10시간 / 42시간&lt;/td&gt;
          &lt;td&gt;14시간 / 46시간&lt;/td&gt;
          &lt;td&gt;긴 운동은 Pro, 평소 사용은 2도 충분하다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;방수&lt;/td&gt;
          &lt;td&gt;IP55&lt;/td&gt;
          &lt;td&gt;IPX5&lt;/td&gt;
          &lt;td&gt;먼지 등급까지 보면 2가 표기상 더 깔끔하다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;조작&lt;/td&gt;
          &lt;td&gt;터치&lt;/td&gt;
          &lt;td&gt;물리 버튼&lt;/td&gt;
          &lt;td&gt;땀·장갑·러닝 중 조작은 버튼이 편하다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;가격&lt;/td&gt;
          &lt;td&gt;미국 공식 $129.99&lt;/td&gt;
          &lt;td&gt;미국 공식 $179.99&lt;/td&gt;
          &lt;td&gt;할인 없는 기준에서는 AeroFit 2가 가성비 우세다.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;직구로 가성비 제품 사는 법&lt;/h2&gt;
  &lt;p&gt;직구는 싸게 사는 방법이 맞다. 하지만 제품가만 보고 &quot;무조건 이득&quot;이라고 판단하면 안 된다. 특히 오픈이어 이어폰은 모델코드가 지역별로 다르고, 국내 AS가 빠지는 순간 몇 만 원 차이가 의미 없어질 수 있다.&lt;/p&gt;

  &lt;ol&gt;
    &lt;li&gt;&lt;strong&gt;모델코드부터 본다.&lt;/strong&gt; Soundcore AeroFit 2 A3874와 국내 A3874X처럼 지역형 모델이 섞일 수 있다. 같은 이름이어도 색상, 앱 기능, 인증, 구성품이 다를 수 있다.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;총액으로 비교한다.&lt;/strong&gt; 제품가, 배송비, 카드 해외결제 수수료, 환율, 관부가세 가능성, 반품비를 더한다. 애매하면 관세청 예상세액 조회로 확인한다.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;AS 가격을 붙인다.&lt;/strong&gt; 앤커코리아 FAQ는 해외 직구나 비공식 경로 구매품을 서비스 대상에서 제외한다고 안내한다. 국내 정품과 직구 가격 차이가 작으면 국내 정품이 더 싸게 먹힐 수 있다.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;반품 가능한 판매처를 고른다.&lt;/strong&gt; 집게형과 귀걸이형은 귀 모양 차이가 커서 스펙만으로 착용감을 확정하기 어렵다.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;KC/RRA와 재판매를 구분한다.&lt;/strong&gt; 개인 사용 목적의 1대 반입과 판매 목적 수입은 다르다. 직구품을 되팔 생각이면 인증 문제가 생길 수 있다.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;수영용은 더 조심한다.&lt;/strong&gt; IP55, IPX5는 수영용 표시가 아니다. 물속에서 쓸 제품은 제조사가 수영을 명시한 제품과 MP3 저장 기능을 본다.&lt;/li&gt;
  &lt;/ol&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;직구 추천 판단표&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;제품군&lt;/th&gt;
          &lt;th&gt;직구 매력&lt;/th&gt;
          &lt;th&gt;국내 정품 매력&lt;/th&gt;
          &lt;th&gt;판단 기준&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;AeroFit 2&lt;/td&gt;
          &lt;td&gt;미국 공식가가 낮고 할인 때 강하다.&lt;/td&gt;
          &lt;td&gt;국내 모델은 AS와 배송이 편하다.&lt;/td&gt;
          &lt;td&gt;최소 3만~5만원 이상 차이가 나야 직구 의미가 커진다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;C50i&lt;/td&gt;
          &lt;td&gt;직구도 싸지만 저가 제품이라 반품비 부담이 상대적으로 크다.&lt;/td&gt;
          &lt;td&gt;국내 정품가가 좋으면 AS 포함 가성비가 좋다.&lt;/td&gt;
          &lt;td&gt;국내 5만원대 전후면 국내 정품 우선.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;OpenDots 2&lt;/td&gt;
          &lt;td&gt;국내 출시가와 미국 가격 차이가 클 때만 검토.&lt;/td&gt;
          &lt;td&gt;프리미엄 제품이라 AS 가치가 크다.&lt;/td&gt;
          &lt;td&gt;실착 실패 가능성을 생각해 반품 조건을 먼저 본다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;TOZO·저가 브랜드&lt;/td&gt;
          &lt;td&gt;가격 자체가 낮다.&lt;/td&gt;
          &lt;td&gt;국내 공식 AS 기대는 낮다.&lt;/td&gt;
          &lt;td&gt;고장 나면 교체보다 새로 산다는 마음이면 가능.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;수영용은 따로 봐야 한다&lt;/h2&gt;
  &lt;p&gt;러닝 글에서 가장 자주 헷갈리는 부분이 방수다. IP55나 IPX5는 땀과 비에는 도움이 되지만, 수영장에서 쓰라고 만든 등급은 아니다. 물속에서는 블루투스 신호가 안정적으로 전달되기 어렵기 때문에 MP3 저장 기능이 있는 제품이 훨씬 현실적이다.&lt;/p&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;수영형 후보 비교&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;제품&lt;/th&gt;
          &lt;th&gt;형태&lt;/th&gt;
          &lt;th&gt;핵심&lt;/th&gt;
          &lt;th&gt;추천 대상&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Shokz OpenSwim Pro&lt;/td&gt;
          &lt;td&gt;넥밴드형 골전도&lt;/td&gt;
          &lt;td&gt;블루투스와 MP3를 함께 쓰는 수영형 라인&lt;/td&gt;
          &lt;td&gt;수영과 러닝을 모두 하는 사람&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Mojawa Run Plus&lt;/td&gt;
          &lt;td&gt;넥밴드형 골전도&lt;/td&gt;
          &lt;td&gt;IP68, 32GB MP3 저장을 앞세운 직구 후보&lt;/td&gt;
          &lt;td&gt;직구와 수영용 MP3를 같이 보는 사람&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Suunto Aqua Light&lt;/td&gt;
          &lt;td&gt;넥밴드형 골전도&lt;/td&gt;
          &lt;td&gt;스포츠 브랜드 기반 수중 운동 후보&lt;/td&gt;
          &lt;td&gt;수영 훈련과 스포츠 생태계를 중시하는 사람&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;최종 추천 정리&lt;/h2&gt;
  &lt;div class=&quot;hb-note-box hb-green&quot;&gt;
    &lt;p&gt;&lt;strong&gt;도로 러닝 안정성:&lt;/strong&gt; Shokz OpenRun Pro 2&lt;/p&gt;
    &lt;p&gt;이 결론은 &quot;세상에서 제일 좋은 이어폰&quot;이라는 뜻이 아니다. 도로 러닝에서 주변 소리와 고정력을 동시에 보려면 넥밴드형이 가장 예측 가능하다는 뜻이다.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;hb-note-box&quot;&gt;
    &lt;p&gt;&lt;strong&gt;집게형 프리미엄:&lt;/strong&gt; Shokz OpenDots 2&lt;/p&gt;
    &lt;p&gt;오픈닷은 이번 업데이트에서 빠지면 안 되는 핵심 후보다. 안경 착용자, 일상 겸용, 집게형 선호라면 먼저 비교할 만하다.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;hb-note-box&quot;&gt;
    &lt;p&gt;&lt;strong&gt;집게형 가성비:&lt;/strong&gt; Soundcore C50i&lt;/p&gt;
    &lt;p&gt;국내 정품가가 좋을 때 입문용으로 현실적이다. 직구 초저가는 TOZO도 있지만, AS와 반품까지 넣으면 C50i가 더 편할 수 있다.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;hb-note-box&quot;&gt;
    &lt;p&gt;&lt;strong&gt;귀걸이형 직구 가성비:&lt;/strong&gt; Soundcore AeroFit 2 A3874&lt;/p&gt;
    &lt;p&gt;스펙 대비 가격이 좋다. 다만 국내 A3874X와 혼동하지 말고, AS 제외를 감수할 만큼 가격 차이가 나는지 봐야 한다.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;hb-note-box&quot;&gt;
    &lt;p&gt;&lt;strong&gt;헬스장 겸용:&lt;/strong&gt; Powerbeats Pro 2 또는 Jabra Elite 8 Active Gen 2&lt;/p&gt;
    &lt;p&gt;오픈이어는 아니지만 실내 운동에서는 차음, ANC, 저음, 강한 고정력이 더 중요할 때가 있다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2&gt;구매 전 체크리스트&lt;/h2&gt;
  &lt;ul&gt;
    &lt;li&gt;도로에서 뛴다면 ANC보다 주변 소리 인지를 먼저 본다.&lt;/li&gt;
    &lt;li&gt;안경을 쓴다면 귀걸이형보다 집게형이 편할 수 있지만, 귓바퀴 압박은 꼭 확인한다.&lt;/li&gt;
    &lt;li&gt;장거리 러닝이면 케이스 포함 시간이 아니라 이어버드 단독 시간을 본다.&lt;/li&gt;
    &lt;li&gt;비와 땀이 많으면 IP55 이상을 우선하되, 수영은 별도 수영형으로 고른다.&lt;/li&gt;
    &lt;li&gt;직구 제품은 제품가가 아니라 총액과 AS 제외 리스크까지 더한다.&lt;/li&gt;
    &lt;li&gt;같은 이름의 지역별 모델코드를 확인한다.&lt;/li&gt;
    &lt;li&gt;리뷰 한두 개보다 반품 조건이 더 중요할 때가 있다. 특히 집게형은 귀 모양을 많이 탄다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h2&gt;FAQ&lt;/h2&gt;
  &lt;h3&gt;Q. 하나만 고르면 뭐가 제일 좋나요?&lt;/h3&gt;
  &lt;p&gt;도로 러닝만 보면 OpenRun Pro 2, 집게형을 원하면 OpenDots 2, 가성비를 원하면 C50i나 AeroFit 2다. 하나의 전체 1위보다 용도별 1위가 더 정확하다.&lt;/p&gt;

  &lt;h3&gt;Q. 오픈닷이 OpenRun Pro 2보다 더 좋은가요?&lt;/h3&gt;
  &lt;p&gt;좋고 나쁨의 문제가 아니라 형태가 다르다. OpenDots 2는 가볍고 안경 간섭이 적을 수 있지만, 격한 러닝의 예측 가능한 고정력은 넥밴드형 OpenRun Pro 2가 더 유리하다.&lt;/p&gt;

  &lt;h3&gt;Q. 직구가 무조건 싼가요?&lt;/h3&gt;
  &lt;p&gt;아니다. 제품가만 보면 싼데 배송비, 환율, 카드 수수료, 관부가세 가능성, 반품비, AS 제외를 더하면 국내 정품이 더 나은 경우도 많다.&lt;/p&gt;

  &lt;h3&gt;Q. IP55면 수영해도 되나요?&lt;/h3&gt;
  &lt;p&gt;아니다. IP55는 땀과 비 중심으로 보는 편이 맞다. 수영은 OpenSwim Pro처럼 제조사가 수영 용도를 명시한 제품을 봐야 한다.&lt;/p&gt;

  &lt;h3&gt;Q. 이 글은 실제 착용 리뷰인가요?&lt;/h3&gt;
  &lt;p&gt;아니다. 이 글은 공식 스펙, 공식 판매가, 국내 AS 조건, 형태별 구조를 바탕으로 한 구매 가이드다. 착용감은 귀 모양 차이가 크므로 반품 조건이 좋은 판매처를 고르는 것이 안전하다.&lt;/p&gt;

  &lt;div class=&quot;hb-source&quot;&gt;
    &lt;h2&gt;참고 자료와 공식 링크&lt;/h2&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://shokz.co.kr/shop/openrun-pro2&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Shokz Korea OpenRun Pro 2 공식 페이지&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://shokz.com/products/opendots-2&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Shokz OpenDots 2 공식 페이지&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://shokz.com/products/opendots-air&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Shokz OpenDots Air 공식 페이지&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://shokz.co.kr/shop/openfit2plus&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Shokz Korea OpenFit 2+ 공식 페이지&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://shokz.com/products/openfit-pro&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Shokz OpenFit Pro 공식 페이지&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.soundcore.com/products/a3874-aerofit-2-open-earbuds&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Soundcore AeroFit 2 공식 페이지&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.soundcore.com/products/d1101-c50i-comfortable-clip-on-earbuds&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Soundcore C50i 공식 페이지&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://service.soundcore.com/article-description/soundcore-AeroClip-FAQ&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Soundcore AeroClip 공식 FAQ&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://ankerkorea.co.kr/board/faq/list.html?board_no=3&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;앤커코리아 공식 AS FAQ&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.bose.com/p/earbuds/bose-ultra-open-earbuds/ULT-HEADPHONEOPN.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Bose Ultra Open Earbuds 공식 페이지&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.tozostore.com/products/openearring-headphone&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;TOZO Open EarRing 공식 페이지&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.customs.go.kr/kcs/ad/tax/BuyTaxCalculation.do&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;관세청 해외직구 예상세액 조회&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.rra.go.kr/ko/notice/licenseList_view.do?db_seq=887&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;국립전파연구원 개인 사용 목적 반입 안내&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
    &lt;p class=&quot;hb-disclaimer&quot;&gt;가격, 할인, 재고, AS 조건은 2026년 7월 12일 확인 기준이며 판매처와 시점에 따라 달라질 수 있다. 이 글은 제휴 링크 없이 작성했다.&lt;/p&gt;
  &lt;/div&gt;
&lt;/article&gt;</description>
      <category>Exercise/running</category>
      <category>골전도이어폰</category>
      <category>귀걸이형이어폰</category>
      <category>러닝이어폰</category>
      <category>방수이어폰</category>
      <category>사운드코어</category>
      <category>샥즈오픈닷</category>
      <category>오픈이어이어폰</category>
      <category>운동이어폰</category>
      <category>이어폰직구</category>
      <category>집게형이어폰</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/95</guid>
      <comments>https://onethingflow.tistory.com/entry/%EB%9F%AC%EB%8B%9D-%EC%9D%B4%EC%96%B4%ED%8F%B0-%EC%B6%94%EC%B2%9C-%EC%B4%9D%EC%A0%95%EB%A6%AC-2026-%EC%98%A4%ED%94%88%EC%9D%B4%EC%96%B4%C2%B7%EA%B3%A8%EC%A0%84%EB%8F%84%C2%B7%ED%97%AC%EC%8A%A4%EC%9E%A5-%EA%B2%B8%EC%9A%A9%EA%B9%8C%EC%A7%80-%EA%B0%80%EC%84%B1%EB%B9%84-%EB%B9%84%EA%B5%90#entry95comment</comments>
      <pubDate>Wed, 10 Jun 2026 12:08:04 +0900</pubDate>
    </item>
    <item>
      <title>블로그 플랫폼 비교 2026: 티스토리&amp;middot;블로그스팟&amp;middot;워드프레스&amp;middot;GitHub Pages&amp;middot;Velog 어디에 시작할까</title>
      <link>https://onethingflow.tistory.com/entry/%EB%B8%94%EB%A1%9C%EA%B7%B8-%ED%94%8C%EB%9E%AB%ED%8F%BC-%EA%B8%B0%EB%8A%A5-%EB%B9%84%EA%B5%90-%EC%B4%9D-%EC%A0%95%EB%A6%AC-%EB%B8%94%EB%A1%9C%EA%B7%B8%EC%8A%A4%ED%8C%9F-%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC-%EC%9B%8C%EB%93%9C%ED%94%84%EB%A0%88%EC%8A%A4-githubio-%EB%B2%A8%EB%A1%9C%EA%B7%B8-%EB%93%B1</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Y1IfL/dJMcai4CM5D/ST8jPxCydGrRYGuaxFAW31/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Y1IfL/dJMcai4CM5D/ST8jPxCydGrRYGuaxFAW31/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Y1IfL/dJMcai4CM5D/ST8jPxCydGrRYGuaxFAW31/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FY1IfL%2FdJMcai4CM5D%2FST8jPxCydGrRYGuaxFAW31%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1600&quot; height=&quot;1200&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블로그 플랫폼은 처음 정하면 오래 갑니다. 글쓰기 편의성보다 수익화, 이전 가능성, 검색 노출, 운영 리스크까지 함께 봐야 합니다. 이미지: Nick Morrison, Unsplash.&lt;/p&gt;
&lt;h1 data-ke-size=&quot;size30&quot;&gt;블로그 플랫폼 비교 2026: 티스토리&amp;middot;블로그스팟&amp;middot;워드프레스&amp;middot;GitHub Pages&amp;middot;Velog 어디에 시작할까&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블로그를 시작할 때 가장 먼저 부딪히는 질문은 &amp;ldquo;어디에 만들까?&amp;rdquo;입니다. 티스토리는 애드센스와 한국어 자료가 강하고, 블로그스팟은 구글 계정으로 빠르게 시작하기 좋습니다. 워드프레스는 확장성이 뛰어나지만 비용과 관리 난도가 올라갑니다. GitHub Pages는 개발자에게 강력하지만 일반 블로그 운영에는 CMS가 부족하고, Velog는 개발자 글쓰기와 커뮤니티 노출에는 좋지만 수익형 블로그에는 맞지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 2026년 6월 10일 기준으로 Blogger, Google AdSense, WordPress.com, GitHub Pages, Tistory 공식 공지와 공개 페이지를 확인해 다시 정리한 비교 글입니다. 단순히 &amp;ldquo;무료냐 유료냐&amp;rdquo;가 아니라 애드센스 승인, 커스텀 도메인, 디자인 수정, 검색 노출, 백업과 이전 가능성까지 함께 봅니다.&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fff8e1;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결론부터 말하면&lt;/b&gt; 애드센스 수익형 블로그를 한국어로 운영하려면 티스토리 또는 워드프레스가 가장 현실적입니다. 무료로 구글 생태계에서 시작하려면 블로그스팟, 개발 포트폴리오와 기술 문서라면 GitHub Pages나 Velog가 더 맞습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;먼저 결론: 목적별 추천 플랫폼&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;목적&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;1순위&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;대안&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;이유&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;애드센스 수익형 블로그&lt;/td&gt;
&lt;td&gt;&lt;b&gt;티스토리&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;워드프레스&lt;/td&gt;
&lt;td&gt;한국어 자료가 많고, 스킨 수정과 광고 배치가 비교적 쉽습니다. 다만 플랫폼 정책 변경 리스크는 봐야 합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;장기 자산형 사이트&lt;/td&gt;
&lt;td&gt;&lt;b&gt;워드프레스&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;GitHub Pages&lt;/td&gt;
&lt;td&gt;도메인, 플러그인, 백업, 이전, 확장성이 좋습니다. 대신 호스팅&amp;middot;보안&amp;middot;업데이트 관리가 필요합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;무료로 가볍게 시작&lt;/td&gt;
&lt;td&gt;&lt;b&gt;블로그스팟&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;티스토리&lt;/td&gt;
&lt;td&gt;Google 계정만 있으면 바로 시작할 수 있고 AdSense 연동 안내도 공식적으로 제공됩니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;개발자 포트폴리오&amp;middot;문서&lt;/td&gt;
&lt;td&gt;&lt;b&gt;GitHub Pages&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Velog&lt;/td&gt;
&lt;td&gt;정적 사이트를 저장소에서 바로 배포할 수 있고, 코드 이력과 문서 관리가 깔끔합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;개발자 커뮤니티 노출&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Velog&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;GitHub Pages&lt;/td&gt;
&lt;td&gt;Markdown 기반 글쓰기와 개발자 독자층 접근성이 장점입니다. 수익화&amp;middot;디자인 자유도는 약합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;비교 기준: 블로그 플랫폼은 이 7가지를 봐야 합니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블로그 플랫폼을 고를 때 &amp;ldquo;예쁜가&amp;rdquo;, &amp;ldquo;무료인가&amp;rdquo;만 보면 나중에 옮기기 어렵습니다. 특히 애드센스 승인과 장기 운영을 생각한다면 아래 기준이 중요합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;수익화 가능성:&lt;/b&gt; AdSense, 자체 광고, 제휴 링크, 유료 콘텐츠를 넣을 수 있는지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;소유권과 이전 가능성:&lt;/b&gt; 내 도메인, 백업, 글 내보내기, 플랫폼 이전이 가능한지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;검색 노출:&lt;/b&gt; 구글&amp;middot;네이버&amp;middot;다음 검색에 등록하고 관리하기 쉬운지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;디자인 자유도:&lt;/b&gt; 스킨, HTML, CSS, 광고 위치, 모바일 화면을 수정할 수 있는지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;운영 난도:&lt;/b&gt; 서버, 보안, 업데이트, 플러그인을 직접 관리해야 하는지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;콘텐츠 유형:&lt;/b&gt; 일상글, 정보글, 개발글, 기업 홈페이지, 포트폴리오 중 무엇에 맞는지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정책 리스크:&lt;/b&gt; 플랫폼 기능이 중단되거나 약관이 바뀌어도 대응할 수 있는지&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5대 블로그 플랫폼 핵심 비교표&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;항목&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;티스토리&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;블로그스팟&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;워드프레스&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;GitHub Pages&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Velog&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;추천 대상&lt;/td&gt;
&lt;td&gt;한국어 수익형 블로그&lt;/td&gt;
&lt;td&gt;무료 구글 블로그&lt;/td&gt;
&lt;td&gt;장기 자산형 사이트&lt;/td&gt;
&lt;td&gt;개발자 문서&amp;middot;포트폴리오&lt;/td&gt;
&lt;td&gt;개발자 글쓰기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;초기 비용&lt;/td&gt;
&lt;td&gt;무료&lt;/td&gt;
&lt;td&gt;무료&lt;/td&gt;
&lt;td&gt;무료 시작 가능, 제대로 운영하면 유료 가능성 큼&lt;/td&gt;
&lt;td&gt;무료 시작 가능&lt;/td&gt;
&lt;td&gt;무료&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;애드센스&lt;/td&gt;
&lt;td&gt;운영자 직접 신청&amp;middot;설정 가능&lt;/td&gt;
&lt;td&gt;Blogger 수익 메뉴에서 AdSense 안내 제공&lt;/td&gt;
&lt;td&gt;직접 설치형 또는 유료 플랜에서 유리&lt;/td&gt;
&lt;td&gt;가능은 하지만 정적 사이트라 직접 코드 삽입 필요&lt;/td&gt;
&lt;td&gt;수익형 블로그 용도에는 부적합&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;디자인 자유도&lt;/td&gt;
&lt;td&gt;스킨&amp;middot;HTML&amp;middot;CSS 수정 가능&lt;/td&gt;
&lt;td&gt;템플릿 수정 가능하지만 세련된 선택지는 제한적&lt;/td&gt;
&lt;td&gt;가장 높음&lt;/td&gt;
&lt;td&gt;직접 만들면 자유도 높음&lt;/td&gt;
&lt;td&gt;낮음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;운영 난도&lt;/td&gt;
&lt;td&gt;낮음~중간&lt;/td&gt;
&lt;td&gt;낮음&lt;/td&gt;
&lt;td&gt;중간~높음&lt;/td&gt;
&lt;td&gt;개발자에게 낮음, 비개발자에게 높음&lt;/td&gt;
&lt;td&gt;낮음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;검색&amp;middot;SEO&lt;/td&gt;
&lt;td&gt;한국어 정보글 운영에 무난&lt;/td&gt;
&lt;td&gt;구글 생태계와 연결 쉬움&lt;/td&gt;
&lt;td&gt;플러그인과 구조화 데이터 활용 가능&lt;/td&gt;
&lt;td&gt;직접 세팅해야 함&lt;/td&gt;
&lt;td&gt;플랫폼 내 노출은 좋지만 검색 최적화 자유도는 낮음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;장기 리스크&lt;/td&gt;
&lt;td&gt;플랫폼 정책 변경&lt;/td&gt;
&lt;td&gt;디자인&amp;middot;국내 자료 부족&lt;/td&gt;
&lt;td&gt;비용&amp;middot;보안&amp;middot;유지보수&lt;/td&gt;
&lt;td&gt;CMS 부재&amp;middot;비개발자 진입장벽&lt;/td&gt;
&lt;td&gt;수익화와 소유권 한계&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 티스토리: 한국어 애드센스 블로그의 현실적인 출발점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;티스토리는 한국어 수익형 블로그를 시작하려는 사람에게 여전히 가장 현실적인 선택지입니다. 무료로 시작할 수 있고, 스킨 편집을 통해 HTML과 CSS를 수정할 수 있으며, 광고 배치도 비교적 자유롭습니다. 네이버 블로그보다 애드센스 관점에서 유리하고, 워드프레스보다 시작 장벽이 낮습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 티스토리는 &amp;ldquo;내 서버&amp;rdquo;가 아니라 플랫폼입니다. 정책 변경, 기능 종료, 수익 메뉴 변화에 영향을 받을 수 있습니다. 실제로 티스토리 공지에서는 2026년 6월 29일부터 카카오 애드핏 신규 연동 신청이 종료되지만 Google AdSense, Dable, Tenping 등 다른 광고 플랫폼 연동은 기존과 동일하게 이용 가능하다고 안내했습니다. 또 2026년 공지에서 동영상 직접 업로드 기능을 점진적으로 정리하고 유튜브 등 외부 영상 플랫폼 활용을 안내했습니다. 이런 변화는 무료 플랫폼을 쓸 때 반드시 고려해야 하는 운영 리스크입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;티스토리가 잘 맞는 사람&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한국어 정보성 글로 애드센스를 통과하고 싶은 사람&lt;/li&gt;
&lt;li&gt;서버 관리 없이 스킨과 광고 위치만 어느 정도 수정하고 싶은 사람&lt;/li&gt;
&lt;li&gt;블로그 운영 자료를 한국어로 많이 찾고 싶은 사람&lt;/li&gt;
&lt;li&gt;처음에는 무료로 시작하고, 나중에 도메인이나 워드프레스로 확장할 생각이 있는 사람&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;티스토리 주의점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;티스토리는 글 자체의 품질이 낮으면 애드센스 승인에 불리합니다. 플랫폼보다 중요한 것은 독창적인 글, 명확한 카테고리, 개인정보처리방침, 소개 페이지, 충분한 본문 길이, 출처 표시입니다. 특히 자동 생성 글을 대량으로 올리는 방식은 장기적으로 검색과 광고 승인 모두에 좋지 않습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 블로그스팟(Blogger): 무료와 구글 생태계가 장점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블로그스팟은 Google의 Blogger 서비스입니다. Google Blogger 도움말은 Blogger에서 블로그를 만들고 관리할 수 있다고 안내하며, Google 계정으로 로그인한 뒤 새 블로그를 만들고 이름과 주소를 정하면 시작할 수 있습니다. 서버나 설치 과정이 없어서 진입장벽이 낮습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수익화 면에서도 장점이 있습니다. Google AdSense 도움말은 Blogger에서 AdSense와 기타 광고를 표시할 수 있고, AdSense 정책과 제한을 준수해야 한다고 안내합니다. Blogger의 수익 메뉴에서 AdSense 계정을 만들고, 레이아웃에서 글 사이 광고나 사이드바 광고를 설정하는 흐름도 제공됩니다. 또한 수익화 블로그라면 ads.txt 설정도 공식 도움말에 안내되어 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;블로그스팟이 잘 맞는 사람&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;무료로 구글 계정 기반 블로그를 만들고 싶은 사람&lt;/li&gt;
&lt;li&gt;국내 플랫폼 정책보다 Google 생태계 안에서 운영하고 싶은 사람&lt;/li&gt;
&lt;li&gt;간단한 애드센스 테스트용 블로그를 만들고 싶은 사람&lt;/li&gt;
&lt;li&gt;디자인보다 유지비 0원과 단순한 운영을 더 중요하게 보는 사람&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;블로그스팟 주의점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;국내 사용자에게는 자료와 커뮤니티가 티스토리보다 적습니다. 디자인도 최신 블로그 빌더에 비하면 투박하게 느껴질 수 있습니다. 한국어 정보글로 빠르게 성장시키려면 글 품질뿐 아니라 검색 등록, 템플릿 정리, 모바일 가독성 개선을 직접 챙겨야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 워드프레스: 가장 강력하지만 관리가 필요한 선택지&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;워드프레스는 크게 WordPress.com과 WordPress.org로 나눠 봐야 합니다. WordPress.com은 가입형 서비스이고, WordPress.org는 직접 호스팅에 설치해 운영하는 오픈소스 워드프레스입니다. 초보자는 WordPress.com이 쉽지만, 자유도와 수익화 확장성은 직접 설치형 워드프레스가 더 큽니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WordPress.com 가격 페이지 기준으로 무료 플랜부터 Personal, Premium, Business, Commerce 플랜이 있으며, 무료 플랜은 1GB 저장 공간, Personal은 6GB, Premium은 13GB, Business 이상은 더 큰 저장 공간과 플러그인&amp;middot;개발자 기능이 제공됩니다. Business 플랜에는 SFTP/SSH, WP-CLI, Git 명령, GitHub Deployments 같은 개발자 기능도 안내됩니다. 다만 실제 가격과 프로모션은 국가와 결제 주기에 따라 달라질 수 있으므로 결제 전 공식 가격표를 다시 확인해야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;워드프레스가 잘 맞는 사람&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;블로그를 장기 자산으로 키우고 싶은 사람&lt;/li&gt;
&lt;li&gt;도메인, 백업, 플러그인, SEO, 구조화 데이터를 직접 관리하고 싶은 사람&lt;/li&gt;
&lt;li&gt;블로그에서 쇼핑몰, 뉴스레터, 회원제 콘텐츠까지 확장할 계획이 있는 사람&lt;/li&gt;
&lt;li&gt;초기 비용보다 소유권과 확장성을 더 중요하게 생각하는 사람&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;워드프레스 주의점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;워드프레스는 &amp;ldquo;시작은 쉬운데 잘 운영하려면 공부가 필요한 플랫폼&amp;rdquo;입니다. 플러그인 충돌, 보안 업데이트, 백업, 속도 최적화, 호스팅 비용을 관리해야 합니다. 애드센스만 목표라면 티스토리보다 시작 부담이 큽니다. 하지만 브랜드 사이트나 장기 SEO 자산을 만들 생각이라면 가장 강력한 선택지입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. GitHub Pages: 개발자에게 좋은 정적 사이트 호스팅&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GitHub Pages는 블로그 플랫폼이라기보다 정적 사이트 호스팅 서비스입니다. GitHub 공식 문서는 GitHub Pages가 저장소의 HTML, CSS, JavaScript 파일을 가져와 빌드 과정을 거쳐 웹사이트로 게시하는 정적 사이트 호스팅 서비스라고 설명합니다. 개인&amp;middot;조직 사이트와 프로젝트 사이트를 만들 수 있고, github.io 도메인 또는 커스텀 도메인을 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자에게는 장점이 많습니다. Markdown으로 글을 쓰고, Git으로 변경 이력을 관리하고, Jekyll&amp;middot;Hugo&amp;middot;Astro 같은 정적 사이트 생성기와 연결할 수 있습니다. 비용도 낮고 속도도 빠릅니다. 하지만 댓글, 검색, 관리자 화면, 이미지 업로드, 예약 발행, 광고 배치 같은 일반 블로그 기능은 직접 붙여야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;GitHub Pages가 잘 맞는 사람&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개발 포트폴리오나 기술 문서를 깔끔하게 운영하고 싶은 사람&lt;/li&gt;
&lt;li&gt;Git, Markdown, 정적 사이트 생성기에 익숙한 사람&lt;/li&gt;
&lt;li&gt;서버 비용 없이 빠른 정적 사이트를 만들고 싶은 사람&lt;/li&gt;
&lt;li&gt;광고 수익보다 이력 관리와 기술 브랜딩이 중요한 사람&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;GitHub Pages 주의점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비개발자에게는 진입장벽이 높습니다. 글 하나를 수정할 때도 Git과 빌드 흐름을 이해해야 할 수 있습니다. AdSense 코드를 넣을 수는 있지만, 광고 승인만 목표라면 티스토리나 워드프레스가 더 편합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. Velog: 개발자 글쓰기와 커뮤니티 노출에 강함&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Velog는 개발자들이 기술 글을 쓰고 공유하기 좋은 플랫폼입니다. 공개 메인 화면에는 트렌딩, 추천, 최신, 피드 같은 탐색 메뉴가 있고, 개발자 글이 플랫폼 안에서 노출되기 쉽습니다. Markdown으로 글을 쓰는 개발자에게는 부담이 적습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 수익형 블로그 관점에서는 한계가 뚜렷합니다. 광고 코드 삽입, 스킨 수정, 애드센스 승인, 커스텀 레이아웃, 백업과 이전까지 고려하면 티스토리나 워드프레스보다 불리합니다. 따라서 Velog는 &amp;ldquo;돈 버는 블로그&amp;rdquo;보다는 &amp;ldquo;개발자로서 배운 것을 기록하고 커뮤니티에 노출하는 공간&amp;rdquo;으로 보는 편이 맞습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;애드센스 통과를 목표로 한다면 무엇을 고를까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애드센스 통과만 놓고 보면 플랫폼보다 콘텐츠 품질이 더 중요합니다. 그래도 플랫폼별로 유리한 방향은 있습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;상황&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;추천&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;이유&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;한국어 정보글로 빠르게 승인 도전&lt;/td&gt;
&lt;td&gt;티스토리&lt;/td&gt;
&lt;td&gt;설정 자료가 많고 애드센스 운영 사례가 많습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;구글 계정 기반 무료 블로그 선호&lt;/td&gt;
&lt;td&gt;블로그스팟&lt;/td&gt;
&lt;td&gt;Blogger와 AdSense 연결 흐름이 공식 도움말로 제공됩니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;브랜드 사이트와 블로그를 함께 키움&lt;/td&gt;
&lt;td&gt;워드프레스&lt;/td&gt;
&lt;td&gt;SEO, 도메인, 플러그인, 확장성이 가장 좋습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;개발자 포트폴리오 중심&lt;/td&gt;
&lt;td&gt;GitHub Pages 또는 Velog&lt;/td&gt;
&lt;td&gt;광고 수익보다 기술 브랜딩에 적합합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;플랫폼보다 중요한 애드센스 승인 체크리스트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 플랫폼을 선택하든 아래 조건을 갖추지 않으면 애드센스 승인은 어렵습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;카테고리를 좁힙니다.&lt;/b&gt; 처음부터 IT, 건강, 여행, 재테크를 모두 쓰기보다 한 주제를 깊게 다루는 것이 좋습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;각 글에 실제 경험과 판단 기준을 넣습니다.&lt;/b&gt; 단순 기능 나열보다 &amp;ldquo;왜 이 선택이 나은지&amp;rdquo;를 설명해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;출처를 남깁니다.&lt;/b&gt; 가격, 정책, 기능, 제한은 공식 문서 링크를 붙입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;필수 페이지를 만듭니다.&lt;/b&gt; 소개, 문의, 개인정보처리방침은 신뢰도를 높입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;빈 카테고리를 없앱니다.&lt;/b&gt; 빈 메뉴와 미완성 페이지는 품질이 낮아 보입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이미지를 합법적으로 사용합니다.&lt;/b&gt; 직접 촬영, 공식 이미지, Unsplash 등 사용 가능한 이미지를 쓰고 출처를 남깁니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;AI 글은 반드시 편집합니다.&lt;/b&gt; 중복 문장, 과장된 표현, 틀린 가격 정보, 오래된 정책은 승인과 검색 노출에 모두 불리합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;최종 정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 블로그를 시작하는 목적이 &amp;ldquo;애드센스 수익&amp;rdquo;이라면 티스토리가 가장 무난합니다. 무료이고, 한국어 자료가 많고, 스킨과 광고 배치를 어느 정도 수정할 수 있습니다. 다만 플랫폼 정책 변경이 있으므로 중요한 글은 백업해 두는 습관이 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장기적으로 블로그를 내 자산으로 키우고 싶다면 워드프레스가 가장 강합니다. 비용과 관리 부담이 있지만, 도메인&amp;middot;플러그인&amp;middot;백업&amp;middot;SEO 측면에서 자유도가 높습니다. 블로그스팟은 무료와 구글 생태계가 장점이지만 국내 자료와 디자인 면에서 아쉬움이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GitHub Pages와 Velog는 수익형 블로그보다 개발자 브랜딩에 더 어울립니다. GitHub Pages는 직접 사이트를 관리할 수 있는 개발자에게, Velog는 빠르게 기술 글을 쓰고 개발자 독자에게 노출되고 싶은 사람에게 맞습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 좋은 플랫폼은 &amp;ldquo;내가 오래 쓸 수 있는 플랫폼&amp;rdquo;입니다. 처음부터 완벽한 선택을 하려고 하기보다, 목적을 하나로 정하세요. 수익이면 티스토리나 워드프레스, 무료 실험이면 블로그스팟, 개발자 브랜딩이면 GitHub Pages나 Velog가 가장 합리적인 출발점입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고한 공식 자료&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://support.google.com/blogger/answer/1623800?hl=en&quot;&gt;Google Blogger Help - Create a blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://support.google.com/adsense/answer/1269077?hl=en&quot;&gt;Google AdSense Help - Advertise on your blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wordpress.com/pricing/&quot;&gt;WordPress.com Plans &amp;amp; Pricing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.github.com/en/pages/getting-started-with-github-pages/what-is-github-pages&quot;&gt;GitHub Docs - What is GitHub Pages?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://notice.tistory.com/2701&quot;&gt;티스토리 공지 - 카카오 애드핏 신규 연동 신청 종료 안내&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://notice.tistory.com/2696&quot;&gt;티스토리 공지 - 동영상 업로드 기능 조정 예정&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://velog.io/&quot;&gt;Velog 공식 페이지&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://unsplash.com/s/photos/laptop-writing&quot;&gt;대표 이미지: Nick Morrison on Unsplash&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;이 글은 2026년 6월 10일 공개 자료 기준으로 작성했습니다. 각 플랫폼의 가격, 저장 공간, 광고 정책, 플러그인 제한, 수익화 조건은 변경될 수 있으므로 실제 가입과 결제 전 공식 페이지에서 다시 확인하세요.&lt;/p&gt;</description>
      <category>AI</category>
      <category>블로그플랫폼 #티스토리 #워드프레스 #블로그스팟 #수익형블로그 #개발자블로그 #기술블로그 #초보자블로그 #SEO #블로그비교 #콘텐츠제작 #구글애드센스</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/60</guid>
      <comments>https://onethingflow.tistory.com/entry/%EB%B8%94%EB%A1%9C%EA%B7%B8-%ED%94%8C%EB%9E%AB%ED%8F%BC-%EA%B8%B0%EB%8A%A5-%EB%B9%84%EA%B5%90-%EC%B4%9D-%EC%A0%95%EB%A6%AC-%EB%B8%94%EB%A1%9C%EA%B7%B8%EC%8A%A4%ED%8C%9F-%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC-%EC%9B%8C%EB%93%9C%ED%94%84%EB%A0%88%EC%8A%A4-githubio-%EB%B2%A8%EB%A1%9C%EA%B7%B8-%EB%93%B1#entry60comment</comments>
      <pubDate>Wed, 10 Jun 2026 10:38:19 +0900</pubDate>
    </item>
    <item>
      <title>AI PPT 제작 도구 비교 2026: Skywork, Genspark, Gamma 중 무엇을 써야 할까</title>
      <link>https://onethingflow.tistory.com/entry/AI-PPT-%EC%A0%9C%EC%9E%91-%EB%8F%84%EA%B5%AC-3%EB%8C%80%EC%9E%A5-%EC%99%84%EC%A0%84-%EB%B9%84%EA%B5%90-Skywork-vs-Genspark-vs-Gamma</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;2400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/doagMg/dJMcaf1asVy/7a1lqmbiMzUkN7cIkm20Kk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/doagMg/dJMcaf1asVy/7a1lqmbiMzUkN7cIkm20Kk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/doagMg/dJMcaf1asVy/7a1lqmbiMzUkN7cIkm20Kk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdoagMg%2FdJMcaf1asVy%2F7a1lqmbiMzUkN7cIkm20Kk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1600&quot; height=&quot;2400&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;2400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;AI PPT 도구는 초안 작성 시간을 줄여주지만, 최종 발표 품질은 자료 검증과 편집 과정에서 갈립니다. 이미지: Slidebean, Unsplash.&lt;/p&gt;
&lt;div&gt;
&lt;h1&gt;AI PPT 제작 도구 비교 2026: Skywork, Genspark, Gamma 중 무엇을 써야 할까&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI PPT 도구를 고를 때 가장 많이 하는 실수는 &amp;ldquo;예쁜 슬라이드를 빨리 만들어 주는가&amp;rdquo;만 보는 것입니다. 실제 업무에서는 발표 목적, 자료의 신뢰도, PPTX 내보내기, 팀 편집, 한국어 결과물까지 함께 봐야 실패 확률이 낮아집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 2026년 6월 10일 기준으로 Skywork, Genspark, Gamma의 공식 페이지와 공개 기능을 확인해 다시 정리한 비교 글입니다. 가격과 크레딧은 서비스 정책, 국가, 프로모션에 따라 수시로 바뀔 수 있어 숫자를 단정하기보다 &amp;ldquo;어떤 상황에서 어떤 도구가 유리한지&amp;rdquo;를 중심으로 판단했습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;2026년 6월 기준&lt;/span&gt; &lt;span&gt;공식 자료 확인&lt;/span&gt; &lt;span&gt;PPTX 내보내기 기준 반영&lt;/span&gt; &lt;span&gt;업무&amp;middot;학습&amp;middot;마케팅별 추천&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;리서치와 검증&lt;/span&gt; &lt;b&gt;Genspark, Skywork 우세&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;디자인 완성도&lt;/span&gt; &lt;b&gt;Gamma 우세&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;실무 PPTX 편집&lt;/span&gt; &lt;b&gt;Genspark 확인 필요, Gamma 안정적&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;한 줄 결론: 보고서나 시장조사 자료를 PPT로 바꿀 때는 Genspark, 디자인이 중요한 제안서와 강의자료는 Gamma, 문서&amp;middot;슬라이드&amp;middot;시트까지 한 번에 묶어 작업하고 싶다면 Skywork부터 확인하는 것이 가장 현실적입니다.&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;먼저 결론: 상황별 추천&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 도구는 모두 &amp;ldquo;AI로 발표자료를 만든다&amp;rdquo;는 점에서는 비슷하지만, 실제 강점은 다릅니다. 같은 프롬프트를 넣어도 어떤 도구는 리서치가 강하고, 어떤 도구는 디자인과 공유가 강하며, 어떤 도구는 여러 산출물을 한 워크스페이스에서 처리하는 데 초점이 있습니다.&lt;/p&gt;
&lt;div&gt;AI PPT 제작 도구 상황별 추천 요약사용 상황 1순위 대안 이유
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;시장조사, 보고서, 경쟁사 분석을 PPT로 바꾸기&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Genspark&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Skywork&lt;/td&gt;
&lt;td&gt;Genspark는 공식 AI Presentation Maker에서 문서 업로드, 실시간 웹 기반 리서치, 아웃라인 승인, 출처 기반 생성, 팩트체크 기능을 강조합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;제안서, 포트폴리오, 강의자료처럼 보기 좋은 발표자료 만들기&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Gamma&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Genspark&lt;/td&gt;
&lt;td&gt;Gamma는 프레젠테이션, 문서, 웹페이지를 카드 기반으로 빠르게 만들고 PDF, PPTX, PNG, Google Slides 내보내기를 지원합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;문서, 슬라이드, 시트, 이미지까지 한 공간에서 만들기&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Skywork&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Genspark&lt;/td&gt;
&lt;td&gt;Skywork는 공식 홈페이지에서 General, Images, Documents, Slides, Sheets, AI Developer, Podcasts, Videos 등 여러 작업 영역을 제공합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;회사 발표에서 PowerPoint로 다시 편집해야 하는 경우&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Genspark 또는 Gamma&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Skywork&lt;/td&gt;
&lt;td&gt;Genspark는 &amp;ldquo;real .pptx&amp;rdquo; 내보내기를 전면에 내세우고, Gamma도 가격표와 제품 페이지에서 PPTX&amp;middot;Google Slides 내보내기를 안내합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;처음 AI PPT 도구를 쓰는 사람&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Gamma&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Genspark&lt;/td&gt;
&lt;td&gt;Gamma는 UI가 단순하고 결과물의 첫인상이 좋습니다. 단, 통계&amp;middot;출처가 중요한 발표라면 사용자가 직접 검증해야 합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;비교 기준: 예쁜 슬라이드보다 중요한 것&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI PPT 글을 보면 별점만 크게 붙인 표가 많습니다. 하지만 실제로는 &amp;ldquo;누가 발표하느냐&amp;rdquo;와 &amp;ldquo;발표 후 어떤 파일을 넘겨야 하느냐&amp;rdquo;가 더 중요합니다. 그래서 이 글에서는 아래 기준을 중심으로 비교했습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;입력 방식&lt;/b&gt;: 프롬프트만 받는지, PDF&amp;middot;Word&amp;middot;Excel&amp;middot;기존 PPT를 넣을 수 있는지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;리서치 품질&lt;/b&gt;: 웹 자료를 참고하는지, 출처나 팩트체크 흐름이 있는지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;아웃라인 제어&lt;/b&gt;: 슬라이드를 만들기 전에 목차를 검토할 수 있는지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;디자인 완성도&lt;/b&gt;: 초안이 바로 공유 가능한 수준인지, 브랜드 톤을 맞출 수 있는지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;내보내기&lt;/b&gt;: PPTX, PDF, Google Slides 등 실무 파일로 넘길 수 있는지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;한국어 결과물&lt;/b&gt;: 한국어 제목, 문장 길이, 줄바꿈이 자연스러운지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;요금 안정성&lt;/b&gt;: 무료 사용량, 유료 전환 조건, 크레딧 소모 방식이 예측 가능한지&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;중요:&lt;/b&gt; AI PPT 도구가 만든 통계, 가격, 시장 규모, 법률&amp;middot;의학&amp;middot;금융 정보는 그대로 발표에 쓰면 안 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성형 AI는 그럴듯한 문장을 만들 수 있지만, 발표에서 책임지는 사람은 도구가 아니라 사용자입니다. 투자 발표, 회사 보고, 논문 발표는 반드시 원문 자료를 다시 확인해야 합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3대 도구 한눈에 비교&lt;/h2&gt;
&lt;div&gt;Skywork Genspark Gamma 기능 비교표항목 Skywork Genspark Gamma
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;가장 잘 맞는 일&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;문서, 슬라이드, 시트 등 여러 산출물을 묶어 만드는 작업&lt;/td&gt;
&lt;td&gt;리서치 기반 보고서, 문서/PDF를 PPT로 바꾸는 작업&lt;/td&gt;
&lt;td&gt;디자인이 좋은 발표자료, 웹 공유용 자료, 마케팅 제안서&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;공식 제품 방향&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;AI Workspace Agents. Slides, Documents, Sheets, Images, Podcasts 등 다기능 워크스페이스&lt;/td&gt;
&lt;td&gt;AI Workspace 4.0. AI Presentation Maker, AI PowerPoint Generator, PDF/Word/Text to PPT 도구 제공&lt;/td&gt;
&lt;td&gt;프레젠테이션, 문서, 웹사이트, 소셜 콘텐츠를 카드 기반으로 생성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;자료 입력&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;앱 내 작업 유형별 입력. 공개 페이지에서는 세부 제한이 제한적으로 노출됨&lt;/td&gt;
&lt;td&gt;주제 입력, PDF, Word, Excel, 기존 PPT, 링크 등을 활용한다고 안내&lt;/td&gt;
&lt;td&gt;프롬프트, PDF, PPTX 가져오기 지원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;아웃라인 검토&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;작업 유형에 따라 확인 필요&lt;/td&gt;
&lt;td&gt;&lt;span&gt;강점&lt;/span&gt;. 먼저 아웃라인을 만들고 승인 후 슬라이드를 생성하는 흐름을 강조&lt;/td&gt;
&lt;td&gt;카드 수와 구조를 조정하면서 빠르게 생성하는 방식&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;리서치와 검증&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;리서치형 워크스페이스 성격이 강함. 세부 출처 표시는 작업별 확인 필요&lt;/td&gt;
&lt;td&gt;&lt;span&gt;강점&lt;/span&gt;. 실시간 웹 데이터, 소스 기반 생성, Fact Check 기능을 공식 페이지에서 안내&lt;/td&gt;
&lt;td&gt;디자인과 생성 속도는 강하지만, 통계와 출처는 사용자가 별도 검증하는 것이 안전&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;디자인 완성도&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;작업 유형별 편차가 있을 수 있음&lt;/td&gt;
&lt;td&gt;보고서형, 비즈니스형 덱에 적합&lt;/td&gt;
&lt;td&gt;&lt;span&gt;강점&lt;/span&gt;. 스마트 레이아웃, 테마, 카드 기반 편집이 장점&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;내보내기&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;현재 공개 페이지 기준 세부 포맷은 앱 안에서 확인 필요&lt;/td&gt;
&lt;td&gt;PPTX, PDF, Google Slides 내보내기를 안내. AI PowerPoint Generator는 실제 PPTX 파일을 강조&lt;/td&gt;
&lt;td&gt;PDF, PPTX, PNG, Google Slides 내보내기 지원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;한국어&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;공식 슬라이드 페이지에서 Korean 언어 옵션 노출&lt;/td&gt;
&lt;td&gt;공식 FAQ에서 한국어를 포함한 19개 언어 생성을 안내&lt;/td&gt;
&lt;td&gt;한국어 입력과 출력이 가능하나, 긴 문장은 줄바꿈을 직접 다듬는 편이 좋음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;주의할 점&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;공개 정보가 비교적 적고, JS 앱 기반이라 로그인 후 실제 제한을 확인해야 함&lt;/td&gt;
&lt;td&gt;기능이 많아 초보자는 흐름이 복잡하게 느껴질 수 있음. 크레딧 소모도 확인 필요&lt;/td&gt;
&lt;td&gt;근거 자료가 중요한 발표에서는 리서치 도구를 별도로 붙이는 것이 안전&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Skywork: 여러 산출물을 한 번에 만드는 워크스페이스형 도구&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Skywork는 &amp;ldquo;PPT만 만드는 앱&amp;rdquo;이라기보다 여러 종류의 콘텐츠를 만드는 AI 워크스페이스에 가깝습니다. 공식 홈페이지에는 General, Images, Documents, Slides, Sheets, AI Developer, Podcasts, YouVibe, Videos 같은 작업 영역이 보입니다. 즉 슬라이드 하나만 만들기보다 리서치, 문서, 표, 이미지, 영상 등 여러 산출물을 연결해 만드는 방향에 가깝습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 구조는 자료 조사와 콘텐츠 패키징을 함께 해야 하는 사람에게 유리합니다. 예를 들어 &amp;ldquo;시장조사 보고서, 발표자료, 요약표, 발표 스크립트&amp;rdquo;를 한 프로젝트에서 이어서 만들고 싶다면 Skywork의 방향성이 잘 맞습니다. 반대로 단순히 예쁜 PPTX 파일 하나만 빨리 받아야 한다면 Gamma나 Genspark가 더 직관적일 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Skywork가 잘 맞는 사용자&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문서, 슬라이드, 시트, 이미지 등 여러 결과물을 한 번에 만드는 사람&lt;/li&gt;
&lt;li&gt;발표자료뿐 아니라 보고서, 요약문, 콘텐츠 기획안까지 함께 필요한 사람&lt;/li&gt;
&lt;li&gt;AI 워크스페이스형 도구를 테스트하면서 장기적으로 업무 흐름을 바꾸고 싶은 사람&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Skywork 사용 시 주의할 점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Skywork의 공개 페이지는 일부 정보가 JS 앱 안에서만 보이기 때문에, 가격과 내보내기 제한은 실제 계정으로 로그인한 뒤 다시 확인해야 합니다. 특히 회사에서 사용할 경우에는 결과물의 저작권, 데이터 저장 위치, 보안 정책, 팀 계정 기능을 먼저 확인하는 것이 좋습니다.&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;추천 프롬프트 예시:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;2026년 한국 중소기업의 AI 도입 현황을 발표할 12장짜리 슬라이드 초안을 만들어줘. 대상은 비개발자 임원진이고, 각 슬라이드마다 핵심 메시지 1개, 근거 자료, 발표자 노트를 포함해줘. 마지막에는 도입 우선순위 표를 넣어줘.&amp;rdquo;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Genspark: 리서치와 실무형 PPTX에 강한 올인원 도구&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Genspark는 AI Presentation Maker와 AI PowerPoint Generator를 별도로 내세웁니다. 공식 AI Presentation Maker 페이지에는 &amp;ldquo;주제를 설명하거나 노트를 업로드하면 리서치, 작성, 슬라이드 디자인을 처리한다&amp;rdquo;는 흐름이 소개되어 있습니다. 또 Guide mode에서 청중, 톤, 슬라이드 수를 물어보고, 먼저 아웃라인을 만든 뒤 사용자가 승인하면 슬라이드를 생성한다고 안내합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 점이 실무에서 중요합니다. AI가 바로 20장의 슬라이드를 만들어 버리면, 틀린 방향으로 생성됐을 때 수정 비용이 커집니다. 반대로 아웃라인을 먼저 확인하면 발표 구조를 잡고, 슬라이드 수를 줄이고, 빠진 논거를 보완한 뒤 제작할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Genspark의 강점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;문서 기반 제작:&lt;/b&gt; PDF, Word, Excel, 기존 PowerPoint를 업로드해 발표자료로 바꾸는 흐름이 강합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;아웃라인 우선:&lt;/b&gt; 바로 슬라이드를 만들기보다 구조를 먼저 확인할 수 있어 보고서형 PPT에 유리합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;실제 PPTX 내보내기:&lt;/b&gt; AI PowerPoint Generator 페이지에서 &amp;ldquo;real .pptx&amp;rdquo; 파일을 강조합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;팩트체크 기능:&lt;/b&gt; 공식 FAQ에서 슬라이드의 데이터와 통계를 출처와 대조해 확인하는 Fact Check 기능을 안내합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;한국어 포함 다국어:&lt;/b&gt; 공식 FAQ 기준 19개 언어 생성에 한국어가 포함됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Genspark 사용 시 주의할 점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기능이 많은 만큼 처음에는 복잡하게 느껴질 수 있습니다. 단순한 5장짜리 발표자료를 만들 때는 Gamma가 더 빠를 수 있습니다. 반대로 기존 보고서, PDF, 통계표, 기사 링크를 넣고 &amp;ldquo;발표 가능한 자료&amp;rdquo;로 바꾸려면 Genspark가 유리합니다.&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;추천 프롬프트 예시:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;첨부한 PDF 보고서를 바탕으로 10장짜리 임원 보고용 PPT를 만들어줘. 첫 장은 결론 요약, 2~4장은 핵심 지표, 5~7장은 원인 분석, 8~9장은 실행 전략, 마지막 장은 의사결정 요청으로 구성해줘. 모든 숫자는 원문 페이지나 출처를 함께 표시해줘.&amp;rdquo;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Gamma: 빠르고 보기 좋은 발표자료에 강한 디자인형 도구&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Gamma는 세 도구 중 가장 &amp;ldquo;처음 써도 결과물이 보기 좋은&amp;rdquo; 쪽에 가깝습니다. 공식 프레젠테이션 페이지에서는 텍스트를 몇 분 만에 발표자료로 바꾸고, 스마트 템플릿과 블록으로 전문적인 결과물을 만들 수 있다고 설명합니다. 또한 발표 모드, 링크 공유, PDF&amp;middot;PowerPoint&amp;middot;Google Slides 내보내기를 지원한다고 안내합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Gamma 가격 페이지 기준으로 무료 플랜은 프롬프트당 최대 10개 카드 생성, PDF와 PPTX 가져오기, PDF&amp;middot;PPTX&amp;middot;PNG&amp;middot;Google Slides 내보내기를 포함합니다. Plus는 프롬프트당 최대 20개 카드와 Gamma 브랜딩 제거, Pro는 최대 60개 카드와 커스텀 브랜딩&amp;middot;폰트&amp;middot;분석&amp;middot;API 접근, Ultra는 최대 75개 카드와 더 많은 AI 사용량, 고급 모델 접근을 안내합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Gamma의 강점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;디자인 초안이 빠름:&lt;/b&gt; 제안서, 강의자료, 포트폴리오처럼 첫인상이 중요한 자료에 강합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;공유가 쉬움:&lt;/b&gt; 링크 공유, 발표 모드, 웹페이지형 콘텐츠 제작에 적합합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;내보내기 옵션:&lt;/b&gt; PDF, PPTX, PNG, Google Slides 등 다양한 포맷을 지원합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;브랜드 작업:&lt;/b&gt; 유료 플랜에서는 커스텀 브랜딩과 폰트를 사용할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Gamma 사용 시 주의할 점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Gamma는 예쁜 결과물을 빠르게 만드는 데 강하지만, 깊은 리서치와 출처 검증은 사용자가 직접 보강해야 합니다. 특히 &amp;ldquo;국내 시장 규모&amp;rdquo;, &amp;ldquo;최신 가격&amp;rdquo;, &amp;ldquo;규제 변화&amp;rdquo;, &amp;ldquo;통계 수치&amp;rdquo;가 들어가는 발표라면 Gamma로 만든 초안을 그대로 쓰지 말고 원문 링크를 확인해 숫자를 다시 검증하세요.&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;추천 프롬프트 예시:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;20분짜리 마케팅 제안 발표자료를 만들어줘. 대상은 B2B SaaS 대표와 마케팅 팀장이고, 톤은 전문적이지만 너무 딱딱하지 않게 해줘. 문제 정의, 시장 변화, 제안 전략, 실행 로드맵, 기대 성과, 다음 액션 순서로 구성해줘.&amp;rdquo;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실전 선택 가이드: 이렇게 고르면 실패가 줄어듭니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도구 선택은 &amp;ldquo;어느 제품이 제일 좋은가&amp;rdquo;보다 &amp;ldquo;내가 지금 만드는 발표자료가 무엇인가&amp;rdquo;로 결정하는 것이 정확합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 데이터와 근거가 중요한 발표&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;투자 발표, 경영진 보고, 논문 발표, 시장조사 발표라면 Genspark나 Skywork처럼 리서치 흐름이 강한 도구를 먼저 쓰는 것이 좋습니다. 단, AI가 붙인 출처가 실제 문장과 맞는지는 반드시 확인해야 합니다. 발표자료에서 숫자 하나가 틀리면 디자인이 아무리 좋아도 신뢰도가 떨어집니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 빠른 제안서와 내부 공유용 발표&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내일 회의에 쓸 제안서, 팀 내부 공유 자료, 강의 개요처럼 &amp;ldquo;깔끔한 초안&amp;rdquo;이 필요한 경우에는 Gamma가 편합니다. Gamma는 텍스트를 넣고 결과물을 만드는 속도가 빠르고, 링크 공유도 편리합니다. 이후 PowerPoint나 Google Slides로 내보내 세부 문구를 다듬으면 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 기존 문서를 PPT로 바꾸는 작업&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PDF 보고서, Word 문서, 회의록, 엑셀 표를 발표자료로 바꿔야 한다면 Genspark 쪽이 더 실무적입니다. 기존 문서에서 핵심 메시지를 뽑고, 아웃라인을 승인한 뒤, 실제 PPTX로 내보내는 흐름이 명확합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 콘텐츠를 여러 형태로 재활용하는 작업&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블로그 글을 슬라이드로 바꾸고, 다시 요약표와 발표 스크립트로 만들고, 추가로 이미지나 영상까지 붙이는 식의 작업이라면 Skywork 같은 워크스페이스형 도구가 맞을 수 있습니다. 다만 최종 포맷 제한은 실제 계정에서 확인해야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AI PPT 품질을 올리는 7단계 워크플로우&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 AI PPT는 &amp;ldquo;프롬프트 한 번&amp;rdquo;으로 나오지 않습니다. 실무에서는 아래 순서로 만들면 훨씬 안정적입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;발표 목적을 먼저 적습니다.&lt;/b&gt; 정보 전달, 설득, 보고, 교육 중 무엇인지 정해야 슬라이드 구조가 맞습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;청중을 구체화합니다.&lt;/b&gt; 대학생, 임원, 고객사, 투자자, 내부 팀원은 필요한 설명 수준이 다릅니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;슬라이드 수를 제한합니다.&lt;/b&gt; 10분 발표라면 6~8장, 20분 발표라면 10~15장 정도가 보통 안전합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;먼저 아웃라인만 생성합니다.&lt;/b&gt; 바로 디자인까지 만들지 말고 목차와 핵심 메시지를 먼저 검토합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;근거 자료를 확인합니다.&lt;/b&gt; 통계, 가격, 시장 규모, 제품 기능은 원문 링크로 확인합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;한 슬라이드에 메시지 하나만 남깁니다.&lt;/b&gt; AI는 내용을 많이 넣는 경향이 있어 사람이 덜어내야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;마지막은 PowerPoint 또는 Google Slides에서 다듬습니다.&lt;/b&gt; 발표 환경, 폰트, 줄바꿈, 로고, 표기법은 사람이 최종 정리해야 합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실무 팁:&lt;/b&gt; AI에게 &amp;ldquo;예쁜 PPT 만들어줘&amp;rdquo;라고 말하기보다 &amp;ldquo;누가, 왜, 몇 분 동안, 어떤 결정을 얻기 위해 보는 발표인지&amp;rdquo;를 알려줘야 결과가 좋아집니다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;추천 조합: 하나만 쓰지 않아도 됩니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 도구 중 하나만 고집할 필요는 없습니다. 실제로는 역할을 나눠 쓰는 것이 더 좋습니다.&lt;/p&gt;
&lt;div&gt;AI PPT 도구 조합별 활용법작업 흐름 추천 조합 활용 방식
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;리서치부터 발표자료까지&lt;/td&gt;
&lt;td&gt;Genspark &amp;rarr; Gamma&lt;/td&gt;
&lt;td&gt;Genspark로 자료 조사와 아웃라인을 만들고, Gamma에서 디자인을 다듬습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;문서 패키지 제작&lt;/td&gt;
&lt;td&gt;Skywork &amp;rarr; Genspark&lt;/td&gt;
&lt;td&gt;Skywork에서 문서&amp;middot;표&amp;middot;기초 자료를 만들고, Genspark에서 발표용 PPTX로 정리합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;빠른 내부 공유&lt;/td&gt;
&lt;td&gt;Gamma 단독&lt;/td&gt;
&lt;td&gt;초안을 빠르게 만들고 링크로 공유합니다. 복잡한 수치는 별도 검증합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;기존 PDF를 발표자료로 변환&lt;/td&gt;
&lt;td&gt;Genspark 단독&lt;/td&gt;
&lt;td&gt;PDF, Word, Excel을 넣고 아웃라인 승인 후 PPTX로 내보냅니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자주 묻는 질문&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;무료 플랜만으로 충분한가요?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 테스트나 5~10장짜리 초안은 무료 플랜으로도 시작할 수 있습니다. 하지만 PPTX 내보내기, 브랜드 제거, 더 긴 카드 수, 고급 AI 모델, 팀 협업, API 같은 기능은 유료 플랜에서 차이가 납니다. 특히 가격과 크레딧은 자주 바뀌므로 결제 전 공식 가격표를 다시 확인하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;AI PPT를 그대로 제출해도 괜찮나요?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;권장하지 않습니다. AI PPT는 초안 제작 도구로 보는 것이 안전합니다. 발표자의 말투, 회사 표기법, 숫자 근거, 슬라이드 줄바꿈, 이미지 저작권, 폰트 호환성은 최종 제출 전에 직접 점검해야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;한국어 발표자료는 어떤 도구가 좋나요?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 도구 모두 한국어 입력과 생성에 사용할 수 있습니다. 다만 한국어는 문장이 길어지면 슬라이드 안에서 줄바꿈이 어색해질 수 있습니다. 그래서 최종본은 PowerPoint나 Google Slides에서 제목 길이, 조사, 띄어쓰기, 표 셀 너비를 직접 다듬는 것이 좋습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PPTX 내보내기가 꼭 필요한가요?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사나 학교에서 PowerPoint 파일 제출을 요구한다면 꼭 필요합니다. 링크 공유만 하면 되는 발표라면 Gamma 같은 웹 기반 공유도 편합니다. 하지만 발표장 PC, 폰트, 인터넷 연결 문제가 있을 수 있으니 중요한 발표는 PPTX와 PDF를 모두 준비하는 편이 안전합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;최종 추천&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Genspark&lt;/b&gt;는 자료 기반 발표자료에 가장 현실적인 선택입니다. 문서 업로드, 아웃라인 승인, 실제 PPTX 내보내기, 팩트체크 흐름이 실무 보고서와 잘 맞습니다. 단, 기능이 많기 때문에 처음에는 하나의 작업 흐름만 정해서 쓰는 것이 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Gamma&lt;/b&gt;는 빠르고 보기 좋은 발표자료를 만들 때 가장 편합니다. 제안서, 강의자료, 포트폴리오, 웹 공유용 자료에 강합니다. 다만 통계와 출처가 중요한 발표에서는 리서치 도구를 별도로 붙이는 것이 안전합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Skywork&lt;/b&gt;는 단일 PPT 제작 도구라기보다 여러 산출물을 함께 만드는 AI 워크스페이스로 보는 편이 맞습니다. 문서, 슬라이드, 시트, 이미지, 영상 등 여러 결과물을 한 프로젝트에서 만들고 싶다면 테스트할 가치가 있습니다. 다만 가격, 내보내기, 보안 조건은 실제 계정에서 확인해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면, &amp;ldquo;보고서와 근거 중심&amp;rdquo;이면 Genspark, &amp;ldquo;디자인과 공유 중심&amp;rdquo;이면 Gamma, &amp;ldquo;여러 콘텐츠를 한 번에 만드는 작업&amp;rdquo;이면 Skywork가 출발점입니다. AI PPT 도구는 발표자를 대체하는 도구가 아니라, 초안 작성 시간을 줄이고 더 많은 시간을 검증과 메시지 정리에 쓰게 해주는 도구로 보는 것이 가장 정확합니다.&lt;/p&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고한 공식 자료&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://skywork.ai/&quot;&gt;Skywork 공식 홈페이지&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://skywork.ai/slide&quot;&gt;Skywork Slides 페이지&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.genspark.ai/tools/ai-presentation-maker&quot;&gt;Genspark AI Presentation Maker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.genspark.ai/tools/ai-powerpoint-generator&quot;&gt;Genspark AI PowerPoint Generator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gamma.app/products/presentations&quot;&gt;Gamma Presentations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gamma.app/pricing&quot;&gt;Gamma Pricing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gamma.app/products/api&quot;&gt;Gamma API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://unsplash.com/photos/person-using-macbook-pro-on-brown-wooden-table-txoG5VLqsjM&quot;&gt;대표 이미지: Slidebean on Unsplash&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 2026년 6월 10일 공개 페이지 기준으로 작성했습니다. AI 서비스의 가격, 크레딧, 내보내기 제한, 지원 언어, 모델 구성은 예고 없이 변경될 수 있으므로 실제 사용 전 각 공식 페이지에서 다시 확인하세요.&lt;/p&gt;
&lt;/div&gt;</description>
      <category>AI</category>
      <category>ai #툴 #ppt #skywork #genspark #gamma</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/59</guid>
      <comments>https://onethingflow.tistory.com/entry/AI-PPT-%EC%A0%9C%EC%9E%91-%EB%8F%84%EA%B5%AC-3%EB%8C%80%EC%9E%A5-%EC%99%84%EC%A0%84-%EB%B9%84%EA%B5%90-Skywork-vs-Genspark-vs-Gamma#entry59comment</comments>
      <pubDate>Wed, 10 Jun 2026 10:29:34 +0900</pubDate>
    </item>
    <item>
      <title>코딩의 덧셈&amp;middot;나눗셈&amp;middot;몫&amp;middot;나머지 완전 기초: 초보자를 위한 산술 연산자 설명</title>
      <link>https://onethingflow.tistory.com/entry/%EC%BD%94%EB%94%A9%EC%9D%98-%EB%8D%A7%EC%85%88%C2%B7%EB%82%98%EB%88%97%EC%85%88%C2%B7%EB%AA%AB%C2%B7%EB%82%98%EB%A8%B8%EC%A7%80-%EC%99%84%EC%A0%84-%EA%B8%B0%EC%B4%88-%EC%B4%88%EB%B3%B4%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%82%B0%EC%88%A0-%EC%97%B0%EC%82%B0%EC%9E%90-%EC%84%A4%EB%AA%85</link>
      <description>&lt;!--
티스토리 제목 추천:
코딩의 덧셈·나눗셈·몫·나머지 완전 기초: 초보자를 위한 산술 연산자 설명

티스토리 태그 추천:
코딩기초, 프로그래밍기초, 산술연산자, 덧셈, 나눗셈, 몫, 나머지, 파이썬기초, 자바스크립트기초, 초보개발자

메타 설명 추천:
코딩에서 덧셈, 뺄셈, 곱셈, 나눗셈, 몫, 나머지, 정수 나눗셈, 소수 나눗셈, 연산자 우선순위를 초보자 눈높이로 정리했습니다. Python과 JavaScript 예제로 헷갈리는 포인트까지 함께 설명합니다.
--&gt;
&lt;div&gt;
&lt;style&gt;
.hb-post{max-width:780px;margin:0 auto;line-height:1.86;font-size:17px;color:#222;word-break:keep-all;}
.hb-post *{box-sizing:border-box;}
.hb-post h1{margin:0 0 .72em;font-size:2em;line-height:1.28;font-weight:800;color:#111;}
.hb-post h2{margin:2.5em 0 .75em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.36em;border-bottom:2px solid #edf0f4;color:#111;}
.hb-post h3{margin:1.85em 0 .55em;font-size:1.08em;line-height:1.45;font-weight:800;color:#182033;}
.hb-post p{margin:0 0 1.12em;}
.hb-post a{color:#235ad1;text-decoration:none;border-bottom:1px solid rgba(35,90,209,.25);}
.hb-post a:hover{border-bottom-color:#235ad1;}
.hb-post strong{font-weight:800;}
.hb-post code{background:#f4f5f7;border:1px solid #e6e8eb;border-radius:4px;padding:.08em .4em;font-size:.92em;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;color:#c7254e;}
.hb-post pre{background:#1f2430;color:#eef2ff;border-radius:8px;padding:1.1em 1.2em;overflow-x:auto;line-height:1.62;font-size:.88em;margin:1.35em 0;}
.hb-post pre code{background:transparent;border:none;color:inherit;padding:0;font-size:1em;}
.hb-post .hb-lead{font-size:1.08em;color:#343a46;}
.hb-post .hb-hero{margin:0 0 1.6em;padding:1.35em 1.4em;border:1px solid #e1e6ef;border-radius:8px;background:#f8fbff;}
.hb-post .hb-hero p:last-child{margin-bottom:0;}
.hb-post .hb-kpi{display:grid;grid-template-columns:repeat(3,1fr);gap:.85em;margin:1.4em 0;}
.hb-post .hb-kpi div{border:1px solid #e5e8ee;border-radius:8px;background:#fbfcfd;padding:1em;}
.hb-post .hb-kpi span{display:block;font-size:.82em;color:#687182;margin-bottom:.25em;}
.hb-post .hb-kpi strong{display:block;font-size:1.1em;color:#10141b;line-height:1.35;}
.hb-post .hb-note-box{background:#f7f9fc;border:1px solid #e3e9f2;border-left:4px solid #3f75ff;border-radius:8px;padding:1.1em 1.25em;margin:1.55em 0;}
.hb-post .hb-note-box p{margin:0 0 .58em;}
.hb-post .hb-note-box p:last-child{margin-bottom:0;}
.hb-post .hb-green{background:#f4fbf8;border-color:#d7eee3;border-left-color:#2a9d8f;}
.hb-post .hb-warn{background:#fff8f4;border-color:#f1d8cc;border-left-color:#e76f51;}
.hb-post blockquote.hb-pull{margin:1.55em 0;padding:.95em 1.15em;background:#fff9e8;border-left:4px solid #f2b705;border-radius:8px;font-size:1.06em;font-weight:800;color:#584500;}
.hb-post ul,.hb-post ol{margin:0 0 1.18em;padding-left:1.38em;}
.hb-post ul li{list-style:disc;}
.hb-post ol li{list-style:decimal;}
.hb-post li{margin:.38em 0;}
.hb-post .hb-table-wrap{overflow-x:auto;margin:1.45em 0;-webkit-overflow-scrolling:touch;}
.hb-post table{border-collapse:collapse;width:100%;font-size:.93em;min-width:760px;}
.hb-post th,.hb-post td{border:1px solid #e1e5eb;padding:.72em .82em;text-align:left;vertical-align:top;}
.hb-post thead th{background:#f1f4f8;font-weight:800;color:#172033;}
.hb-post tbody tr:nth-child(even){background:#fafbfc;}
.hb-post caption{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);}
.hb-post .hb-formula{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;background:#fbfcfd;border:1px solid #e4e8ef;border-radius:8px;padding:1em 1.15em;margin:1.35em 0;color:#202938;}
.hb-post .hb-answer{background:#fbfbfb;border:1px solid #ededed;border-radius:8px;padding:1.1em 1.3em;margin:1.45em 0;}
.hb-post .hb-answer strong{color:#1f3b73;}
.hb-post .hb-source{margin-top:2.7em;padding-top:1.2em;border-top:1px solid #edf0f4;font-size:.92em;color:#4b5565;}
.hb-post .hb-source li{margin:.45em 0;}
.hb-post .hb-disclaimer{margin-top:1.6em;font-size:.88em;color:#7a8290;}
@media (max-width:640px){
  .hb-post{font-size:16px;}
  .hb-post h1{font-size:1.58em;}
  .hb-post .hb-kpi{grid-template-columns:1fr;}
  .hb-post table{font-size:.9em;min-width:860px;}
}
&lt;/style&gt;
&lt;/div&gt;
&lt;article class=&quot;hb-post&quot;&gt;
&lt;div class=&quot;hb-hero&quot;&gt;
&lt;h1&gt;코딩의 덧셈&amp;middot;나눗셈&amp;middot;몫&amp;middot;나머지 완전 기초&lt;/h1&gt;
&lt;p class=&quot;hb-lead&quot; data-ke-size=&quot;size16&quot;&gt;코딩을 처음 배울 때 덧셈, 뺄셈, 곱셈, 나눗셈은 쉬워 보인다. 그런데 막상 코드를 쓰다 보면 &lt;code&gt;/&lt;/code&gt;와 &lt;code&gt;//&lt;/code&gt;의 차이, &lt;code&gt;%&lt;/code&gt;가 왜 필요한지, &lt;code&gt;1 + &quot;2&quot;&lt;/code&gt; 같은 코드가 왜 이상한 결과를 만드는지에서 자주 막힌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 수학을 잘하는 사람을 위한 글이 아니라, 코딩을 막 시작한 사람이 &amp;ldquo;아, 그래서 이렇게 쓰는구나&amp;rdquo; 하고 감을 잡을 수 있도록 정리한 산술 연산자 기초 가이드다. 예제는 Python을 중심으로 설명하고, 웹 개발 입문자가 많이 만나는 JavaScript 차이도 함께 적었다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-kpi&quot;&gt;
&lt;div&gt;&lt;span&gt;기본 연산&lt;/span&gt; &lt;b&gt;&lt;code&gt;+&lt;/code&gt; &lt;code&gt;-&lt;/code&gt; &lt;code&gt;*&lt;/code&gt; &lt;code&gt;/&lt;/code&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;나눗셈의 핵심&lt;/span&gt; &lt;b&gt;몫과 나머지&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;초보자 실수&lt;/span&gt; &lt;b&gt;타입, 0, 우선순위&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote class=&quot;hb-pull&quot; data-ke-style=&quot;style1&quot;&gt;코딩에서 산술 연산은 계산기 기능이 아니라, 데이터를 원하는 형태로 바꾸는 가장 기본적인 도구다.&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 코딩에서 연산자는 무엇일까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연산자는 컴퓨터에게 &amp;ldquo;이 값과 저 값을 이렇게 계산해줘&amp;rdquo;라고 말하는 기호다. 예를 들어 &lt;code&gt;3 + 4&lt;/code&gt;에서 &lt;code&gt;3&lt;/code&gt;과 &lt;code&gt;4&lt;/code&gt;는 계산에 쓰이는 값이고, &lt;code&gt;+&lt;/code&gt;는 두 값을 더하라는 연산자다. 이런 계산식 전체를 보통 표현식이라고 부른다.&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;3 + 4
price * count
total / people&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초보자는 연산자를 &amp;ldquo;수학 기호&amp;rdquo;로만 생각하기 쉽다. 하지만 코딩에서는 한 가지를 더 봐야 한다. 바로 &lt;b&gt;값의 종류, 즉 타입&lt;/b&gt;이다. 숫자끼리 더하면 계산이 되지만, 문자열끼리 더하면 글자가 이어 붙는다. 같은 &lt;code&gt;+&lt;/code&gt;라도 어떤 타입에 쓰느냐에 따라 의미가 달라질 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 기본 산술 연산자 한 번에 보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 프로그래밍 언어는 아래 연산자를 공통으로 사용한다. 기호 자체는 단순하지만, 실제 코드를 짤 때는 &amp;ldquo;결과가 정수인지 소수인지&amp;rdquo;, &amp;ldquo;나눗셈에서 몫만 필요한지&amp;rdquo;, &amp;ldquo;나머지가 필요한지&amp;rdquo;를 구분해야 한다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;초보자를 위한 코딩 산술 연산자 표&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;연산자&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;이름&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;의미&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;Python 예시&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;결과&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;+&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;덧셈&lt;/td&gt;
&lt;td&gt;두 값을 더한다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10 + 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;13&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;뺄셈&lt;/td&gt;
&lt;td&gt;왼쪽 값에서 오른쪽 값을 뺀다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10 - 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;7&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;곱셈&lt;/td&gt;
&lt;td&gt;두 값을 곱한다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10 * 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;30&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;나눗셈&lt;/td&gt;
&lt;td&gt;왼쪽 값을 오른쪽 값으로 나눈다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10 / 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3.333...&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;//&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;몫, floor division&lt;/td&gt;
&lt;td&gt;나눈 결과에서 정수 몫을 구한다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10 // 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;나머지, modulo&lt;/td&gt;
&lt;td&gt;나누고 남은 값을 구한다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10 % 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;**&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;거듭제곱&lt;/td&gt;
&lt;td&gt;같은 수를 여러 번 곱한다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2 ** 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;8&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-note-box&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;JavaScript를 공부한다면?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript에도 &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;%&lt;/code&gt;, &lt;code&gt;**&lt;/code&gt;가 있다. 다만 Python의 &lt;code&gt;//&lt;/code&gt;처럼 몫만 바로 구하는 연산자는 일반 숫자 타입에 따로 없어서 &lt;code&gt;Math.floor()&lt;/code&gt;, &lt;code&gt;Math.trunc()&lt;/code&gt; 같은 함수를 함께 쓴다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 덧셈: 숫자는 더하고, 문자열은 붙인다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;덧셈은 가장 익숙한 연산이다. 숫자끼리 더하면 우리가 아는 그 덧셈이다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;a = 10
b = 3

print(a + b)  # 13&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 코딩에서 &lt;code&gt;+&lt;/code&gt;는 숫자에만 쓰이지 않는다. 문자열에도 쓸 수 있다. 문자열은 글자 데이터이기 때문에, 이때 &lt;code&gt;+&lt;/code&gt;는 계산이 아니라 이어 붙이기가 된다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;first_name = &quot;Heo&quot;
last_name = &quot;Brain&quot;

print(first_name + last_name)   # HeoBrain
print(first_name + &quot; &quot; + last_name)  # Heo Brain&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 초보자가 자주 만나는 실수가 있다. 숫자처럼 보이는 문자열은 숫자가 아니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;print(1 + 2)      # 3
print(&quot;1&quot; + &quot;2&quot;)  # 12&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&quot;1&quot;&lt;/code&gt;은 숫자 1이 아니라 글자 &quot;1&quot;이다. 그래서 &lt;code&gt;&quot;1&quot; + &quot;2&quot;&lt;/code&gt;는 3이 아니라 &quot;12&quot;가 된다. 사용자 입력값은 대부분 문자열로 들어오기 때문에, 계산하려면 숫자로 바꿔야 한다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;age_text = &quot;20&quot;
age = int(age_text)

print(age + 1)  # 21&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;hb-warn hb-note-box&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;JavaScript에서 더 조심해야 하는 부분&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript에서는 &lt;code&gt;&quot;1&quot; + 2&lt;/code&gt;가 &lt;code&gt;&quot;12&quot;&lt;/code&gt;가 된다. 한쪽이 문자열이면 다른 값도 문자열처럼 이어 붙는 상황이 생긴다. 숫자 계산을 하고 싶다면 &lt;code&gt;Number(&quot;1&quot;) + 2&lt;/code&gt;처럼 명시적으로 변환하는 습관이 좋다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 뺄셈과 곱셈: 순서와 기호를 정확히 보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뺄셈은 왼쪽 값에서 오른쪽 값을 빼는 연산이다. 덧셈과 달리 순서를 바꾸면 결과가 달라진다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;print(10 - 3)  # 7
print(3 - 10)  # -7&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;곱셈은 코딩에서 &lt;code&gt;x&lt;/code&gt;가 아니라 &lt;code&gt;*&lt;/code&gt;를 쓴다. 처음에는 낯설지만 금방 익숙해진다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;price = 12000
count = 3

total = price * count
print(total)  # 36000&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Python에서는 문자열에 정수를 곱하면 같은 문자열을 반복할 수도 있다. 이것은 숫자 곱셈이라기보다 &amp;ldquo;반복&amp;rdquo;에 가깝다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;print(&quot;ha&quot; * 3)  # hahaha
print(&quot;-&quot; * 10)  # ----------&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 기능은 간단한 출력 테스트에는 편하지만, 실제 계산 코드에서는 값이 숫자인지 문자열인지 계속 확인하는 습관이 중요하다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 나눗셈: 몫을 볼지, 소수까지 볼지 정해야 한다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나눗셈을 이해하려면 먼저 용어를 정리하는 편이 좋다.&lt;/p&gt;
&lt;div class=&quot;hb-formula&quot;&gt;10 &amp;divide; 3 = 3 ... 1&lt;br /&gt;나누어지는 수: 10&lt;br /&gt;나누는 수: 3&lt;br /&gt;몫: 3&lt;br /&gt;나머지: 1&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코딩에서는 이 네 가지를 자주 나눠서 생각한다. 어떤 상황에서는 &lt;code&gt;10 / 3&lt;/code&gt;처럼 소수 결과가 필요하고, 어떤 상황에서는 &amp;ldquo;3개씩 묶으면 몇 묶음이 되는지&amp;rdquo;처럼 몫만 필요하다. 또 어떤 상황에서는 &amp;ldquo;묶고 남는 것이 몇 개인지&amp;rdquo;가 더 중요하다.&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;print(10 / 3)   # 3.3333333333333335
print(10 // 3)  # 3
print(10 % 3)   # 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Python에서 &lt;code&gt;/&lt;/code&gt;는 정수끼리 나눠도 소수형 결과를 만든다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;print(6 / 3)  # 2.0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수학적으로는 2지만, Python 결과는 &lt;code&gt;2.0&lt;/code&gt;이다. &lt;code&gt;2&lt;/code&gt;는 정수, &lt;code&gt;2.0&lt;/code&gt;은 소수형 숫자다. 값은 비슷해 보여도 타입이 다르다. 이 차이는 나중에 데이터베이스 저장, 화면 표시, 반올림 처리에서 중요해진다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 몫: &lt;code&gt;//&lt;/code&gt;는 &amp;ldquo;그냥 소수점 버리기&amp;rdquo;가 아니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몫은 나눗셈 결과에서 &amp;ldquo;몇 번 들어가는가&amp;rdquo;를 나타내는 값이다. 예를 들어 사탕 10개를 3명에게 똑같이 나눠주면 한 명당 3개씩 줄 수 있고, 1개가 남는다. 여기서 3이 몫이다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;candies = 10
people = 3

each = candies // people
left = candies % people

print(each)  # 3
print(left)  # 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Python의 &lt;code&gt;//&lt;/code&gt;는 floor division이라고 부른다. 양수끼리 계산할 때는 단순히 소수점 아래를 버리는 것처럼 보인다.&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;print(7 // 2)   # 3
print(9 // 4)   # 2
print(100 // 30)  # 3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 음수가 들어가면 이야기가 조금 달라진다. Python의 &lt;code&gt;//&lt;/code&gt;는 결과를 0쪽으로 자르는 것이 아니라 더 작은 정수 방향으로 내린다.&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;print(-7 / 2)   # -3.5
print(-7 // 2)  # -4&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 보면 &amp;ldquo;왜 -3이 아니지?&amp;rdquo; 싶을 수 있다. 이유는 &lt;code&gt;//&lt;/code&gt;가 floor, 즉 바닥 방향으로 내리기 때문이다. 숫자선에서 -4는 -3보다 더 작다. 양수만 다룰 때는 크게 신경 쓰지 않아도 되지만, 좌표 계산이나 날짜 차이처럼 음수가 나올 수 있는 코드에서는 이 차이가 중요하다.&lt;/p&gt;
&lt;div class=&quot;hb-note-box&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;JavaScript에서 몫을 구하려면&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript 일반 숫자에는 Python의 &lt;code&gt;//&lt;/code&gt;가 없다. 양수에서 몫만 필요하면 &lt;code&gt;Math.floor(7 / 2)&lt;/code&gt;를 많이 쓴다. 음수까지 다룰 때는 &lt;code&gt;Math.floor()&lt;/code&gt;와 &lt;code&gt;Math.trunc()&lt;/code&gt;의 결과가 달라질 수 있으므로 의도를 먼저 정해야 한다.&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;console.log(Math.floor(7 / 2));   // 3
console.log(Math.trunc(7 / 2));   // 3

console.log(Math.floor(-7 / 2));  // -4
console.log(Math.trunc(-7 / 2));  // -3&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 나머지: &lt;code&gt;%&lt;/code&gt;는 생각보다 자주 쓴다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나머지는 나누고 남은 값이다. 수학 시간에는 그냥 문제 풀이용으로 지나갔을 수 있지만, 코딩에서는 매우 자주 등장한다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;print(10 % 3)  # 1
print(8 % 2)   # 0
print(9 % 2)   # 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 쉬운 예는 짝수와 홀수 판별이다. 어떤 수를 2로 나눴을 때 나머지가 0이면 짝수, 1이면 홀수다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;number = 17

if number % 2 == 0:
    print(&quot;짝수&quot;)
else:
    print(&quot;홀수&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나머지는 반복되는 패턴을 만들 때도 유용하다. 예를 들어 요일은 7일마다 반복되고, 배열 인덱스는 길이를 넘으면 다시 처음으로 돌아가야 할 때가 있다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;days = [&quot;월&quot;, &quot;화&quot;, &quot;수&quot;, &quot;목&quot;, &quot;금&quot;, &quot;토&quot;, &quot;일&quot;]

today_index = 0
after_10_days = (today_index + 10) % 7

print(days[after_10_days])  # 목&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;7로 나눈 나머지&amp;rdquo;를 사용했기 때문에 0부터 6 사이의 인덱스 안에서만 결과가 나온다. 달력, 순번, 페이지, 슬라이드, 게임 캐릭터 위치처럼 반복 구조가 있는 곳에서 &lt;code&gt;%&lt;/code&gt;는 정말 자주 쓰인다.&lt;/p&gt;
&lt;div class=&quot;hb-warn hb-note-box&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;음수의 나머지는 언어마다 다를 수 있다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;양수끼리 계산할 때는 &lt;code&gt;%&lt;/code&gt;를 &amp;ldquo;나머지&amp;rdquo;라고 이해해도 거의 문제가 없다. 다만 음수가 들어가면 Python과 JavaScript 결과가 달라질 수 있다. 예를 들어 Python의 &lt;code&gt;-7 % 2&lt;/code&gt;는 &lt;code&gt;1&lt;/code&gt;이고, JavaScript의 &lt;code&gt;-7 % 2&lt;/code&gt;는 &lt;code&gt;-1&lt;/code&gt;이다. 좌표 이동, 회전, 순환 인덱스처럼 음수가 나올 수 있는 코드는 공식 문서를 확인하는 습관이 좋다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 몫과 나머지는 항상 한 세트로 생각하면 편하다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몫과 나머지는 따로 외우는 것보다 아래 관계로 묶어 이해하면 훨씬 쉽다.&lt;/p&gt;
&lt;div class=&quot;hb-formula&quot;&gt;원래 수 = 나누는 수 &amp;times; 몫 + 나머지&lt;br /&gt;10 = 3 &amp;times; 3 + 1&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Python에서는 이 관계가 그대로 코드로도 이어진다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;x = 10
y = 3

quotient = x // y
remainder = x % y

print(x == y * quotient + remainder)  # True&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몫과 나머지를 동시에 구하고 싶다면 Python에서는 &lt;code&gt;divmod()&lt;/code&gt;도 쓸 수 있다.&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;quotient, remainder = divmod(10, 3)

print(quotient)   # 3
print(remainder)  # 1&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;hb-green hb-note-box&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실전 감각으로 바꿔보기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람 5명에게 쿠키 23개를 나눠준다면 &lt;code&gt;23 // 5&lt;/code&gt;는 한 명당 받을 수 있는 쿠키 수이고, &lt;code&gt;23 % 5&lt;/code&gt;는 나누고 남는 쿠키 수다. 즉 몫은 &amp;ldquo;공평하게 몇 개씩?&amp;rdquo;, 나머지는 &amp;ldquo;그래도 남는 것은?&amp;rdquo;이라는 질문에 답한다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9. 연산자 우선순위: 컴퓨터도 계산 순서가 있다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드는 왼쪽에서 오른쪽으로만 계산되는 것이 아니다. 수학처럼 곱셈과 나눗셈이 덧셈과 뺄셈보다 먼저 계산된다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;print(2 + 3 * 4)    # 14
print((2 + 3) * 4)  # 20&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 순서는 대략 이렇게 기억하면 된다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;괄호 &lt;code&gt;()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;거듭제곱 &lt;code&gt;**&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;곱셈, 나눗셈, 몫, 나머지 &lt;code&gt;*&lt;/code&gt; &lt;code&gt;/&lt;/code&gt; &lt;code&gt;//&lt;/code&gt; &lt;code&gt;%&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;덧셈, 뺄셈 &lt;code&gt;+&lt;/code&gt; &lt;code&gt;-&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초보자에게 가장 좋은 습관은 애매하면 괄호를 쓰는 것이다. 컴퓨터가 알아서 해석하겠지 하고 맡기기보다, 내가 의도한 계산 순서를 코드에 드러내는 편이 유지보수에도 좋다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;total_price = (item_price * count) + delivery_fee
average_score = (math_score + english_score + coding_score) / 3&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;10. 실전 예제로 익히기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 1. 장바구니 총액 계산&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상품 가격과 개수를 곱하고, 배송비를 더하면 총 결제 금액이 된다. 가장 기본적인 덧셈과 곱셈 조합이다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;item_price = 15000
count = 2
delivery_fee = 3000

total = item_price * count + delivery_fee

print(total)  # 33000&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 2. 회비를 나눠 내기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 금액을 인원수로 나누면 1인당 금액이 나온다. 원 단위로 딱 떨어지지 않으면 몫과 나머지를 함께 봐야 한다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;total_fee = 10000
people = 3

each = total_fee // people
left = total_fee % people

print(each)  # 3333
print(left)  # 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우 한 사람당 3,333원씩 내면 1원이 남는다. 실제 서비스라면 남은 1원을 누가 부담할지 정책을 정해야 한다. 코딩에서 산술 연산은 단순 계산으로 끝나지 않고, 이렇게 서비스 규칙과 연결된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 3. 게시글 페이지 수 계산&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게시글이 53개 있고 한 페이지에 10개씩 보여준다면 몇 페이지가 필요할까? 일반 나눗셈으로는 5.3이지만, 실제 화면에는 6페이지가 필요하다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;import math

total_posts = 53
page_size = 10

pages = math.ceil(total_posts / page_size)

print(pages)  # 6&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 몫만 구하면 안 된다. 5페이지까지는 50개를 보여주고, 남은 3개를 보여줄 6페이지가 필요하기 때문이다. 이런 경우에는 올림을 사용한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 4. 초를 분과 초로 바꾸기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;러닝 앱이나 타이머 앱을 만든다고 생각해보자. 125초를 &amp;ldquo;2분 5초&amp;rdquo;로 바꾸려면 몫과 나머지를 함께 쓰면 된다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;seconds = 125

minutes = seconds // 60
remaining_seconds = seconds % 60

print(minutes)            # 2
print(remaining_seconds)  # 5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 예제는 몫과 나머지가 왜 중요한지 가장 잘 보여준다. 몫은 완성된 분 단위이고, 나머지는 분으로 묶고 남은 초다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;11. 초보자가 자주 만나는 오류&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;0으로 나누기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 수를 0으로 나누는 계산은 성립하지 않는다. Python에서는 &lt;code&gt;ZeroDivisionError&lt;/code&gt;가 발생한다.&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;print(10 / 0)  # ZeroDivisionError&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 사용자 입력값이나 데이터 개수로 나눌 때는 0인지 먼저 확인해야 한다.&lt;/p&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;total = 100
count = 0

if count == 0:
    print(&quot;평균을 계산할 수 없습니다.&quot;)
else:
    print(total / count)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;소수 계산이 딱 맞지 않는 문제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터는 소수를 10진수 그대로 저장하지 못하는 경우가 있다. 그래서 아래처럼 예상과 조금 다른 결과가 나올 수 있다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;print(0.1 + 0.2)  # 0.30000000000000004&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것은 Python만의 문제가 아니라 많은 프로그래밍 언어에서 만나는 부동소수점 표현 문제다. 일반적인 화면 표시에서는 반올림해서 보여주면 되고, 돈 계산처럼 정확성이 중요한 경우에는 원 단위 정수로 저장하거나 Decimal 같은 별도 방식을 사용한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;반올림, 올림, 내림을 섞어 쓰는 문제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나눗셈 결과를 정수로 바꿀 때는 &amp;ldquo;어떤 방식으로 정수화할 것인지&amp;rdquo;를 분명히 해야 한다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;나눗셈 결과를 정수로 바꾸는 대표 방식&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;방식&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;의미&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;예시&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;어울리는 상황&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;버림&lt;/td&gt;
&lt;td&gt;소수 부분을 제거한다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;int(3.8) == 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;소수는 필요 없고 정수 부분만 쓸 때&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;내림&lt;/td&gt;
&lt;td&gt;더 작은 정수로 내린다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;math.floor(3.8) == 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;좌표, 구간, floor division 개념&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;올림&lt;/td&gt;
&lt;td&gt;더 큰 정수로 올린다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;math.ceil(3.1) == 4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;페이지 수, 필요한 박스 수 계산&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;반올림&lt;/td&gt;
&lt;td&gt;가까운 정수로 맞춘다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;round(3.6) == 4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;평균 점수, 화면 표시&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;값을 업데이트할 때 생기는 헷갈림&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코딩에서는 기존 값에 어떤 값을 더해서 다시 저장하는 일이 아주 많다.&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;count = 0
count = count + 1

print(count)  # 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드는 수학 방정식이 아니다. &amp;ldquo;오른쪽을 먼저 계산한 뒤, 그 결과를 왼쪽 변수에 다시 넣는다&amp;rdquo;는 뜻이다. 같은 코드를 더 짧게 쓰면 이렇게 된다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;count += 1
total += price
stock -= 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;+=&lt;/code&gt;, &lt;code&gt;-=&lt;/code&gt;, &lt;code&gt;*=&lt;/code&gt;, &lt;code&gt;/=&lt;/code&gt; 같은 대입 연산자는 계산과 저장을 한 번에 표현한다. 반복문에서 카운트를 세거나, 장바구니 금액을 누적하거나, 재고를 줄일 때 자주 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript나 C 계열 언어에서는 &lt;code&gt;count++&lt;/code&gt;, &lt;code&gt;count--&lt;/code&gt;처럼 1씩 증가하거나 감소시키는 증감 연산자도 자주 보인다. Python에는 &lt;code&gt;++&lt;/code&gt; 연산자가 없으므로 &lt;code&gt;count += 1&lt;/code&gt;처럼 쓰면 된다. 처음에는 언어별 특수 문법보다 &lt;code&gt;count = count + 1&lt;/code&gt;의 의미를 정확히 이해하는 것이 먼저다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;12. 머릿속에 이렇게 정리하면 오래 간다&lt;/h2&gt;
&lt;div class=&quot;hb-answer&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;+&lt;/code&gt;&lt;/b&gt;: 숫자끼리는 더하고, 문자열끼리는 이어 붙인다. 계산 전 타입을 확인하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;-&lt;/code&gt;&lt;/b&gt;: 왼쪽에서 오른쪽을 뺀다. 순서가 바뀌면 결과도 바뀐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;*&lt;/code&gt;&lt;/b&gt;: 곱셈이다. Python에서는 문자열 반복에도 쓰일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;/&lt;/code&gt;&lt;/b&gt;: 나눗셈 결과를 소수까지 본다. Python에서는 정수끼리 나눠도 결과가 소수형이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;//&lt;/code&gt;&lt;/b&gt;: 몫을 구한다. Python에서는 floor division이라 음수 계산에서 주의가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;%&lt;/code&gt;&lt;/b&gt;: 나머지를 구한다. 짝수/홀수, 반복 패턴, 시간 변환, 페이지 계산에서 자주 쓴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;괄호&lt;/b&gt;: 계산 순서가 조금이라도 헷갈리면 괄호로 의도를 드러내자.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;13. 연습 문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 문제를 직접 손으로 예상해보고, 그다음 코드로 실행해보면 훨씬 빨리 익숙해진다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;code&gt;17 // 5&lt;/code&gt;와 &lt;code&gt;17 % 5&lt;/code&gt;의 결과는 무엇일까?&lt;/li&gt;
&lt;li&gt;초 367초를 &amp;ldquo;몇 분 몇 초&amp;rdquo;로 바꾸려면 어떤 연산자를 써야 할까?&lt;/li&gt;
&lt;li&gt;게시글 101개를 한 페이지에 20개씩 보여주려면 총 몇 페이지가 필요할까?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&quot;3&quot; + &quot;4&quot;&lt;/code&gt;와 &lt;code&gt;int(&quot;3&quot;) + int(&quot;4&quot;)&lt;/code&gt;의 결과는 어떻게 다를까?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2 + 3 * 4&lt;/code&gt;와 &lt;code&gt;(2 + 3) * 4&lt;/code&gt;의 결과가 다른 이유는 무엇일까?&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;hb-green hb-note-box&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정답 힌트&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번은 몫 3, 나머지 2다. 2번은 &lt;code&gt;// 60&lt;/code&gt;과 &lt;code&gt;% 60&lt;/code&gt;을 함께 쓰면 된다. 3번은 딱 나누어떨어지지 않는 남은 글이 있으므로 올림이 필요하다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;덧셈, 나눗셈, 몫, 나머지는 코딩 입문 초반에 배우지만, 실제로는 계속 다시 만나는 개념이다. 가격 계산, 평균 계산, 시간 변환, 페이지네이션, 짝수&amp;middot;홀수 판별, 반복 패턴 만들기까지 거의 모든 기본 프로그램에 들어간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 연산자 기호를 외우는 것보다 &amp;ldquo;이 계산에서 내가 원하는 결과가 소수인지, 몫인지, 나머지인지&amp;rdquo;를 먼저 묻는 습관이 더 중요하다. 그 질문에 답할 수 있으면 &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;//&lt;/code&gt;, &lt;code&gt;%&lt;/code&gt; 중 무엇을 써야 할지도 자연스럽게 보인다.&lt;/p&gt;
&lt;div class=&quot;hb-source&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고 자료&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Python Documentation: Binary arithmetic operations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_operators#arithmetic_operators&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MDN Web Docs: JavaScript arithmetic operators&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Division&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MDN Web Docs: Division operator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Remainder&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MDN Web Docs: Remainder operator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p class=&quot;hb-disclaimer&quot; data-ke-size=&quot;size16&quot;&gt;이 글은 코딩 입문자를 위한 학습용 글입니다. 언어마다 산술 연산자의 세부 동작이 조금씩 다를 수 있으므로, 실제 프로젝트에서는 사용 중인 언어의 공식 문서를 함께 확인하는 것이 좋습니다.&lt;/p&gt;
&lt;/article&gt;
&lt;!--
티스토리 제목 추천:
코딩의 덧셈·나눗셈·몫·나머지 완전 기초: 초보자를 위한 산술 연산자 설명

티스토리 태그 추천:
코딩기초, 프로그래밍기초, 산술연산자, 덧셈, 나눗셈, 몫, 나머지, 파이썬기초, 자바스크립트기초, 초보개발자

메타 설명 추천:
코딩에서 덧셈, 뺄셈, 곱셈, 나눗셈, 몫, 나머지, 정수 나눗셈, 소수 나눗셈, 연산자 우선순위를 초보자 눈높이로 정리했습니다. Python과 JavaScript 예제로 헷갈리는 포인트까지 함께 설명합니다.
--&gt;
&lt;div&gt;
&lt;style&gt;
.hb-post{max-width:780px;margin:0 auto;line-height:1.86;font-size:17px;color:#222;word-break:keep-all;}
.hb-post *{box-sizing:border-box;}
.hb-post h1{margin:0 0 .72em;font-size:2em;line-height:1.28;font-weight:800;color:#111;}
.hb-post h2{margin:2.5em 0 .75em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.36em;border-bottom:2px solid #edf0f4;color:#111;}
.hb-post h3{margin:1.85em 0 .55em;font-size:1.08em;line-height:1.45;font-weight:800;color:#182033;}
.hb-post p{margin:0 0 1.12em;}
.hb-post a{color:#235ad1;text-decoration:none;border-bottom:1px solid rgba(35,90,209,.25);}
.hb-post a:hover{border-bottom-color:#235ad1;}
.hb-post strong{font-weight:800;}
.hb-post code{background:#f4f5f7;border:1px solid #e6e8eb;border-radius:4px;padding:.08em .4em;font-size:.92em;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;color:#c7254e;}
.hb-post pre{background:#1f2430;color:#eef2ff;border-radius:8px;padding:1.1em 1.2em;overflow-x:auto;line-height:1.62;font-size:.88em;margin:1.35em 0;}
.hb-post pre code{background:transparent;border:none;color:inherit;padding:0;font-size:1em;}
.hb-post .hb-lead{font-size:1.08em;color:#343a46;}
.hb-post .hb-hero{margin:0 0 1.6em;padding:1.35em 1.4em;border:1px solid #e1e6ef;border-radius:8px;background:#f8fbff;}
.hb-post .hb-hero p:last-child{margin-bottom:0;}
.hb-post .hb-kpi{display:grid;grid-template-columns:repeat(3,1fr);gap:.85em;margin:1.4em 0;}
.hb-post .hb-kpi div{border:1px solid #e5e8ee;border-radius:8px;background:#fbfcfd;padding:1em;}
.hb-post .hb-kpi span{display:block;font-size:.82em;color:#687182;margin-bottom:.25em;}
.hb-post .hb-kpi strong{display:block;font-size:1.1em;color:#10141b;line-height:1.35;}
.hb-post .hb-note-box{background:#f7f9fc;border:1px solid #e3e9f2;border-left:4px solid #3f75ff;border-radius:8px;padding:1.1em 1.25em;margin:1.55em 0;}
.hb-post .hb-note-box p{margin:0 0 .58em;}
.hb-post .hb-note-box p:last-child{margin-bottom:0;}
.hb-post .hb-green{background:#f4fbf8;border-color:#d7eee3;border-left-color:#2a9d8f;}
.hb-post .hb-warn{background:#fff8f4;border-color:#f1d8cc;border-left-color:#e76f51;}
.hb-post blockquote.hb-pull{margin:1.55em 0;padding:.95em 1.15em;background:#fff9e8;border-left:4px solid #f2b705;border-radius:8px;font-size:1.06em;font-weight:800;color:#584500;}
.hb-post ul,.hb-post ol{margin:0 0 1.18em;padding-left:1.38em;}
.hb-post ul li{list-style:disc;}
.hb-post ol li{list-style:decimal;}
.hb-post li{margin:.38em 0;}
.hb-post .hb-table-wrap{overflow-x:auto;margin:1.45em 0;-webkit-overflow-scrolling:touch;}
.hb-post table{border-collapse:collapse;width:100%;font-size:.93em;min-width:760px;}
.hb-post th,.hb-post td{border:1px solid #e1e5eb;padding:.72em .82em;text-align:left;vertical-align:top;}
.hb-post thead th{background:#f1f4f8;font-weight:800;color:#172033;}
.hb-post tbody tr:nth-child(even){background:#fafbfc;}
.hb-post caption{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);}
.hb-post .hb-formula{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;background:#fbfcfd;border:1px solid #e4e8ef;border-radius:8px;padding:1em 1.15em;margin:1.35em 0;color:#202938;}
.hb-post .hb-answer{background:#fbfbfb;border:1px solid #ededed;border-radius:8px;padding:1.1em 1.3em;margin:1.45em 0;}
.hb-post .hb-answer strong{color:#1f3b73;}
.hb-post .hb-source{margin-top:2.7em;padding-top:1.2em;border-top:1px solid #edf0f4;font-size:.92em;color:#4b5565;}
.hb-post .hb-source li{margin:.45em 0;}
.hb-post .hb-disclaimer{margin-top:1.6em;font-size:.88em;color:#7a8290;}
@media (max-width:640px){
  .hb-post{font-size:16px;}
  .hb-post h1{font-size:1.58em;}
  .hb-post .hb-kpi{grid-template-columns:1fr;}
  .hb-post table{font-size:.9em;min-width:860px;}
}
&lt;/style&gt;
&lt;/div&gt;
&lt;article class=&quot;hb-post&quot;&gt;
&lt;div class=&quot;hb-hero&quot;&gt;
&lt;h1&gt;코딩의 덧셈&amp;middot;나눗셈&amp;middot;몫&amp;middot;나머지 완전 기초&lt;/h1&gt;
&lt;p class=&quot;hb-lead&quot; data-ke-size=&quot;size16&quot;&gt;코딩을 처음 배울 때 덧셈, 뺄셈, 곱셈, 나눗셈은 쉬워 보인다. 그런데 막상 코드를 쓰다 보면 &lt;code&gt;/&lt;/code&gt;와 &lt;code&gt;//&lt;/code&gt;의 차이, &lt;code&gt;%&lt;/code&gt;가 왜 필요한지, &lt;code&gt;1 + &quot;2&quot;&lt;/code&gt; 같은 코드가 왜 이상한 결과를 만드는지에서 자주 막힌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 수학을 잘하는 사람을 위한 글이 아니라, 코딩을 막 시작한 사람이 &amp;ldquo;아, 그래서 이렇게 쓰는구나&amp;rdquo; 하고 감을 잡을 수 있도록 정리한 산술 연산자 기초 가이드다. 예제는 Python을 중심으로 설명하고, 웹 개발 입문자가 많이 만나는 JavaScript 차이도 함께 적었다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-kpi&quot;&gt;
&lt;div&gt;&lt;span&gt;기본 연산&lt;/span&gt; &lt;b&gt;&lt;code&gt;+&lt;/code&gt; &lt;code&gt;-&lt;/code&gt; &lt;code&gt;*&lt;/code&gt; &lt;code&gt;/&lt;/code&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;나눗셈의 핵심&lt;/span&gt; &lt;b&gt;몫과 나머지&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;초보자 실수&lt;/span&gt; &lt;b&gt;타입, 0, 우선순위&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote class=&quot;hb-pull&quot; data-ke-style=&quot;style1&quot;&gt;코딩에서 산술 연산은 계산기 기능이 아니라, 데이터를 원하는 형태로 바꾸는 가장 기본적인 도구다.&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 코딩에서 연산자는 무엇일까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연산자는 컴퓨터에게 &amp;ldquo;이 값과 저 값을 이렇게 계산해줘&amp;rdquo;라고 말하는 기호다. 예를 들어 &lt;code&gt;3 + 4&lt;/code&gt;에서 &lt;code&gt;3&lt;/code&gt;과 &lt;code&gt;4&lt;/code&gt;는 계산에 쓰이는 값이고, &lt;code&gt;+&lt;/code&gt;는 두 값을 더하라는 연산자다. 이런 계산식 전체를 보통 표현식이라고 부른다.&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;3 + 4
price * count
total / people&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초보자는 연산자를 &amp;ldquo;수학 기호&amp;rdquo;로만 생각하기 쉽다. 하지만 코딩에서는 한 가지를 더 봐야 한다. 바로 &lt;b&gt;값의 종류, 즉 타입&lt;/b&gt;이다. 숫자끼리 더하면 계산이 되지만, 문자열끼리 더하면 글자가 이어 붙는다. 같은 &lt;code&gt;+&lt;/code&gt;라도 어떤 타입에 쓰느냐에 따라 의미가 달라질 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 기본 산술 연산자 한 번에 보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 프로그래밍 언어는 아래 연산자를 공통으로 사용한다. 기호 자체는 단순하지만, 실제 코드를 짤 때는 &amp;ldquo;결과가 정수인지 소수인지&amp;rdquo;, &amp;ldquo;나눗셈에서 몫만 필요한지&amp;rdquo;, &amp;ldquo;나머지가 필요한지&amp;rdquo;를 구분해야 한다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;초보자를 위한 코딩 산술 연산자 표&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;연산자&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;이름&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;의미&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;Python 예시&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;결과&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;+&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;덧셈&lt;/td&gt;
&lt;td&gt;두 값을 더한다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10 + 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;13&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;뺄셈&lt;/td&gt;
&lt;td&gt;왼쪽 값에서 오른쪽 값을 뺀다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10 - 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;7&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;곱셈&lt;/td&gt;
&lt;td&gt;두 값을 곱한다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10 * 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;30&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;나눗셈&lt;/td&gt;
&lt;td&gt;왼쪽 값을 오른쪽 값으로 나눈다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10 / 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3.333...&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;//&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;몫, floor division&lt;/td&gt;
&lt;td&gt;나눈 결과에서 정수 몫을 구한다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10 // 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;나머지, modulo&lt;/td&gt;
&lt;td&gt;나누고 남은 값을 구한다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10 % 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;**&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;거듭제곱&lt;/td&gt;
&lt;td&gt;같은 수를 여러 번 곱한다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2 ** 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;8&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-note-box&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;JavaScript를 공부한다면?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript에도 &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;%&lt;/code&gt;, &lt;code&gt;**&lt;/code&gt;가 있다. 다만 Python의 &lt;code&gt;//&lt;/code&gt;처럼 몫만 바로 구하는 연산자는 일반 숫자 타입에 따로 없어서 &lt;code&gt;Math.floor()&lt;/code&gt;, &lt;code&gt;Math.trunc()&lt;/code&gt; 같은 함수를 함께 쓴다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 덧셈: 숫자는 더하고, 문자열은 붙인다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;덧셈은 가장 익숙한 연산이다. 숫자끼리 더하면 우리가 아는 그 덧셈이다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;a = 10
b = 3

print(a + b)  # 13&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 코딩에서 &lt;code&gt;+&lt;/code&gt;는 숫자에만 쓰이지 않는다. 문자열에도 쓸 수 있다. 문자열은 글자 데이터이기 때문에, 이때 &lt;code&gt;+&lt;/code&gt;는 계산이 아니라 이어 붙이기가 된다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;first_name = &quot;Heo&quot;
last_name = &quot;Brain&quot;

print(first_name + last_name)   # HeoBrain
print(first_name + &quot; &quot; + last_name)  # Heo Brain&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 초보자가 자주 만나는 실수가 있다. 숫자처럼 보이는 문자열은 숫자가 아니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;print(1 + 2)      # 3
print(&quot;1&quot; + &quot;2&quot;)  # 12&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&quot;1&quot;&lt;/code&gt;은 숫자 1이 아니라 글자 &quot;1&quot;이다. 그래서 &lt;code&gt;&quot;1&quot; + &quot;2&quot;&lt;/code&gt;는 3이 아니라 &quot;12&quot;가 된다. 사용자 입력값은 대부분 문자열로 들어오기 때문에, 계산하려면 숫자로 바꿔야 한다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;age_text = &quot;20&quot;
age = int(age_text)

print(age + 1)  # 21&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;hb-warn hb-note-box&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;JavaScript에서 더 조심해야 하는 부분&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript에서는 &lt;code&gt;&quot;1&quot; + 2&lt;/code&gt;가 &lt;code&gt;&quot;12&quot;&lt;/code&gt;가 된다. 한쪽이 문자열이면 다른 값도 문자열처럼 이어 붙는 상황이 생긴다. 숫자 계산을 하고 싶다면 &lt;code&gt;Number(&quot;1&quot;) + 2&lt;/code&gt;처럼 명시적으로 변환하는 습관이 좋다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 뺄셈과 곱셈: 순서와 기호를 정확히 보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뺄셈은 왼쪽 값에서 오른쪽 값을 빼는 연산이다. 덧셈과 달리 순서를 바꾸면 결과가 달라진다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;print(10 - 3)  # 7
print(3 - 10)  # -7&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;곱셈은 코딩에서 &lt;code&gt;x&lt;/code&gt;가 아니라 &lt;code&gt;*&lt;/code&gt;를 쓴다. 처음에는 낯설지만 금방 익숙해진다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;price = 12000
count = 3

total = price * count
print(total)  # 36000&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Python에서는 문자열에 정수를 곱하면 같은 문자열을 반복할 수도 있다. 이것은 숫자 곱셈이라기보다 &amp;ldquo;반복&amp;rdquo;에 가깝다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;print(&quot;ha&quot; * 3)  # hahaha
print(&quot;-&quot; * 10)  # ----------&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 기능은 간단한 출력 테스트에는 편하지만, 실제 계산 코드에서는 값이 숫자인지 문자열인지 계속 확인하는 습관이 중요하다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 나눗셈: 몫을 볼지, 소수까지 볼지 정해야 한다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나눗셈을 이해하려면 먼저 용어를 정리하는 편이 좋다.&lt;/p&gt;
&lt;div class=&quot;hb-formula&quot;&gt;10 &amp;divide; 3 = 3 ... 1&lt;br /&gt;나누어지는 수: 10&lt;br /&gt;나누는 수: 3&lt;br /&gt;몫: 3&lt;br /&gt;나머지: 1&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코딩에서는 이 네 가지를 자주 나눠서 생각한다. 어떤 상황에서는 &lt;code&gt;10 / 3&lt;/code&gt;처럼 소수 결과가 필요하고, 어떤 상황에서는 &amp;ldquo;3개씩 묶으면 몇 묶음이 되는지&amp;rdquo;처럼 몫만 필요하다. 또 어떤 상황에서는 &amp;ldquo;묶고 남는 것이 몇 개인지&amp;rdquo;가 더 중요하다.&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;print(10 / 3)   # 3.3333333333333335
print(10 // 3)  # 3
print(10 % 3)   # 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Python에서 &lt;code&gt;/&lt;/code&gt;는 정수끼리 나눠도 소수형 결과를 만든다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;print(6 / 3)  # 2.0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수학적으로는 2지만, Python 결과는 &lt;code&gt;2.0&lt;/code&gt;이다. &lt;code&gt;2&lt;/code&gt;는 정수, &lt;code&gt;2.0&lt;/code&gt;은 소수형 숫자다. 값은 비슷해 보여도 타입이 다르다. 이 차이는 나중에 데이터베이스 저장, 화면 표시, 반올림 처리에서 중요해진다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 몫: &lt;code&gt;//&lt;/code&gt;는 &amp;ldquo;그냥 소수점 버리기&amp;rdquo;가 아니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몫은 나눗셈 결과에서 &amp;ldquo;몇 번 들어가는가&amp;rdquo;를 나타내는 값이다. 예를 들어 사탕 10개를 3명에게 똑같이 나눠주면 한 명당 3개씩 줄 수 있고, 1개가 남는다. 여기서 3이 몫이다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;candies = 10
people = 3

each = candies // people
left = candies % people

print(each)  # 3
print(left)  # 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Python의 &lt;code&gt;//&lt;/code&gt;는 floor division이라고 부른다. 양수끼리 계산할 때는 단순히 소수점 아래를 버리는 것처럼 보인다.&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;print(7 // 2)   # 3
print(9 // 4)   # 2
print(100 // 30)  # 3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 음수가 들어가면 이야기가 조금 달라진다. Python의 &lt;code&gt;//&lt;/code&gt;는 결과를 0쪽으로 자르는 것이 아니라 더 작은 정수 방향으로 내린다.&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;print(-7 / 2)   # -3.5
print(-7 // 2)  # -4&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 보면 &amp;ldquo;왜 -3이 아니지?&amp;rdquo; 싶을 수 있다. 이유는 &lt;code&gt;//&lt;/code&gt;가 floor, 즉 바닥 방향으로 내리기 때문이다. 숫자선에서 -4는 -3보다 더 작다. 양수만 다룰 때는 크게 신경 쓰지 않아도 되지만, 좌표 계산이나 날짜 차이처럼 음수가 나올 수 있는 코드에서는 이 차이가 중요하다.&lt;/p&gt;
&lt;div class=&quot;hb-note-box&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;JavaScript에서 몫을 구하려면&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript 일반 숫자에는 Python의 &lt;code&gt;//&lt;/code&gt;가 없다. 양수에서 몫만 필요하면 &lt;code&gt;Math.floor(7 / 2)&lt;/code&gt;를 많이 쓴다. 음수까지 다룰 때는 &lt;code&gt;Math.floor()&lt;/code&gt;와 &lt;code&gt;Math.trunc()&lt;/code&gt;의 결과가 달라질 수 있으므로 의도를 먼저 정해야 한다.&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;console.log(Math.floor(7 / 2));   // 3
console.log(Math.trunc(7 / 2));   // 3

console.log(Math.floor(-7 / 2));  // -4
console.log(Math.trunc(-7 / 2));  // -3&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 나머지: &lt;code&gt;%&lt;/code&gt;는 생각보다 자주 쓴다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나머지는 나누고 남은 값이다. 수학 시간에는 그냥 문제 풀이용으로 지나갔을 수 있지만, 코딩에서는 매우 자주 등장한다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;print(10 % 3)  # 1
print(8 % 2)   # 0
print(9 % 2)   # 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 쉬운 예는 짝수와 홀수 판별이다. 어떤 수를 2로 나눴을 때 나머지가 0이면 짝수, 1이면 홀수다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;number = 17

if number % 2 == 0:
    print(&quot;짝수&quot;)
else:
    print(&quot;홀수&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나머지는 반복되는 패턴을 만들 때도 유용하다. 예를 들어 요일은 7일마다 반복되고, 배열 인덱스는 길이를 넘으면 다시 처음으로 돌아가야 할 때가 있다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;days = [&quot;월&quot;, &quot;화&quot;, &quot;수&quot;, &quot;목&quot;, &quot;금&quot;, &quot;토&quot;, &quot;일&quot;]

today_index = 0
after_10_days = (today_index + 10) % 7

print(days[after_10_days])  # 목&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;7로 나눈 나머지&amp;rdquo;를 사용했기 때문에 0부터 6 사이의 인덱스 안에서만 결과가 나온다. 달력, 순번, 페이지, 슬라이드, 게임 캐릭터 위치처럼 반복 구조가 있는 곳에서 &lt;code&gt;%&lt;/code&gt;는 정말 자주 쓰인다.&lt;/p&gt;
&lt;div class=&quot;hb-warn hb-note-box&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;음수의 나머지는 언어마다 다를 수 있다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;양수끼리 계산할 때는 &lt;code&gt;%&lt;/code&gt;를 &amp;ldquo;나머지&amp;rdquo;라고 이해해도 거의 문제가 없다. 다만 음수가 들어가면 Python과 JavaScript 결과가 달라질 수 있다. 예를 들어 Python의 &lt;code&gt;-7 % 2&lt;/code&gt;는 &lt;code&gt;1&lt;/code&gt;이고, JavaScript의 &lt;code&gt;-7 % 2&lt;/code&gt;는 &lt;code&gt;-1&lt;/code&gt;이다. 좌표 이동, 회전, 순환 인덱스처럼 음수가 나올 수 있는 코드는 공식 문서를 확인하는 습관이 좋다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 몫과 나머지는 항상 한 세트로 생각하면 편하다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몫과 나머지는 따로 외우는 것보다 아래 관계로 묶어 이해하면 훨씬 쉽다.&lt;/p&gt;
&lt;div class=&quot;hb-formula&quot;&gt;원래 수 = 나누는 수 &amp;times; 몫 + 나머지&lt;br /&gt;10 = 3 &amp;times; 3 + 1&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Python에서는 이 관계가 그대로 코드로도 이어진다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;x = 10
y = 3

quotient = x // y
remainder = x % y

print(x == y * quotient + remainder)  # True&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몫과 나머지를 동시에 구하고 싶다면 Python에서는 &lt;code&gt;divmod()&lt;/code&gt;도 쓸 수 있다.&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;quotient, remainder = divmod(10, 3)

print(quotient)   # 3
print(remainder)  # 1&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;hb-green hb-note-box&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실전 감각으로 바꿔보기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람 5명에게 쿠키 23개를 나눠준다면 &lt;code&gt;23 // 5&lt;/code&gt;는 한 명당 받을 수 있는 쿠키 수이고, &lt;code&gt;23 % 5&lt;/code&gt;는 나누고 남는 쿠키 수다. 즉 몫은 &amp;ldquo;공평하게 몇 개씩?&amp;rdquo;, 나머지는 &amp;ldquo;그래도 남는 것은?&amp;rdquo;이라는 질문에 답한다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9. 연산자 우선순위: 컴퓨터도 계산 순서가 있다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드는 왼쪽에서 오른쪽으로만 계산되는 것이 아니다. 수학처럼 곱셈과 나눗셈이 덧셈과 뺄셈보다 먼저 계산된다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;print(2 + 3 * 4)    # 14
print((2 + 3) * 4)  # 20&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 순서는 대략 이렇게 기억하면 된다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;괄호 &lt;code&gt;()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;거듭제곱 &lt;code&gt;**&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;곱셈, 나눗셈, 몫, 나머지 &lt;code&gt;*&lt;/code&gt; &lt;code&gt;/&lt;/code&gt; &lt;code&gt;//&lt;/code&gt; &lt;code&gt;%&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;덧셈, 뺄셈 &lt;code&gt;+&lt;/code&gt; &lt;code&gt;-&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초보자에게 가장 좋은 습관은 애매하면 괄호를 쓰는 것이다. 컴퓨터가 알아서 해석하겠지 하고 맡기기보다, 내가 의도한 계산 순서를 코드에 드러내는 편이 유지보수에도 좋다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;total_price = (item_price * count) + delivery_fee
average_score = (math_score + english_score + coding_score) / 3&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;10. 실전 예제로 익히기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 1. 장바구니 총액 계산&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상품 가격과 개수를 곱하고, 배송비를 더하면 총 결제 금액이 된다. 가장 기본적인 덧셈과 곱셈 조합이다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;item_price = 15000
count = 2
delivery_fee = 3000

total = item_price * count + delivery_fee

print(total)  # 33000&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 2. 회비를 나눠 내기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 금액을 인원수로 나누면 1인당 금액이 나온다. 원 단위로 딱 떨어지지 않으면 몫과 나머지를 함께 봐야 한다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;total_fee = 10000
people = 3

each = total_fee // people
left = total_fee % people

print(each)  # 3333
print(left)  # 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우 한 사람당 3,333원씩 내면 1원이 남는다. 실제 서비스라면 남은 1원을 누가 부담할지 정책을 정해야 한다. 코딩에서 산술 연산은 단순 계산으로 끝나지 않고, 이렇게 서비스 규칙과 연결된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 3. 게시글 페이지 수 계산&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게시글이 53개 있고 한 페이지에 10개씩 보여준다면 몇 페이지가 필요할까? 일반 나눗셈으로는 5.3이지만, 실제 화면에는 6페이지가 필요하다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;import math

total_posts = 53
page_size = 10

pages = math.ceil(total_posts / page_size)

print(pages)  # 6&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 몫만 구하면 안 된다. 5페이지까지는 50개를 보여주고, 남은 3개를 보여줄 6페이지가 필요하기 때문이다. 이런 경우에는 올림을 사용한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 4. 초를 분과 초로 바꾸기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;러닝 앱이나 타이머 앱을 만든다고 생각해보자. 125초를 &amp;ldquo;2분 5초&amp;rdquo;로 바꾸려면 몫과 나머지를 함께 쓰면 된다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;seconds = 125

minutes = seconds // 60
remaining_seconds = seconds % 60

print(minutes)            # 2
print(remaining_seconds)  # 5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 예제는 몫과 나머지가 왜 중요한지 가장 잘 보여준다. 몫은 완성된 분 단위이고, 나머지는 분으로 묶고 남은 초다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;11. 초보자가 자주 만나는 오류&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;0으로 나누기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 수를 0으로 나누는 계산은 성립하지 않는다. Python에서는 &lt;code&gt;ZeroDivisionError&lt;/code&gt;가 발생한다.&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;print(10 / 0)  # ZeroDivisionError&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 사용자 입력값이나 데이터 개수로 나눌 때는 0인지 먼저 확인해야 한다.&lt;/p&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;total = 100
count = 0

if count == 0:
    print(&quot;평균을 계산할 수 없습니다.&quot;)
else:
    print(total / count)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;소수 계산이 딱 맞지 않는 문제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터는 소수를 10진수 그대로 저장하지 못하는 경우가 있다. 그래서 아래처럼 예상과 조금 다른 결과가 나올 수 있다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;print(0.1 + 0.2)  # 0.30000000000000004&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것은 Python만의 문제가 아니라 많은 프로그래밍 언어에서 만나는 부동소수점 표현 문제다. 일반적인 화면 표시에서는 반올림해서 보여주면 되고, 돈 계산처럼 정확성이 중요한 경우에는 원 단위 정수로 저장하거나 Decimal 같은 별도 방식을 사용한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;반올림, 올림, 내림을 섞어 쓰는 문제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나눗셈 결과를 정수로 바꿀 때는 &amp;ldquo;어떤 방식으로 정수화할 것인지&amp;rdquo;를 분명히 해야 한다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;나눗셈 결과를 정수로 바꾸는 대표 방식&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;방식&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;의미&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;예시&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;어울리는 상황&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;버림&lt;/td&gt;
&lt;td&gt;소수 부분을 제거한다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;int(3.8) == 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;소수는 필요 없고 정수 부분만 쓸 때&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;내림&lt;/td&gt;
&lt;td&gt;더 작은 정수로 내린다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;math.floor(3.8) == 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;좌표, 구간, floor division 개념&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;올림&lt;/td&gt;
&lt;td&gt;더 큰 정수로 올린다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;math.ceil(3.1) == 4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;페이지 수, 필요한 박스 수 계산&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;반올림&lt;/td&gt;
&lt;td&gt;가까운 정수로 맞춘다.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;round(3.6) == 4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;평균 점수, 화면 표시&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;값을 업데이트할 때 생기는 헷갈림&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코딩에서는 기존 값에 어떤 값을 더해서 다시 저장하는 일이 아주 많다.&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;count = 0
count = count + 1

print(count)  # 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드는 수학 방정식이 아니다. &amp;ldquo;오른쪽을 먼저 계산한 뒤, 그 결과를 왼쪽 변수에 다시 넣는다&amp;rdquo;는 뜻이다. 같은 코드를 더 짧게 쓰면 이렇게 된다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;count += 1
total += price
stock -= 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;+=&lt;/code&gt;, &lt;code&gt;-=&lt;/code&gt;, &lt;code&gt;*=&lt;/code&gt;, &lt;code&gt;/=&lt;/code&gt; 같은 대입 연산자는 계산과 저장을 한 번에 표현한다. 반복문에서 카운트를 세거나, 장바구니 금액을 누적하거나, 재고를 줄일 때 자주 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript나 C 계열 언어에서는 &lt;code&gt;count++&lt;/code&gt;, &lt;code&gt;count--&lt;/code&gt;처럼 1씩 증가하거나 감소시키는 증감 연산자도 자주 보인다. Python에는 &lt;code&gt;++&lt;/code&gt; 연산자가 없으므로 &lt;code&gt;count += 1&lt;/code&gt;처럼 쓰면 된다. 처음에는 언어별 특수 문법보다 &lt;code&gt;count = count + 1&lt;/code&gt;의 의미를 정확히 이해하는 것이 먼저다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;12. 머릿속에 이렇게 정리하면 오래 간다&lt;/h2&gt;
&lt;div class=&quot;hb-answer&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;+&lt;/code&gt;&lt;/b&gt;: 숫자끼리는 더하고, 문자열끼리는 이어 붙인다. 계산 전 타입을 확인하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;-&lt;/code&gt;&lt;/b&gt;: 왼쪽에서 오른쪽을 뺀다. 순서가 바뀌면 결과도 바뀐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;*&lt;/code&gt;&lt;/b&gt;: 곱셈이다. Python에서는 문자열 반복에도 쓰일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;/&lt;/code&gt;&lt;/b&gt;: 나눗셈 결과를 소수까지 본다. Python에서는 정수끼리 나눠도 결과가 소수형이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;//&lt;/code&gt;&lt;/b&gt;: 몫을 구한다. Python에서는 floor division이라 음수 계산에서 주의가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;%&lt;/code&gt;&lt;/b&gt;: 나머지를 구한다. 짝수/홀수, 반복 패턴, 시간 변환, 페이지 계산에서 자주 쓴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;괄호&lt;/b&gt;: 계산 순서가 조금이라도 헷갈리면 괄호로 의도를 드러내자.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;13. 연습 문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 문제를 직접 손으로 예상해보고, 그다음 코드로 실행해보면 훨씬 빨리 익숙해진다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;code&gt;17 // 5&lt;/code&gt;와 &lt;code&gt;17 % 5&lt;/code&gt;의 결과는 무엇일까?&lt;/li&gt;
&lt;li&gt;초 367초를 &amp;ldquo;몇 분 몇 초&amp;rdquo;로 바꾸려면 어떤 연산자를 써야 할까?&lt;/li&gt;
&lt;li&gt;게시글 101개를 한 페이지에 20개씩 보여주려면 총 몇 페이지가 필요할까?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&quot;3&quot; + &quot;4&quot;&lt;/code&gt;와 &lt;code&gt;int(&quot;3&quot;) + int(&quot;4&quot;)&lt;/code&gt;의 결과는 어떻게 다를까?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2 + 3 * 4&lt;/code&gt;와 &lt;code&gt;(2 + 3) * 4&lt;/code&gt;의 결과가 다른 이유는 무엇일까?&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;hb-green hb-note-box&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정답 힌트&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번은 몫 3, 나머지 2다. 2번은 &lt;code&gt;// 60&lt;/code&gt;과 &lt;code&gt;% 60&lt;/code&gt;을 함께 쓰면 된다. 3번은 딱 나누어떨어지지 않는 남은 글이 있으므로 올림이 필요하다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;덧셈, 나눗셈, 몫, 나머지는 코딩 입문 초반에 배우지만, 실제로는 계속 다시 만나는 개념이다. 가격 계산, 평균 계산, 시간 변환, 페이지네이션, 짝수&amp;middot;홀수 판별, 반복 패턴 만들기까지 거의 모든 기본 프로그램에 들어간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 연산자 기호를 외우는 것보다 &amp;ldquo;이 계산에서 내가 원하는 결과가 소수인지, 몫인지, 나머지인지&amp;rdquo;를 먼저 묻는 습관이 더 중요하다. 그 질문에 답할 수 있으면 &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;//&lt;/code&gt;, &lt;code&gt;%&lt;/code&gt; 중 무엇을 써야 할지도 자연스럽게 보인다.&lt;/p&gt;
&lt;div class=&quot;hb-source&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고 자료&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Python Documentation: Binary arithmetic operations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_operators#arithmetic_operators&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MDN Web Docs: JavaScript arithmetic operators&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Division&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MDN Web Docs: Division operator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Remainder&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MDN Web Docs: Remainder operator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p class=&quot;hb-disclaimer&quot; data-ke-size=&quot;size16&quot;&gt;이 글은 코딩 입문자를 위한 학습용 글입니다. 언어마다 산술 연산자의 세부 동작이 조금씩 다를 수 있으므로, 실제 프로젝트에서는 사용 중인 언어의 공식 문서를 함께 확인하는 것이 좋습니다.&lt;/p&gt;
&lt;/article&gt;</description>
      <category>AI/Coding</category>
      <category>나눗셈</category>
      <category>나머지</category>
      <category>덧셈</category>
      <category>몫</category>
      <category>산술연산자</category>
      <category>자바스크립트기초</category>
      <category>초보개발자</category>
      <category>코딩기초</category>
      <category>파이썬기초</category>
      <category>프로그래밍기초</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/94</guid>
      <comments>https://onethingflow.tistory.com/entry/%EC%BD%94%EB%94%A9%EC%9D%98-%EB%8D%A7%EC%85%88%C2%B7%EB%82%98%EB%88%97%EC%85%88%C2%B7%EB%AA%AB%C2%B7%EB%82%98%EB%A8%B8%EC%A7%80-%EC%99%84%EC%A0%84-%EA%B8%B0%EC%B4%88-%EC%B4%88%EB%B3%B4%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%82%B0%EC%88%A0-%EC%97%B0%EC%82%B0%EC%9E%90-%EC%84%A4%EB%AA%85#entry94comment</comments>
      <pubDate>Tue, 9 Jun 2026 17:14:29 +0900</pubDate>
    </item>
    <item>
      <title>10km 51분에서 45분 완주로: 2026 서울런 D-20 훈련 계획</title>
      <link>https://onethingflow.tistory.com/entry/10km-51%EB%B6%84%EC%97%90%EC%84%9C-45%EB%B6%84-%EC%99%84%EC%A3%BC%EB%A1%9C-2026-%EC%84%9C%EC%9A%B8%EB%9F%B0-D-20-%ED%9B%88%EB%A0%A8-%EA%B3%84%ED%9A%8D</link>
      <description>&lt;style&gt;
.hb-post{max-width:760px;margin:0 auto;line-height:1.85;font-size:17px;color:#222;word-break:keep-all;}
.hb-post h2{margin:2.4em 0 .7em;font-size:1.32em;line-height:1.4;font-weight:700;padding-bottom:.35em;border-bottom:2px solid #eee;}
.hb-post h3{margin:1.8em 0 .5em;font-size:1.1em;font-weight:700;}
.hb-post p{margin:0 0 1.15em;}
.hb-post strong{font-weight:700;}
.hb-post .hb-lead{font-size:1.06em;color:#333;}
.hb-post .hb-note-box{background:#f7f9fc;border:1px solid #e3e9f2;border-left:4px solid #4a7dff;border-radius:8px;padding:1.1em 1.3em;margin:1.6em 0;}
.hb-post .hb-note-box p{margin:0 0 .6em;}
.hb-post .hb-note-box p:last-child{margin-bottom:0;}
.hb-post blockquote.hb-pull{margin:1.6em 0;padding:.9em 1.2em;background:#fff8e6;border-left:4px solid #f5b301;border-radius:6px;font-size:1.08em;font-weight:600;color:#5a4500;}
.hb-post ul,.hb-post ol{margin:0 0 1.2em;padding-left:1.4em;}
.hb-post ul li{list-style:disc;}
.hb-post ol li{list-style:decimal;}
.hb-post li{margin:.42em 0;}
.hb-post .hb-table-wrap{overflow-x:auto;margin:1.6em 0;-webkit-overflow-scrolling:touch;}
.hb-post table{border-collapse:collapse;width:100%;font-size:.94em;min-width:720px;}
.hb-post th,.hb-post td{border:1px solid #e2e5e9;padding:.72em .82em;text-align:left;vertical-align:top;}
.hb-post thead th{background:#f2f4f7;font-weight:700;}
.hb-post tbody tr:nth-child(even){background:#fafbfc;}
.hb-post caption{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);}
.hb-post .hb-kpi{display:grid;grid-template-columns:repeat(3,1fr);gap:.8em;margin:1.5em 0;}
.hb-post .hb-kpi div{background:#fbfbfb;border:1px solid #e8e8e8;border-radius:8px;padding:1em;}
.hb-post .hb-kpi span{display:block;font-size:.82em;color:#666;margin-bottom:.25em;}
.hb-post .hb-kpi strong{display:block;font-size:1.2em;color:#111;}
.hb-post .hb-answer{background:#fbfbfb;border:1px solid #ededed;border-radius:8px;padding:1.1em 1.3em;margin:1.5em 0;}
.hb-post .hb-answer strong{color:#1f3b73;}
.hb-post .hb-disclaimer{margin-top:1.6em;font-size:.88em;color:#888;}
@media (max-width:640px){
  .hb-post{font-size:16px;}
  .hb-post .hb-kpi{grid-template-columns:1fr;}
  .hb-post table{font-size:.9em;min-width:780px;}
}
&lt;/style&gt;

&lt;article class=&quot;hb-post&quot;&gt;
  &lt;p class=&quot;hb-lead&quot;&gt;2026년 6월 28일 오전 8시, 여의도공원 문화의마당에서 열리는 2026 서울런까지 20일 남았다. 현재 내 10km 기록은 51분 16초, 평균 페이스는 5분 07초/km다. 목표는 45분. 숫자로 보면 1km마다 약 38초를 줄여야 한다.&lt;/p&gt;

  &lt;p&gt;20일 만에 10km 기록을 6분 이상 줄이는 건 여유 있는 목표가 아니다. 그래서 이번 글에서는 중간 목표를 따로 두지 않고, 처음부터 45분 완주를 기준으로 모든 훈련을 역산한다. 핵심은 하루 2번 훈련하되, 아침에 본훈련을 하고 저녁에는 회복 조깅이나 스트레칭으로 가볍게 마무리하는 것이다.&lt;/p&gt;

  &lt;div class=&quot;hb-kpi&quot;&gt;
    &lt;div&gt;
      &lt;span&gt;현재 기록&lt;/span&gt;
      &lt;strong&gt;10km 51:16&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div&gt;
      &lt;span&gt;현재 평균 페이스&lt;/span&gt;
      &lt;strong&gt;5:07/km&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div&gt;
      &lt;span&gt;목표 기록&lt;/span&gt;
      &lt;strong&gt;10km 45:00&lt;/strong&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;blockquote class=&quot;hb-pull&quot;&gt;목표 페이스는 4분 30초/km다. 이번 20일은 체력을 새로 만드는 기간이 아니라, 이미 가진 체력을 10km 레이스 페이스로 끌어올리는 기간이다.&lt;/blockquote&gt;

  &lt;div class=&quot;hb-note-box&quot;&gt;
    &lt;p&gt;&lt;strong&gt;이 글의 전제&lt;/strong&gt;&lt;/p&gt;
    &lt;p&gt;목표는 “45분에 가까운 기록”이 아니라 &lt;strong&gt;10km 45분 완주&lt;/strong&gt;다. 훈련표도 4분 30초/km를 몸에 익히는 방향으로 짠다. 다만 45분을 망치는 가장 큰 변수는 부상이기 때문에, 강훈련을 무작정 늘리지 않고 필요한 자극만 정확히 넣는다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2&gt;1. 목표를 페이스로 쪼개기&lt;/h2&gt;

  &lt;p&gt;10km 45분은 단순히 “조금 빨리 뛰자”가 아니다. 현재 5분 07초/km에서 목표 4분 30초/km로 내려가야 한다. 한 번에 4분 30초 페이스로 10km를 밀어붙이려 하면 초반 3km 안에 무너질 가능성이 높다.&lt;/p&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;현재 기록과 목표 기록 비교&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;구분&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;기록&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;평균 페이스&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;의미&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;현재&lt;/td&gt;
          &lt;td&gt;51분 16초&lt;/td&gt;
          &lt;td&gt;5분 07초/km&lt;/td&gt;
          &lt;td&gt;이미 10km 완주 능력은 충분하다. 이제 속도 유지력이 핵심이다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;목표&lt;/td&gt;
          &lt;td&gt;45분 00초&lt;/td&gt;
          &lt;td&gt;4분 30초/km&lt;/td&gt;
          &lt;td&gt;현재보다 km당 약 38초 빠르게 뛰어야 한다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;차이&lt;/td&gt;
          &lt;td&gt;6분 16초 단축&lt;/td&gt;
          &lt;td&gt;약 12.2% 향상&lt;/td&gt;
          &lt;td&gt;여유 있는 목표가 아니다. 부상 없이 컨디션을 끌어올리는 운영이 필요하다.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;p&gt;그래서 훈련은 다섯 가지 페이스로 나눈다. 쉬운 날은 확실히 천천히 뛰고, 강한 날은 목표 페이스보다 빠른 구간을 짧게 반복한다. 10km는 스프린트가 아니라 “빠른 페이스를 버티는 능력”의 경기이기 때문이다.&lt;/p&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;훈련 페이스 기준&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;훈련 구분&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;권장 페이스&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;목적&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;회복 조깅&lt;/td&gt;
          &lt;td&gt;6:10-6:40/km&lt;/td&gt;
          &lt;td&gt;다리 피로를 빼고 다음 강훈련을 살린다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;이지런&lt;/td&gt;
          &lt;td&gt;5:45-6:20/km&lt;/td&gt;
          &lt;td&gt;심폐 기반을 유지한다. 숨이 차면 너무 빠른 것이다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;템포런&lt;/td&gt;
          &lt;td&gt;4:40-4:55/km&lt;/td&gt;
          &lt;td&gt;10km 후반에 무너지지 않는 역치 능력을 만든다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;목표 페이스&lt;/td&gt;
          &lt;td&gt;4:30/km&lt;/td&gt;
          &lt;td&gt;대회 당일 몸이 기억해야 할 정확한 리듬이다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;인터벌&lt;/td&gt;
          &lt;td&gt;4:05-4:20/km&lt;/td&gt;
          &lt;td&gt;목표 페이스를 상대적으로 편하게 느끼게 만든다.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;2. 하루 2번 훈련의 원칙&lt;/h2&gt;

  &lt;p&gt;하루 2번 훈련은 기록 단축에 도움이 될 수 있지만, 잘못하면 20일 안에 컨디션이 망가진다. 그래서 이번 계획은 아침에 본훈련을 배치하고, 저녁에는 회복 목적의 짧은 조깅이나 스트레칭만 한다. 몸이 가장 신선할 때 인터벌, 템포런, 레이스페이스런을 끝내고, 저녁은 다음 날 훈련을 살리는 시간으로 쓰는 구조다.&lt;/p&gt;

  &lt;div class=&quot;hb-note-box&quot;&gt;
    &lt;p&gt;&lt;strong&gt;운영 원칙&lt;/strong&gt;&lt;/p&gt;
    &lt;p&gt;아침: 인터벌, 템포런, 레이스페이스런, 롱런처럼 기록에 직접 연결되는 본훈련을 한다.&lt;/p&gt;
    &lt;p&gt;저녁: 2-4km 회복 조깅, 산책, 스트레칭, 코어 10분처럼 가볍게 끝낸다.&lt;/p&gt;
    &lt;p&gt;저녁 훈련의 목적은 체력을 더 쓰는 것이 아니라, 다리를 풀고 다음 날 훈련 품질을 살리는 것이다.&lt;/p&gt;
    &lt;p&gt;수면이 6시간 미만이거나, 통증이 10점 만점에 4점 이상이면 저녁 훈련은 쉰다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;p&gt;특히 무릎, 아킬레스건, 종아리, 발바닥 통증은 가볍게 넘기면 안 된다. 숨이 찬 것과 관절이나 힘줄이 아픈 것은 다르다. 통증이 뛰면서 더 심해지면 그날은 훈련 성공이 아니라 실패로 봐야 한다.&lt;/p&gt;

  &lt;h2&gt;3. 6월 9일부터 6월 28일까지 수정 훈련 계획&lt;/h2&gt;

  &lt;p&gt;아래 계획은 2026년 6월 9일 화요일부터 대회 당일인 6월 28일 일요일까지의 일정이다. 첫 2주는 아침 본훈련으로 인터벌, 템포런, 주 1회 10km 리허설, 롱런을 반복해 4분 30초/km 리듬에 적응한다. 저녁에는 회복 조깅이나 산책만 넣는다. 마지막 주는 더 강해지는 주간이 아니라 피로를 빼고 다리를 가볍게 만드는 테이퍼 주간이다.&lt;/p&gt;

  &lt;h3&gt;1주차: 6월 9일 화요일 - 6월 14일 일요일&lt;/h3&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;2026 서울런 10km 45분 달성형 1주차 훈련 계획&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;날짜&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;오전&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;저녁&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;포인트&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;6/9 화&lt;br&gt;D-19&lt;/td&gt;
          &lt;td&gt;인터벌&lt;br&gt;2km 워밍업&lt;br&gt;1km x 5회, 4:10-4:20/km&lt;br&gt;1km 쿨다운&lt;/td&gt;
          &lt;td&gt;3km 회복조깅&lt;br&gt;스트레칭&lt;/td&gt;
          &lt;td&gt;목표 페이스보다 빠른 구간을 익힌다. 1km 반복은 전력질주가 아니라 통제된 속도다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;6/10 수&lt;br&gt;D-18&lt;/td&gt;
          &lt;td&gt;5km 회복런, 6:10-6:40/km&lt;/td&gt;
          &lt;td&gt;4km 회복런&lt;br&gt;스트레칭&lt;/td&gt;
          &lt;td&gt;전날 인터벌 피로를 빼는 날. 느리게 뛰는 것이 훈련이다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;6/11 목&lt;br&gt;D-17&lt;/td&gt;
          &lt;td&gt;템포런&lt;br&gt;2km 워밍업&lt;br&gt;5km, 4:45-4:55/km&lt;br&gt;1km 쿨다운&lt;/td&gt;
          &lt;td&gt;3km 아주 가볍게&lt;/td&gt;
          &lt;td&gt;10km 후반에 버티는 역치 페이스를 만든다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;6/12 금&lt;br&gt;D-16&lt;/td&gt;
          &lt;td&gt;4km 회복런&lt;br&gt;코어 10분&lt;/td&gt;
          &lt;td&gt;4km 회복런&lt;/td&gt;
          &lt;td&gt;강도를 낮추고 몸을 정리한다. 코어는 짧게만 한다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;6/13 토&lt;br&gt;D-15&lt;/td&gt;
          &lt;td&gt;10km 리허설 1차&lt;br&gt;1km 4:35/km&lt;br&gt;2-7km 4:30-4:35/km&lt;br&gt;8-10km 가능한 만큼 4:30/km 근처 유지&lt;/td&gt;
          &lt;td&gt;산책 20-30분 또는 완전 휴식&lt;/td&gt;
          &lt;td&gt;주 1회 10km 리허설. 목표는 45분 페이스 운영을 몸에 넣는 것이다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;6/14 일&lt;br&gt;D-14&lt;/td&gt;
          &lt;td&gt;10-12km 이지 롱런, 5:50-6:30/km&lt;/td&gt;
          &lt;td&gt;2-3km 회복조깅 또는 산책&lt;/td&gt;
          &lt;td&gt;전날 10km 리허설 피로를 고려해 거리를 줄인다. 빠르게 뛰지 않는다.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h3&gt;2주차: 6월 15일 월요일 - 6월 21일 일요일&lt;/h3&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;2026 서울런 10km 45분 달성형 2주차 훈련 계획&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;날짜&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;오전&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;저녁&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;포인트&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;6/15 월&lt;br&gt;D-13&lt;/td&gt;
          &lt;td&gt;5km 회복런&lt;/td&gt;
          &lt;td&gt;4km 회복런&lt;/td&gt;
          &lt;td&gt;월요일은 욕심내지 않는다. 화요일 강훈련을 살리는 날이다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;6/16 화&lt;br&gt;D-12&lt;/td&gt;
          &lt;td&gt;인터벌&lt;br&gt;2km 워밍업&lt;br&gt;1km x 6회, 4:10-4:18/km&lt;br&gt;1km 쿨다운&lt;/td&gt;
          &lt;td&gt;3km 회복조깅&lt;br&gt;스트레칭&lt;/td&gt;
          &lt;td&gt;가장 중요한 속도 지구력 훈련이다. 5회가 아니라 6회까지 버티는 것이 포인트다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;6/17 수&lt;br&gt;D-11&lt;/td&gt;
          &lt;td&gt;5km 회복런&lt;/td&gt;
          &lt;td&gt;4km 회복런&lt;/td&gt;
          &lt;td&gt;회복런은 페이스 자존심을 버리는 날이다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;6/18 목&lt;br&gt;D-10&lt;/td&gt;
          &lt;td&gt;템포런&lt;br&gt;2km 워밍업&lt;br&gt;6km, 4:40-4:50/km&lt;br&gt;1km 쿨다운&lt;/td&gt;
          &lt;td&gt;3km 아주 가볍게&lt;/td&gt;
          &lt;td&gt;2주차 핵심 템포런. 숨은 차지만 무너지지 않는 강도로 끝낸다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;6/19 금&lt;br&gt;D-9&lt;/td&gt;
          &lt;td&gt;4km 회복런&lt;br&gt;가벼운 보강&lt;/td&gt;
          &lt;td&gt;4km 회복런&lt;/td&gt;
          &lt;td&gt;보강은 짧게. 다음 날 레이스페이스런에 피로를 남기지 않는다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;6/20 토&lt;br&gt;D-8&lt;/td&gt;
          &lt;td&gt;10km 최종 리허설&lt;br&gt;1km 4:35/km&lt;br&gt;2-4km 4:30/km&lt;br&gt;5-7km 4:28-4:30/km&lt;br&gt;8-9km 4:25-4:28/km&lt;br&gt;마지막 1km 버티기&lt;/td&gt;
          &lt;td&gt;완전 휴식&lt;/td&gt;
          &lt;td&gt;가장 중요한 모의고사다. 대회 페이스 전략을 그대로 리허설한다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;6/21 일&lt;br&gt;D-7&lt;/td&gt;
          &lt;td&gt;10-12km 이지 롱런, 5:55-6:30/km&lt;/td&gt;
          &lt;td&gt;산책 또는 2km 회복조깅&lt;/td&gt;
          &lt;td&gt;마지막 긴 거리지만 전날 10km 리허설 다음 날이다. 피로를 남기지 않고 끝낸다.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h3&gt;대회 주간: 6월 22일 월요일 - 6월 28일 일요일&lt;/h3&gt;

  &lt;p&gt;대회 주간의 목적은 체력을 더 만드는 것이 아니다. 이미 만든 자극을 몸에 남긴 채 피로만 빼는 주간이다. 강한 운동을 너무 자주 넣으면 회복 부족으로 피로와 통증이 쌓일 수 있다.&lt;/p&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;2026 서울런 10km 45분 달성형 대회 주간 훈련 계획&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;날짜&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;오전&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;저녁&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;포인트&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;6/22 월&lt;br&gt;D-6&lt;/td&gt;
          &lt;td&gt;4km 회복런&lt;/td&gt;
          &lt;td&gt;3km 회복런&lt;br&gt;스트레칭&lt;/td&gt;
          &lt;td&gt;테이퍼 시작. 가볍게 움직이고 피로를 뺀다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;6/23 화&lt;br&gt;D-5&lt;/td&gt;
          &lt;td&gt;마지막 인터벌&lt;br&gt;2km 워밍업&lt;br&gt;800m x 4회, 4:05-4:15/km&lt;br&gt;1km 쿨다운&lt;/td&gt;
          &lt;td&gt;3km 회복조깅&lt;/td&gt;
          &lt;td&gt;짧고 날카롭게 끝낸다. 절대 올아웃하지 않는다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;6/24 수&lt;br&gt;D-4&lt;/td&gt;
          &lt;td&gt;4km 회복런&lt;/td&gt;
          &lt;td&gt;3km 회복런 또는 산책&lt;/td&gt;
          &lt;td&gt;다리가 가벼워지는지 확인하는 날이다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;6/25 목&lt;br&gt;D-3&lt;/td&gt;
          &lt;td&gt;마지막 레이스페이스 감각&lt;br&gt;1.5km 워밍업&lt;br&gt;3km @ 4:30/km&lt;br&gt;1km 쿨다운&lt;/td&gt;
          &lt;td&gt;산책 또는 완전 휴식&lt;/td&gt;
          &lt;td&gt;4분 30초/km 리듬만 확인한다. 힘을 다 쓰면 안 된다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;6/26 금&lt;br&gt;D-2&lt;/td&gt;
          &lt;td&gt;2-3km 아주 가볍게&lt;/td&gt;
          &lt;td&gt;완전 휴식&lt;br&gt;스트레칭&lt;/td&gt;
          &lt;td&gt;컨디션을 쌓는 날. 불안해서 더 뛰지 않는다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;6/27 토&lt;br&gt;D-1&lt;/td&gt;
          &lt;td&gt;완전 휴식 또는 15분 조깅&lt;/td&gt;
          &lt;td&gt;완전 휴식&lt;/td&gt;
          &lt;td&gt;새로운 운동, 새로운 음식, 새로운 신발은 금지다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;6/28 일&lt;br&gt;D-Day&lt;/td&gt;
          &lt;td&gt;대회 워밍업&lt;br&gt;10km 경기&lt;/td&gt;
          &lt;td&gt;회복&lt;/td&gt;
          &lt;td&gt;초반 오버페이스만 막으면 45분 성공 확률이 가장 높아진다.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;h2&gt;4. 10km 리허설과 인터벌 선택&lt;/h2&gt;

  &lt;p&gt;이번 계획에서는 10km 리허설을 주 1회 필수로 넣는다. 이유는 단순하다. 목표가 10km 45분이면, 몸이 실제로 10km 전체를 어떻게 버티는지 알아야 한다. 1km 인터벌이나 템포런만 잘해도 실제 10km에서 7km 이후 무너질 수 있기 때문이다.&lt;/p&gt;

  &lt;div class=&quot;hb-note-box&quot;&gt;
    &lt;p&gt;&lt;strong&gt;10km 리허설 운영&lt;/strong&gt;&lt;/p&gt;
    &lt;p&gt;6월 13일은 1차 리허설이다. 1km를 4:35/km로 참고, 2-7km를 4:30-4:35/km로 붙이고, 8-10km는 가능한 만큼 4:30/km 근처를 유지한다.&lt;/p&gt;
    &lt;p&gt;6월 20일은 최종 리허설이다. 대회 당일 페이스 전략과 거의 똑같이 운영한다. 1km 4:35/km, 2-4km 4:30/km, 5-7km 4:28-4:30/km, 8-9km 4:25-4:28/km, 마지막 1km는 버티는 방식이다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;p&gt;대신 10km 리허설을 넣는 주에는 다음 날 롱런을 과하게 가져가지 않는다. 10km 리허설 자체가 이미 강한 본훈련이기 때문이다. 그래서 6월 14일과 6월 21일의 롱런은 10-12km 이지런으로 낮춘다. 여기서 욕심내면 리허설 효과보다 피로 누적이 더 커진다.&lt;/p&gt;

  &lt;p&gt;400m 인터벌과 1km 인터벌도 목적이 다르다. 400m는 빠른 다리 회전, 러닝 폼, 속도감을 만드는 데 좋다. 짧아서 부담이 적고, 목표 페이스보다 빠른 움직임을 익히기 쉽다. 대신 10km에서 필요한 “4분 30초/km 근처를 오래 버티는 능력”은 상대적으로 덜 만든다.&lt;/p&gt;

  &lt;p&gt;반대로 1km 인터벌은 10km 기록 단축에 더 직접적이다. 1km를 4분 10초-4분 20초로 반복하면 목표 페이스보다 빠른 속도를 꽤 긴 시간 유지해야 한다. 그래서 심폐, 리듬, 후반 버티는 감각이 실제 10km와 더 잘 연결된다.&lt;/p&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;400m 인터벌과 1km 인터벌 비교&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;훈련&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;장점&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;이번 목표에서의 역할&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;400m 인터벌&lt;/td&gt;
          &lt;td&gt;속도감, 가벼운 다리 회전, 러닝 이코노미를 만들기 좋다.&lt;/td&gt;
          &lt;td&gt;보조 훈련으로 좋다. 하지만 지금은 이것만으로 10km 45분을 만들기 어렵다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;1km 인터벌&lt;/td&gt;
          &lt;td&gt;목표 페이스보다 빠른 속도를 오래 버티는 능력을 만든다.&lt;/td&gt;
          &lt;td&gt;이번 20일 계획의 핵심이다. 10km 45분 목표에는 1km 반복이 더 직접적이다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;800m 인터벌&lt;/td&gt;
          &lt;td&gt;1km보다 부담은 낮고 400m보다 지속 시간이 길다.&lt;/td&gt;
          &lt;td&gt;대회 주간 마지막 자극으로 적합하다. 그래서 6월 23일에 800m x 4회를 넣는다.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;p&gt;정리하면, 지금 시점에서는 400m 인터벌보다 1km 인터벌이 우선이다. 400m는 완전히 나쁜 훈련이 아니라, 보조 자극으로 좋은 훈련이다. 하지만 10km 45분을 만들려면 “빠르게 움직이는 능력”보다 “빠른 페이스를 계속 붙잡는 능력”이 더 중요하다.&lt;/p&gt;

  &lt;h2&gt;5. 레이스 당일 페이스 전략&lt;/h2&gt;

  &lt;p&gt;45분을 노릴 때 가장 위험한 실수는 1km를 4분 15초로 들어가는 것이다. 처음에는 몸이 가볍고 주변 사람들 때문에 속도가 쉽게 올라간다. 하지만 10km는 7km 이후가 진짜다. 첫 1km는 4분 35초/km로 억제하고, 2km부터 4분 30초/km 리듬에 들어가는 방식이 가장 현실적이다.&lt;/p&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;10km 45분 목표 레이스 운영&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;구간&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;목표 페이스&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;체감&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;1km&lt;/td&gt;
          &lt;td&gt;4:35/km&lt;/td&gt;
          &lt;td&gt;무조건 참는다. 주변 페이스에 끌려가지 않는다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;2-4km&lt;/td&gt;
          &lt;td&gt;4:30/km&lt;/td&gt;
          &lt;td&gt;목표 리듬에 들어간다. 호흡과 팔치기를 일정하게 유지한다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;5-7km&lt;/td&gt;
          &lt;td&gt;4:28-4:30/km&lt;/td&gt;
          &lt;td&gt;가장 중요한 유지 구간이다. 여기서 무리하게 올리지 않는다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;8-9km&lt;/td&gt;
          &lt;td&gt;4:25-4:28/km&lt;/td&gt;
          &lt;td&gt;남은 힘을 쓰기 시작한다. 자세가 무너지지 않는 선에서 올린다.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;마지막 1km&lt;/td&gt;
          &lt;td&gt;남은 힘 전부&lt;/td&gt;
          &lt;td&gt;기록을 계산하지 말고 끝까지 밀어붙인다.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;p&gt;6월 말 오전 8시는 이미 덥고 습할 수 있다. 체감 온도가 높으면 45분 페이스가 더 어렵다. 그날 날씨가 습하고 바람이 없으면 초반 2km는 4분 35초/km로 더 보수적으로 들어가는 편이 낫다.&lt;/p&gt;

  &lt;h2&gt;6. 보강 운동은 짧고 꾸준하게&lt;/h2&gt;

  &lt;p&gt;20일 남은 시점에서 웨이트를 갑자기 늘리는 건 좋지 않다. 목표는 근육을 키우는 것이 아니라, 달릴 때 골반과 발목이 무너지지 않게 만드는 것이다. 보강은 10-30분이면 충분하고, 다음 날 다리가 무거워질 정도로 하면 안 된다.&lt;/p&gt;

  &lt;div class=&quot;hb-answer&quot;&gt;
    &lt;p&gt;&lt;strong&gt;코어&lt;/strong&gt;: 플랭크 40초 3세트, 사이드 플랭크 30초 2세트, 데드버그 10회 2세트&lt;/p&gt;
    &lt;p&gt;&lt;strong&gt;하체&lt;/strong&gt;: 스쿼트 12회 2세트, 런지 10회 2세트, 카프레이즈 20회 3세트&lt;/p&gt;
    &lt;p&gt;&lt;strong&gt;러닝 드릴&lt;/strong&gt;: 스킵, 버트킥, 하이니를 각각 20m씩 2-3회. 인터벌 전에만 가볍게 한다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;p&gt;보강 후 다음 날 다리가 무거우면 강도가 과한 것이다. 이 기간에는 근육통을 만드는 보강보다, 달릴 때 자세를 안정시키는 보강이 더 가치 있다.&lt;/p&gt;

  &lt;h2&gt;7. 식사와 회복&lt;/h2&gt;

  &lt;p&gt;기록을 줄이겠다고 탄수화물을 줄이면 훈련 품질이 바로 떨어진다. 인터벌이나 템포런이 있는 날은 운동 2-3시간 전에 밥, 바나나, 식빵처럼 소화가 쉬운 탄수화물을 먹는다. 운동 후에는 1시간 안에 탄수화물과 단백질을 같이 넣어준다.&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;강훈련 전: 공복으로 하지 않는다. 최소 바나나나 식빵 한 조각은 먹는다.&lt;/li&gt;
    &lt;li&gt;강훈련 후: 단백질만 먹지 말고 밥, 빵, 과일 같은 탄수화물을 함께 먹는다.&lt;/li&gt;
    &lt;li&gt;대회 전날: 새로운 음식 금지. 평소 잘 맞는 식사로 간다.&lt;/li&gt;
    &lt;li&gt;대회 당일: 출발 2-3시간 전에 가볍게 먹고, 물은 조금씩 나눠 마신다.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;p&gt;수면은 훈련의 일부다. 하루 2번 운동을 하려면 밤에 회복해야 한다. 수면이 부족한 상태에서 인터벌을 억지로 하면 심폐보다 종아리와 아킬레스건이 먼저 망가진다.&lt;/p&gt;

  &lt;h2&gt;8. 내가 지킬 체크리스트&lt;/h2&gt;

  &lt;p&gt;이번 20일 계획은 열심히 하는 것보다 정확히 하는 것이 중요하다. 아래 체크리스트를 매일 확인한다.&lt;/p&gt;

  &lt;ol&gt;
    &lt;li&gt;강훈련은 주 3회를 넘기지 않는다.&lt;/li&gt;
    &lt;li&gt;저녁 두 번째 훈련은 회복 목적이다. 빠르게 뛰지 않는다.&lt;/li&gt;
    &lt;li&gt;통증이 뛰면서 커지면 즉시 중단한다.&lt;/li&gt;
    &lt;li&gt;인터벌은 전력질주가 아니라 목표보다 빠른 페이스를 반복하는 훈련이다.&lt;/li&gt;
    &lt;li&gt;대회 6일 전부터는 훈련량을 줄이고 몸을 가볍게 만든다.&lt;/li&gt;
    &lt;li&gt;대회 당일 첫 1km는 무조건 참는다.&lt;/li&gt;
  &lt;/ol&gt;

  &lt;p&gt;이 계획의 기준은 끝까지 45분이다. 지금 필요한 건 막연한 의지가 아니라, 매일 어떤 자극을 넣고 어떤 피로를 빼야 하는지 아는 것이다. 6월 28일까지 남은 20일 동안은 “더 많이”보다 “정확하게” 간다. 아침에는 본훈련으로 필요한 자극을 넣고, 저녁에는 회복을 쌓는다. 그렇게 출발선에 섰을 때 4분 30초/km 페이스가 낯설지 않게 만드는 것이 이번 계획의 목적이다.&lt;/p&gt;

  &lt;p class=&quot;hb-disclaimer&quot;&gt;이 글은 개인 러닝 목표를 위한 훈련 계획 기록입니다. 기존 질환, 부상 이력, 흉통, 어지러움, 비정상적인 통증이 있다면 훈련을 중단하고 전문가 상담을 우선해야 합니다.&lt;/p&gt;
&lt;/article&gt;</description>
      <category>Exercise/running</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/93</guid>
      <comments>https://onethingflow.tistory.com/entry/10km-51%EB%B6%84%EC%97%90%EC%84%9C-45%EB%B6%84-%EC%99%84%EC%A3%BC%EB%A1%9C-2026-%EC%84%9C%EC%9A%B8%EB%9F%B0-D-20-%ED%9B%88%EB%A0%A8-%EA%B3%84%ED%9A%8D#entry93comment</comments>
      <pubDate>Tue, 9 Jun 2026 08:00:11 +0900</pubDate>
    </item>
    <item>
      <title>콘서트 티켓 예매 시스템에서 Overbooking을 막는 백엔드 설계 사고</title>
      <link>https://onethingflow.tistory.com/entry/%EC%BD%98%EC%84%9C%ED%8A%B8-%ED%8B%B0%EC%BC%93-%EC%98%88%EB%A7%A4-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90%EC%84%9C-Overbooking%EC%9D%84-%EB%A7%89%EB%8A%94-%EB%B0%B1%EC%97%94%EB%93%9C-%EC%84%A4%EA%B3%84-%EC%82%AC%EA%B3%A0</link>
      <description>&lt;p style=&quot;color: #333333;&quot; data-ke-size=&quot;size16&quot;&gt;인기 아이돌 콘서트 티켓 예매 시스템은 단순히 서버를 많이 띄운다고 해결되지 않는다. 오픈 직후 1분 동안 10만 명이 동시에 들어오고 좌석은 1만 석뿐이라면, 진짜 문제는 &amp;ldquo;많은 요청을 받는 것&amp;rdquo;보다 &amp;ldquo;같은 좌석이나 같은 재고가 두 번 팔리지 않게 하는 것&amp;rdquo;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글은 엔지니어링 문제 해결 능력 진단 과제의 &lt;b&gt;Scenario B, 콘서트 티켓 예매 시스템&lt;/b&gt;을 선택해 작성한 답변이다. 코드를 나열하기보다, 어떤 기술적 문제가 핵심인지, 어떤 요구사항을 먼저 세워야 하는지, 그리고 DB Lock, Redis, 메시지 큐 같은 선택지가 어떤 Trade-off를 갖는지 중심으로 정리했다.&lt;/p&gt;
&lt;div style=&quot;background-color: #f7f9fc;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;상황 요약&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오픈 1분 만에 10만 명의 동시 접속이 예상된다. 좌석은 1만 석 한정이다. 사용자가 &amp;ldquo;예매하기&amp;rdquo;를 누를 때 재고 중복 차감 없이 정확히 1만 명까지만 티켓을 판매해야 한다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 문제의 핵심: 대량 트래픽 속 재고 정합성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 시나리오에서 해결해야 할 핵심 기술 문제는 &lt;b&gt;동시성 경쟁 상황에서 한정된 자원을 정확히 한 번만 배정하는 것&lt;/b&gt;이다. 사용자가 많다는 사실만 보면 트래픽 처리 문제처럼 보이지만, 실제로는 &amp;ldquo;재고를 읽고, 차감하고, 예약을 생성하는 과정&amp;rdquo;이 동시에 실행될 때 생기는 Race Condition이 더 위험하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 남은 좌석이 1석인 순간 두 요청이 거의 동시에 들어왔다고 하자. 두 요청이 모두 &amp;ldquo;남은 좌석 1석&amp;rdquo;을 읽은 뒤 각각 주문을 생성하면, 시스템은 실제 좌석보다 많은 티켓을 판매하게 된다. 이것이 Overbooking이다.&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fff8e6; color: #5a4500;&quot; data-ke-style=&quot;style1&quot;&gt;핵심은 &amp;ldquo;10만 요청을 모두 빠르게 성공시키는 것&amp;rdquo;이 아니라, &amp;ldquo;성공 가능한 1만 요청만 일관된 기준으로 통과시키고 나머지는 안전하게 거절하거나 대기시키는 것&amp;rdquo;이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 하나 중요한 점은 결제와 예매가 외부 시스템까지 포함한다는 것이다. DB 트랜잭션은 롤백할 수 있지만, 결제 승인 요청처럼 외부 PG사로 나간 부수 효과는 같은 방식으로 되돌리기 어렵다. 따라서 티켓 예매 시스템은 재고 차감뿐 아니라 예약 상태, 결제 상태, 실패 복구, 중복 요청 처리까지 하나의 상태 흐름으로 설계해야 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 핵심 엔지니어링 요구사항&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 풀기 위해 시스템이 반드시 만족해야 할 조건은 다음과 같다.&lt;/p&gt;
&lt;div&gt;콘서트 티켓 예매 시스템의 핵심 엔지니어링 요구사항요구사항 설명 실패 시 문제
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;재고 정합성&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;확정 판매 수는 좌석 수 1만 석을 절대 초과하지 않아야 한다.&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;중복 판매, 환불, 고객 불만, 운영 사고가 발생한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;원자적 처리&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;좌석 배정, 재고 차감, 예약 생성은 논리적으로 하나의 성공 또는 실패로 처리되어야 한다.&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;재고는 줄었는데 예약이 없거나, 예약은 있는데 재고가 줄지 않는 상태가 생긴다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;중복 요청 방지&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;더블 클릭, 새로고침, 네트워크 재시도로 같은 사용자의 같은 요청이 반복되어도 결과가 중복되면 안 된다.&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;한 사용자가 여러 좌석을 의도치 않게 확보하거나 결제가 중복될 수 있다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;피크 트래픽 흡수&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;오픈 직후 1분 동안 들어오는 10만 명의 요청을 직접 DB에 모두 꽂지 않아야 한다.&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;DB 커넥션 고갈, Lock 대기 증가, 장애 전파가 발생한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;공정한 처리&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;먼저 도착한 사용자가 불합리하게 뒤로 밀리지 않도록 대기열 또는 순번 기준이 필요하다.&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;사용자 경험이 무너지고, 재시도 폭주가 더 커질 수 있다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;장애 복구&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;예약 생성 후 결제 실패, 서버 장애, Redis와 DB 불일치 같은 상태를 복구할 수 있어야 한다.&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;좌석이 영구적으로 묶이거나, 결제는 되었는데 티켓이 없는 상태가 생긴다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수치 목표를 잡는다면, &amp;ldquo;확정 예약은 좌석 수를 1건도 초과하지 않는다&amp;rdquo;, &amp;ldquo;대기열 응답은 수백 ms 안에 반환한다&amp;rdquo;, &amp;ldquo;예약 보류 시간은 5분 또는 10분처럼 명확히 둔다&amp;rdquo;, &amp;ldquo;DB 쓰기 경로는 큐와 워커로 제어해 커넥션 상한을 넘기지 않는다&amp;rdquo; 정도로 정의할 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 가장 먼저 부딪힐 기술적 난관&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 큰 난관은 &lt;b&gt;고경합 자원에 대한 일관성 유지와 처리량 확보를 동시에 만족시키는 것&lt;/b&gt;이다. 좌석 수량은 하나의 공유 자원이고, 오픈 직후 모든 요청이 같은 콘서트 재고를 향해 몰린다. 이때 가장 단순한 구현은 DB 한 줄에 남은 좌석 수를 저장하고 모든 요청이 그 행을 갱신하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이 방식은 요청이 적을 때는 안전해도, 10만 명이 몰리면 문제가 달라진다. 하나의 재고 행에 Lock이 집중되면서 Lock 대기 시간이 길어지고, 트랜잭션이 쌓이고, DB 커넥션 풀이 고갈될 수 있다. 결국 정합성을 지키기 위해 Lock을 세게 걸수록 처리량과 사용자 경험이 나빠진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 Lock을 약하게 걸거나 애플리케이션 메모리에서만 재고를 관리하면 속도는 빨라질 수 있지만, 서버가 여러 대일 때 재고 중복 차감이 발생하기 쉽다. 즉 이 문제는 &amp;ldquo;정합성 vs 처리량&amp;rdquo;의 균형을 어떻게 잡느냐가 핵심이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 접근 방식 가설과 Trade-off&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현실적으로는 하나의 기술만으로 모든 요구사항을 만족시키기 어렵다. 그래도 각 선택지의 성격을 비교하면 어떤 조합이 적합한지 판단할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;대안 1. DB 비관적 Lock&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 직관적인 방식은 DB 트랜잭션 안에서 재고 행이나 좌석 행을 SELECT ... FOR UPDATE로 잠그고, 남은 좌석이 있을 때만 예약을 생성하는 방식이다. PostgreSQL 공식 문서 기준으로 FOR UPDATE는 조회된 행이 다른 트랜잭션에서 수정되거나 잠기는 것을 현재 트랜잭션 종료 전까지 막는다.&lt;/p&gt;
&lt;div style=&quot;background-color: #fbfbfb;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;: DB가 최종 Source of Truth가 되므로 정합성을 이해하기 쉽다. 트랜잭션, Unique Constraint, 외래 키를 함께 쓰면 중복 좌석 배정 방어가 명확하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;: 모든 요청이 같은 재고 행을 잠그면 병목이 생긴다. Lock 대기, Deadlock, 커넥션 고갈 문제가 발생할 수 있고, 피크 트래픽에서는 DB가 가장 먼저 힘들어진다.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;대안 2. DB 낙관적 갱신 또는 조건부 Update&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 방식은 명시적인 긴 Lock 대신, DB의 원자적 Update를 이용하는 것이다. 예를 들어 &amp;ldquo;남은 좌석이 0보다 클 때만 sold_count를 1 증가시킨다&amp;rdquo;는 조건부 Update를 수행하고, 변경된 행 수가 1이면 성공으로 판단한다. 버전 컬럼을 두고 Optimistic Lock을 적용할 수도 있다.&lt;/p&gt;
&lt;div style=&quot;background-color: #fbfbfb;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;: 트랜잭션을 짧게 유지할 수 있고, 긴 Lock 점유를 줄일 수 있다. 구현 복잡도가 비교적 낮고 DB만으로 재고 초과를 막을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;: 트래픽이 몰리면 실패와 재시도가 많아진다. 결국 같은 행을 계속 갱신하는 Hot Row 문제가 남고, 공정한 순서 보장이 어렵다.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;대안 3. Redis 원자 연산으로 좌석 토큰 선점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번째 방식은 예매 오픈 전에 Redis에 좌석 토큰 1만 개를 준비해두고, 사용자가 예매하기를 누르면 Redis의 원자 연산 또는 Lua Script로 토큰을 하나 꺼내는 방식이다. Redis는 단일 스레드 실행 모델과 빠른 인메모리 연산 덕분에 짧은 시간의 대량 요청을 흡수하는 데 유리하다.&lt;/p&gt;
&lt;div style=&quot;background-color: #fbfbfb;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;: DB에 직접 몰리는 쓰기 부하를 크게 줄일 수 있다. 좌석 토큰이 1만 개뿐이라면 Redis 단계에서 자연스럽게 1만 명까지만 예약 보류 상태로 보낼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;: Redis에서 토큰을 뺐지만 DB 저장에 실패하는 경우, 또는 Redis 장애와 복제 지연이 발생하는 경우를 별도로 복구해야 한다. Redis Lock도 분산 환경에서는 안전성 조건을 신중하게 따져야 한다.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;대안 4. 메시지 큐와 대기열 기반 처리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네 번째 방식은 사용자의 요청을 바로 예매 처리하지 않고, 대기열에 넣은 뒤 제한된 수의 워커가 순서대로 처리하는 방식이다. 사용자에게는 &amp;ldquo;대기 순번&amp;rdquo; 또는 &amp;ldquo;진입 가능 상태&amp;rdquo;를 먼저 반환하고, 실제 좌석 배정은 큐 뒤쪽에서 수행한다.&lt;/p&gt;
&lt;div style=&quot;background-color: #fbfbfb;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;: 서버와 DB가 감당할 수 있는 속도로 요청을 흘려보낼 수 있다. 장애가 났을 때 재처리, 모니터링, 처리량 조절이 쉽다. 피크 트래픽을 완충하는 데 가장 현실적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;: 사용자는 즉시 성공/실패를 받지 못할 수 있다. 큐 중복 전달, 워커 재시도, 처리 순서, Idempotent Consumer 설계를 추가로 고려해야 한다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 현재 시점에서 선호하는 설계&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 더 적합하다고 보는 방식은 &lt;b&gt;대기열 + Redis 좌석 토큰 + DB 최종 제약 조건&lt;/b&gt;을 함께 쓰는 하이브리드 구조다. 이유는 단순하다. 10만 명이 동시에 들어오는 상황에서 모든 요청을 DB 트랜잭션으로 바로 처리하는 것은 정합성은 지킬 수 있어도 장애 위험이 크다. 반대로 Redis만 믿고 최종 판매를 확정하기에는 장애 복구와 영속성 측면에서 불안하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 역할을 나누는 편이 낫다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;대기열은 10만 명의 동시 접속을 흡수하고, 서버와 DB에 들어갈 요청 속도를 제한한다.&lt;/li&gt;
&lt;li&gt;Redis는 짧은 시간 동안 1만 개의 좌석 토큰을 빠르게 선점시키는 역할을 한다.&lt;/li&gt;
&lt;li&gt;DB는 최종 예약과 결제 상태를 저장하는 Source of Truth가 된다.&lt;/li&gt;
&lt;li&gt;DB에는 event_id + seat_id, event_id + user_id, idempotency_key 같은 Unique Constraint를 둬 최후의 중복 방어선을 만든다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조에서는 Redis에서 토큰을 얻었다고 바로 &amp;ldquo;구매 확정&amp;rdquo;이 아니다. 먼저 &lt;b&gt;PENDING_RESERVED&lt;/b&gt; 상태의 예약을 만들고, 제한 시간 안에 결제가 완료되면 &lt;b&gt;CONFIRMED&lt;/b&gt;로 바꾼다. 결제가 실패하거나 시간이 지나면 예약은 &lt;b&gt;EXPIRED&lt;/b&gt;가 되고 좌석 토큰은 회수 대상이 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 설계 흐름 예시&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기 설계 흐름은 다음과 같이 잡을 수 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;예매 오픈 전에 좌석 1만 개를 DB에 등록하고, Redis에도 동일한 좌석 토큰을 준비한다.&lt;/li&gt;
&lt;li&gt;사용자가 접속하면 바로 예매 API로 보내지 않고 대기열 토큰을 발급한다.&lt;/li&gt;
&lt;li&gt;대기 순번이 된 사용자만 예매 API를 호출할 수 있게 한다.&lt;/li&gt;
&lt;li&gt;예매 API는 사용자 인증, 중복 요청 키, 대기열 토큰 유효성을 먼저 확인한다.&lt;/li&gt;
&lt;li&gt;Redis Lua Script로 &amp;ldquo;이미 이 사용자가 선점했는지&amp;rdquo;와 &amp;ldquo;남은 좌석 토큰이 있는지&amp;rdquo;를 한 번에 검사한다.&lt;/li&gt;
&lt;li&gt;토큰을 얻으면 DB 트랜잭션으로 예약 행을 생성한다. 이때 Unique Constraint로 좌석 중복과 사용자 중복을 다시 막는다.&lt;/li&gt;
&lt;li&gt;DB 저장이 실패하면 Redis 토큰 회수 또는 보정 작업 대상에 넣는다.&lt;/li&gt;
&lt;li&gt;결제가 완료되면 예약 상태를 CONFIRMED로 바꾸고, 실패 또는 타임아웃이면 EXPIRED로 바꾼다.&lt;/li&gt;
&lt;li&gt;주기적인 Reconciliation Job이 Redis, DB, 결제 상태의 불일치를 찾아 보정한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 중요한 것은 &amp;ldquo;한 번에 완벽한 Exactly-once 시스템을 만든다&amp;rdquo;가 아니다. 분산 시스템에서는 네트워크 실패, 재시도, 중복 메시지가 언제든 생길 수 있다. 그래서 각 단계가 중복 실행되어도 최종 상태가 깨지지 않도록 멱등성, Unique Constraint, 상태 전이 규칙을 함께 두는 것이 현실적인 설계다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 면접 답변처럼 요약하면&lt;/h2&gt;
&lt;div style=&quot;background-color: #f7f9fc;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제 정의&lt;/b&gt;: 10만 명 동시 접속 상황에서 1만 개 좌석이라는 한정 자원을 중복 없이 배정해야 하는 고경합 동시성 문제다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심 요구사항&lt;/b&gt;: 재고 초과 판매 0건, 좌석/사용자/요청 단위 중복 방지, 피크 트래픽 완충, 결제 실패 복구, 장애 후 데이터 보정이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;가장 큰 난관&lt;/b&gt;: DB Lock만으로 정합성을 지키면 Hot Row 병목이 생기고, Redis만으로 처리하면 영속성과 복구가 약해진다. 정합성과 처리량을 동시에 만족시키는 경계 설계가 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;선호 방식&lt;/b&gt;: 대기열로 유입량을 제어하고, Redis로 좌석 토큰을 빠르게 선점시키며, DB의 Unique Constraint와 트랜잭션으로 최종 정합성을 보장하는 하이브리드 방식을 선택한다.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 설계의 핵심은 각 기술을 만능 해결책으로 보지 않는 것이다. Redis는 빠른 선점과 부하 흡수에 강하고, DB는 최종 정합성에 강하며, 메시지 큐는 피크 트래픽을 안정적으로 흘리는 데 강하다. 좋은 설계는 이 장점을 역할별로 나누고, 실패했을 때 복구할 수 있는 상태 모델을 함께 갖춘다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #888888;&quot; data-ke-size=&quot;size16&quot;&gt;이 글은 시스템 설계 학습과 과제 답변을 목적으로 작성한 기술 분석 글입니다. 실제 티켓 예매 시스템에서는 좌석 정책, 결제사 연동 방식, 법적 고지, 장애 대응 프로세스에 따라 세부 설계가 달라질 수 있습니다.&lt;/p&gt;</description>
      <category>AI</category>
      <category>DBLOCK</category>
      <category>MessageQueue</category>
      <category>Overbooking</category>
      <category>redis</category>
      <category>동시성제어</category>
      <category>백엔드</category>
      <category>시스템설계</category>
      <category>티켓예매</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/91</guid>
      <comments>https://onethingflow.tistory.com/entry/%EC%BD%98%EC%84%9C%ED%8A%B8-%ED%8B%B0%EC%BC%93-%EC%98%88%EB%A7%A4-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90%EC%84%9C-Overbooking%EC%9D%84-%EB%A7%89%EB%8A%94-%EB%B0%B1%EC%97%94%EB%93%9C-%EC%84%A4%EA%B3%84-%EC%82%AC%EA%B3%A0#entry91comment</comments>
      <pubDate>Tue, 9 Jun 2026 07:30:24 +0900</pubDate>
    </item>
    <item>
      <title>초보 러너를 위한 마라톤 완벽 가이드: 착지, 신발, 스트레칭, 훈련, 대회 준비까지</title>
      <link>https://onethingflow.tistory.com/entry/beginner-running-10km-marathon-guide</link>
      <description>&lt;!--
티스토리 제목 추천:
초보 러너를 위한 10km 마라톤 완벽 가이드: 착지, 신발, 스트레칭, 훈련, 대회 준비까지

티스토리 태그 추천:
러닝, 초보러너, 10km마라톤, 마라톤준비, 러닝화추천, 러닝스트레칭, 러닝자세, 대회준비
--&gt;
&lt;div&gt;
&lt;style&gt;
.hb-post{max-width:780px;margin:0 auto;line-height:1.86;font-size:17px;color:#222;word-break:keep-all;}
.hb-post *{box-sizing:border-box;}
.hb-post h1{margin:0 0 .72em;font-size:2em;line-height:1.28;font-weight:800;color:#111;}
.hb-post h2{margin:2.5em 0 .75em;font-size:1.34em;line-height:1.42;font-weight:800;padding-bottom:.36em;border-bottom:2px solid #edf0f4;color:#111;}
.hb-post h3{margin:1.85em 0 .55em;font-size:1.08em;line-height:1.45;font-weight:800;color:#182033;}
.hb-post p{margin:0 0 1.12em;}
.hb-post a{color:#235ad1;text-decoration:none;border-bottom:1px solid rgba(35,90,209,.25);}
.hb-post a:hover{border-bottom-color:#235ad1;}
.hb-post strong{font-weight:800;}
.hb-post .hb-lead{font-size:1.08em;color:#343a46;}
.hb-post .hb-hero{margin:0 0 1.6em;padding:1.35em 1.4em;border:1px solid #e1e6ef;border-radius:8px;background:linear-gradient(135deg,#f7fbff 0%,#fff 62%,#fff7ef 100%);}
.hb-post .hb-hero p:last-child{margin-bottom:0;}
.hb-post .hb-kpi{display:grid;grid-template-columns:repeat(3,1fr);gap:.85em;margin:1.4em 0;}
.hb-post .hb-kpi div{border:1px solid #e5e8ee;border-radius:8px;background:#fbfcfd;padding:1em;}
.hb-post .hb-kpi span{display:block;font-size:.82em;color:#687182;margin-bottom:.25em;}
.hb-post .hb-kpi strong{display:block;font-size:1.16em;color:#10141b;line-height:1.35;}
.hb-post .hb-note-box{background:#f7f9fc;border:1px solid #e3e9f2;border-left:4px solid #3f75ff;border-radius:8px;padding:1.1em 1.25em;margin:1.55em 0;}
.hb-post .hb-note-box p{margin:0 0 .58em;}
.hb-post .hb-note-box p:last-child{margin-bottom:0;}
.hb-post .hb-warn{background:#fff8f4;border-color:#f1d8cc;border-left-color:#e76f51;}
.hb-post .hb-green{background:#f4fbf8;border-color:#d7eee3;border-left-color:#2a9d8f;}
.hb-post blockquote.hb-pull{margin:1.55em 0;padding:.95em 1.15em;background:#fff9e8;border-left:4px solid #f2b705;border-radius:8px;font-size:1.06em;font-weight:800;color:#584500;}
.hb-post ul,.hb-post ol{margin:0 0 1.18em;padding-left:1.38em;}
.hb-post ul li{list-style:disc;}
.hb-post ol li{list-style:decimal;}
.hb-post li{margin:.38em 0;}
.hb-post .hb-table-wrap{overflow-x:auto;margin:1.45em 0;-webkit-overflow-scrolling:touch;}
.hb-post table{border-collapse:collapse;width:100%;font-size:.94em;min-width:680px;}
.hb-post th,.hb-post td{border:1px solid #e1e5eb;padding:.72em .82em;text-align:left;vertical-align:top;}
.hb-post thead th{background:#f1f4f8;font-weight:800;color:#172033;}
.hb-post tbody tr:nth-child(even){background:#fafbfc;}
.hb-post caption{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);}
.hb-post .hb-badges{display:flex;flex-wrap:wrap;gap:.5em;margin:1em 0 1.4em;}
.hb-post .hb-badge{display:inline-flex;align-items:center;border:1px solid #dfe5ee;border-radius:999px;padding:.28em .68em;background:#fff;font-size:.84em;font-weight:700;color:#303846;}
.hb-post .hb-checklist{display:grid;grid-template-columns:repeat(2,1fr);gap:.8em;margin:1.35em 0;}
.hb-post .hb-checklist div{border:1px solid #e4e7ec;border-radius:8px;padding:1em;background:#fff;}
.hb-post .hb-checklist strong{display:block;margin-bottom:.32em;color:#16233f;}
.hb-post .hb-figure{margin:1.65em 0;border:1px solid #e1e6ef;border-radius:8px;background:#fff;overflow:hidden;}
.hb-post .hb-figure svg{display:block;width:100%;height:auto;background:#fbfcfd;}
.hb-post .hb-figure figcaption{padding:.78em 1em;background:#f6f8fb;color:#566173;font-size:.9em;line-height:1.6;}
.hb-post .hb-stretch-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:.9em;padding:1em;background:#fbfcfd;}
.hb-post .hb-stretch-card{border:1px solid #e1e6ef;border-radius:8px;background:#fff;overflow:hidden;}
.hb-post .hb-stretch-card a{display:block;background:#fbfcfd;}
.hb-post .hb-stretch-card img{display:block;width:100%;aspect-ratio:1/1;object-fit:contain;padding:.65em;box-sizing:border-box;background:#fbfcfd;}
.hb-post .hb-stretch-card div{padding:.85em .95em;}
.hb-post .hb-stretch-card strong{display:block;margin-bottom:.25em;color:#172033;}
.hb-post .hb-stretch-card p{margin:0;font-size:.9em;color:#566173;line-height:1.6;}
.hb-post .hb-source{margin-top:2.7em;padding-top:1.2em;border-top:1px solid #edf0f4;font-size:.92em;color:#4b5565;}
.hb-post .hb-source li{margin:.45em 0;}
.hb-post .hb-disclaimer{margin-top:1.6em;font-size:.88em;color:#7a8290;}
@media (max-width:640px){
  .hb-post{font-size:16px;}
  .hb-post h1{font-size:1.58em;}
  .hb-post .hb-kpi,.hb-post .hb-checklist,.hb-post .hb-stretch-grid{grid-template-columns:1fr;}
  .hb-post table{font-size:.9em;min-width:760px;}
}
&lt;/style&gt;
&lt;/div&gt;
&lt;article class=&quot;hb-post&quot;&gt;
&lt;div class=&quot;hb-hero&quot;&gt;
&lt;h1&gt;초보 러너를 위한 10km 마라톤 완벽 가이드&lt;/h1&gt;
&lt;p class=&quot;hb-lead&quot; data-ke-size=&quot;size16&quot;&gt;러닝을 처음 시작하면 제일 헷갈리는 게 &amp;ldquo;어떻게 달려야 덜 다치고, 어떻게 준비해야 대회에서 무너지지 않을까?&amp;rdquo;다. 착지, 보폭, 팔치기, 호흡, 러닝화, 스트레칭, 7km 벽, 대회 전 식사까지 하나씩 따로 배우면 조각은 생기는데 전체 그림이 흐릿하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 초보 러너가 10km 대회를 준비할 때 필요한 내용을 한 번에 정리한 가이드다. 기준 목표는 &lt;b&gt;10km 45분, 평균 4분 30초/km&lt;/b&gt;로 잡았지만, 원리는 60분 완주 목표나 첫 10km 도전에도 그대로 쓸 수 있다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-kpi&quot;&gt;
&lt;div&gt;&lt;span&gt;초보자의 핵심 목표&lt;/span&gt; &lt;b&gt;부상 없이 꾸준히&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;10km 45분 페이스&lt;/span&gt; &lt;b&gt;4:30/km&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;가장 중요한 변수&lt;/span&gt; &lt;b&gt;보폭과 훈련량&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote class=&quot;hb-pull&quot; data-ke-style=&quot;style1&quot;&gt;초보 러너에게 가장 좋은 자세는 &amp;ldquo;멋있어 보이는 자세&amp;rdquo;가 아니라, 내가 오래 반복해도 통증이 누적되지 않는 자세다.&lt;/blockquote&gt;
&lt;div class=&quot;hb-note-box hb-warn&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;먼저 안전 기준부터&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무릎, 발목, 아킬레스건, 종아리, 발바닥 통증이 달릴수록 심해지면 그날 훈련은 성공이 아니라 중단 신호다. 특히 찌르는 통증, 절뚝거림, 붓기, 휴식 후에도 남는 통증은 병원이나 물리치료사 상담을 우선하자.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 착지법: 힐풋, 미들풋, 포어풋을 어떻게 봐야 하나&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;착지는 보통 세 가지로 나눈다. 뒤꿈치가 먼저 닿는 &lt;b&gt;힐풋&lt;/b&gt;, 발 중간이 먼저 닿는 &lt;b&gt;미들풋&lt;/b&gt;, 앞꿈치가 먼저 닿는 &lt;b&gt;포어풋&lt;/b&gt;이다. 강의 메모처럼 초보자는 미들풋을 부상 예방 쪽으로, 포어풋을 속도 쪽으로 이해하면 큰 방향은 맞다. 다만 실제로는 &amp;ldquo;미들풋이면 무조건 안전하고 힐풋이면 무조건 위험하다&amp;rdquo;가 아니다.&lt;/p&gt;
&lt;figure class=&quot;hb-figure&quot;&gt;힐풋뒤꿈치 먼저미들풋발 중간으로 받기포어풋앞꿈치 먼저
&lt;figcaption&gt;착지법은 몸의 부하가 어디로 가는지를 바꾼다. 힐풋은 무릎 쪽 부하가 커질 수 있고, 포어풋은 종아리와 아킬레스건 부하가 커질 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;착지법별 초보자 이해&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;착지&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;장점&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;주의할 점&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;초보자 적용법&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;힐풋&lt;/td&gt;
&lt;td&gt;많은 러너에게 자연스럽다. 천천히 달릴 때 흔하다.&lt;/td&gt;
&lt;td&gt;발이 몸보다 멀리 앞에 떨어지는 오버스트라이드와 결합하면 충격이 커질 수 있다.&lt;/td&gt;
&lt;td&gt;억지로 버리기보다 보폭을 줄이고 발을 몸 가까이에 내려놓는 데 집중한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;미들풋&lt;/td&gt;
&lt;td&gt;충격을 비교적 고르게 나눠 받기 쉽다.&lt;/td&gt;
&lt;td&gt;억지로 바꾸면 종아리 피로가 늘 수 있다.&lt;/td&gt;
&lt;td&gt;초보자는 &amp;ldquo;발바닥 전체가 조용히 닿는다&amp;rdquo;는 느낌으로 연습한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;포어풋&lt;/td&gt;
&lt;td&gt;빠른 페이스, 질주, 트랙 훈련에서 자연스럽게 나타날 수 있다.&lt;/td&gt;
&lt;td&gt;종아리, 발목, 아킬레스건 부하가 커질 수 있다.&lt;/td&gt;
&lt;td&gt;전력질주나 짧은 가속주 때만 자연스럽게 사용한다. 장거리에서 억지로 유지하지 않는다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 중요한 것은 착지 이름이 아니라 &lt;b&gt;보폭&lt;/b&gt;이다. 보폭을 과하게 넓히면 발이 몸 중심보다 멀리 앞에 떨어지고, 브레이크를 밟듯 충격이 들어온다. 기록을 내고 싶어도 처음부터 다리를 길게 뻗지 말고, &lt;b&gt;짧고 빠르게, 몸 아래에 가깝게&lt;/b&gt; 착지하는 감각을 먼저 잡자.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 팔치기와 자세: 달걀 하나를 쥔 느낌&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팔은 다리를 억지로 끌고 가는 장치가 아니라 리듬을 만드는 장치다. 손은 꽉 쥐지 말고 &lt;b&gt;달걀 하나를 감싸쥔다는 느낌&lt;/b&gt;으로 둔다. 어깨에는 힘을 빼고, 팔꿈치는 대략 90도 전후로 접은 뒤 앞뒤로 자연스럽게 흔든다.&lt;/p&gt;
&lt;div class=&quot;hb-checklist&quot;&gt;
&lt;div&gt;&lt;b&gt;좋은 팔치기&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;손은 가볍게, 팔꿈치는 뒤로 살짝 빠지고, 어깨는 내려간다. 팔과 다리의 리듬이 같이 맞는다.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;b&gt;피해야 할 팔치기&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주먹을 꽉 쥐거나, 팔이 몸 앞에서 좌우로 크게 흔들리거나, 어깨가 귀 쪽으로 올라간다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상체는 너무 뒤로 젖히지 말고, 발목부터 몸 전체가 살짝 앞으로 기울어진 느낌이면 충분하다. 시선은 발끝이 아니라 10~20m 앞을 본다. 숨이 차기 시작하면 자세가 무너지기 쉬운데, 그때일수록 어깨를 내리고 팔을 작게 흔드는 것이 도움이 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 호흡: 정답보다 리듬이 중요하다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;호흡은 &amp;ldquo;코로만 해야 한다&amp;rdquo;, &amp;ldquo;몇 번 들이마시고 몇 번 내쉬어야 한다&amp;rdquo;처럼 하나의 정답이 없다. 초보자가 호흡 때문에 힘들다고 느낄 때 많은 경우 문제는 호흡법이 아니라 &lt;b&gt;속도&lt;/b&gt;다. 호흡이 무너지면 먼저 페이스를 낮춰야 한다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;상황별 호흡 리듬&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;상황&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;추천 느낌&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;포인트&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;평상시 조깅&lt;/td&gt;
&lt;td&gt;짧게 &amp;ldquo;씁씁 후후&amp;rdquo; 또는 2보 들이마시고 2보 내쉬기&lt;/td&gt;
&lt;td&gt;대화가 짧게 가능하면 적절한 강도다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;속도를 낼 때&lt;/td&gt;
&lt;td&gt;내쉬는 숨을 조금 더 길게&lt;/td&gt;
&lt;td&gt;힘을 뺄 때는 들숨보다 날숨이 더 중요하다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;먼 거리 후반&lt;/td&gt;
&lt;td&gt;&amp;ldquo;씁, 후&amp;rdquo;처럼 길게 정리&lt;/td&gt;
&lt;td&gt;호흡을 붙잡기보다 보폭을 줄이고 리듬을 되찾는다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;호흡은 몸 상태를 알려주는 계기판이다. 같은 페이스인데 숨이 평소보다 훨씬 차면 수면, 피로, 더위, 미세먼지, 전날 훈련 강도 중 하나가 영향을 주고 있을 가능성이 크다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 실내, 실외, 트레드밀: 어디서 달리는 게 좋을까&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초보자에게 가장 좋은 장소는 &amp;ldquo;내가 꾸준히 나갈 수 있는 장소&amp;rdquo;다. 실외 러닝은 바람, 날씨, 노면, 경사에 적응할 수 있어 실제 대회 감각을 만들기 좋다. 비를 조금 맞으며 달리는 경험도 러닝의 재미가 될 수 있다. 다만 번개, 폭우, 빙판, 심한 미세먼지는 낭만이 아니라 위험이다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;실내 러닝과 실외 러닝 비교&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;구분&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;장점&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;주의점&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;추천 상황&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;실외 러닝&lt;/td&gt;
&lt;td&gt;대회 감각, 지형 적응, 심리적 재미가 좋다.&lt;/td&gt;
&lt;td&gt;노면, 차량, 날씨, 미세먼지 영향을 받는다.&lt;/td&gt;
&lt;td&gt;날씨가 안정적이고 공기질이 괜찮은 날&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;트레드밀&lt;/td&gt;
&lt;td&gt;속도 조절이 쉽고, 수건과 물을 가까이 둘 수 있다.&lt;/td&gt;
&lt;td&gt;같은 움직임이 반복되어 지루하거나 특정 부위에 피로가 쌓일 수 있다.&lt;/td&gt;
&lt;td&gt;미세먼지, 폭염, 한파, 비상 일정이 있는 날&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;헬스장 보강&lt;/td&gt;
&lt;td&gt;러닝과 근력운동을 함께 하기 좋다.&lt;/td&gt;
&lt;td&gt;러닝 거리만 늘리는 것보다 회복 관리가 필요하다.&lt;/td&gt;
&lt;td&gt;겨울, 장마철, 부상 복귀 초기&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미세먼지는 감으로 판단하지 말고 AQI나 국내 대기질 정보를 확인하자. 공기질이 나쁘면 실내 트레드밀, 실내 자전거, 근력운동으로 대체하는 것이 낫다. 반대로 날씨가 좋다면 초보자도 천천히 야외 러닝 비중을 늘려야 대회 당일 노면과 바람에 덜 당황한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 러닝화: 초보자는 쿠션보다 &amp;lsquo;맞는 신발&amp;rsquo;이 먼저다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;러닝화는 크게 로드 러닝화와 트레일 러닝화로 나눌 수 있다. 초보자가 일반 도로, 공원, 한강변을 달린다면 기본은 &lt;b&gt;로드 러닝화&lt;/b&gt;다. 트레일 러닝화는 바위, 흙, 자갈, 물길이 있는 거친 구간용이라 첫 러닝화로는 보통 우선순위가 낮다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;러닝화 종류와 초보자 적합도&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;종류&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;특징&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;누구에게 맞나&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;쿠션화&lt;/td&gt;
&lt;td&gt;충격 흡수와 편안함 중심&lt;/td&gt;
&lt;td&gt;대부분의 초보자에게 가장 무난하다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;안정화&lt;/td&gt;
&lt;td&gt;발이 안쪽으로 과하게 무너지는 움직임을 보조&lt;/td&gt;
&lt;td&gt;평발, 과회내, 아치 문제로 불편함이 있는 러너가 매장에서 직접 신어보고 고른다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;레이싱화&lt;/td&gt;
&lt;td&gt;가볍고 반발력이 좋으며 속도에 유리&lt;/td&gt;
&lt;td&gt;러닝 근육이 어느 정도 생긴 뒤 기록용으로 고려한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;트레일화&lt;/td&gt;
&lt;td&gt;접지력과 보호력 중심&lt;/td&gt;
&lt;td&gt;산길, 흙길, 자갈길, 젖은 노면이 많은 코스용이다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;힐드랍&lt;/b&gt;은 뒤꿈치 굽 높이와 앞꿈치 굽 높이의 차이다. 강의에서는 약 6mm 전후를 이상적인 기준으로 설명한다. 실제로 6mm 전후는 초보자가 지나치게 높은 드랍과 제로 드랍 사이에서 비교적 무난하게 적응하기 쉬운 영역이다. 다만 제로 드랍이나 낮은 드랍으로 갑자기 바꾸면 종아리와 아킬레스건 부담이 늘 수 있으니 천천히 적응해야 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;신발 추천은 &amp;ldquo;모델명&amp;rdquo;보다 &amp;ldquo;역할&amp;rdquo;로 이해하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 후보군은 &lt;b&gt;2026년 6월 8일 기준&lt;/b&gt; 공식 제품 정보와 판매 페이지를 확인해 역할별로 정리했다. 가격, 색상, 재고, 세부 스펙은 시점에 따라 바뀔 수 있으니 최종 구매 전에는 공식 페이지와 매장 착화를 다시 확인하자.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;초보 러너용 러닝화 후보군&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;역할&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;모델 예시&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;초보자 메모&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;기본 데일리 트레이너&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://www.brooksrunning.com/en_us/mens/shoes/road-running-shoes/ghost-18/110493.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Brooks Ghost 18&lt;/a&gt;, &lt;a href=&quot;https://www.saucony.com/en/ride-18/59943M.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Saucony Ride 18&lt;/a&gt;, &lt;a href=&quot;https://about.nike.com/newsroom/releases/nike-vomero-18-official-images&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Nike Vomero 18&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;첫 러닝화로 가장 무난한 영역이다. 과하게 푹신하거나 과하게 단단한 느낌보다, 30분 조깅 후 발이 편한지가 기준이다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;부드러운 장거리 쿠션&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://www.newbalance.com/pd/fresh-foam-x-1080v14/M108014O-D-09.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;New Balance Fresh Foam X 1080v14&lt;/a&gt;, &lt;a href=&quot;https://www.rei.com/product/242661/hoka-clifton-10-road-running-shoes-mens&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;HOKA Clifton 10&lt;/a&gt;, &lt;a href=&quot;https://www.asics.com/us/en-us/novablast--5/p/ANA_20058504302.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ASICS Novablast 5&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;긴 조깅과 회복주에 편하다. 다만 매우 높은 쿠션은 발목이 흔들리는 사람에게 불안할 수 있으므로 매장 착화가 중요하다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;안정화/가이드형&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://corp.asics.com//en/press/article/the-gel-kayanotm-32-shoe-delivers-premium-stability-with-plush-comfort&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ASICS GEL-KAYANO 32&lt;/a&gt;, &lt;a href=&quot;https://www.rei.com/product/C08594/saucony-guide-18-road-running-shoes-mens&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Saucony Guide 18&lt;/a&gt;, &lt;a href=&quot;https://www.altrarunning.com/en-us/road/mens-experience-form/AL0A85NT.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Altra Experience Form&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;평발, 과회내, 아치 불편감이 있는 러너의 후보군이다. &amp;ldquo;안정화가 무조건 좋다&amp;rdquo;가 아니라, 내 발의 흔들림을 줄여주는지로 판단한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;단단한 쿠션/미들풋 감각&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://www.on.com/en-us/products/cloudmonster-2-m-3mf3104/mens&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;On Cloudmonster 2&lt;/a&gt;, &lt;a href=&quot;https://corp.asics.com//en/press/article/discover-remarkable-stability-and-comfort-with-the-new-gt-2000tm-13-&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ASICS GT-2000 13&lt;/a&gt;, &lt;a href=&quot;https://usa.mizuno.com/running-wave-rider-29-mens?pr_rd_page=1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Mizuno Wave Rider 29&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;너무 말랑한 쿠션이 싫거나 발이 신발 안에서 흔들리는 러너에게 맞을 수 있다. 첫 구매라면 쿠션감보다 착지 안정감을 먼저 본다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;가벼운 데일리/빠른 조깅&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://www.newbalance.com/pd/fuelcell-rebel-v5/MFCXLD5-D-115.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;New Balance FuelCell Rebel v5&lt;/a&gt;, &lt;a href=&quot;https://us.puma.com/us/en/pd/velocity-nitro-3-mens-running-shoes/377748&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PUMA Velocity NITRO 3&lt;/a&gt;, &lt;a href=&quot;https://news.adidas.com/running/adidas-launches-supernova-rise-2---built-to-provide-even-more-comfort-all-in-a-lighter-package/s/664bbf38-10a6-449e-b2b9-b9b7d3cdeb86&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;adidas Supernova Rise 2&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;이지런도 하고 가끔 빠르게 달릴 때 좋은 후보군이다. 체중이 많이 실리는 러너라면 너무 가벼운 신발보다 보호감을 우선한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;스피드 트레이너&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://us.puma.com/us/en/pd/deviate-nitro%E2%84%A2-3-mens-running-shoes/309707&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PUMA Deviate NITRO 3&lt;/a&gt;, &lt;a href=&quot;https://news.adidas.com/sports/adidas-launches-new-adizero-boston-13---designed-for-fast-training-runs/S/0ca9243c-a53d-47a6-8e7c-31e4e2d77357&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;adidas Adizero Boston 13&lt;/a&gt;, &lt;a href=&quot;https://www.asics.com/us/en-us/product/magic-speed-4/p/ANA_1011B875-402.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ASICS Magic Speed 4&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;템포런, 인터벌, 레이스페이스런에 적합하다. 플레이트나 강한 반발감이 있는 모델은 종아리와 발바닥 적응 기간이 필요하다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;제로/로우 드랍&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://www.altrarunning.com/en-us/road/mens-torin-8/AL0A85QE.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Altra Torin 8&lt;/a&gt;, &lt;a href=&quot;https://www.altrarunning.com/en-us/road/mens-escalante-4/AL0A85NE.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Altra Escalante 4&lt;/a&gt;, Altra Paradigm 계열&lt;/td&gt;
&lt;td&gt;발가락 공간과 자연스러운 착지감이 장점이다. 하지만 기존 8~12mm 드랍에서 바로 넘어가면 종아리와 아킬레스건 부담이 커질 수 있다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;레이싱화&lt;/td&gt;
&lt;td&gt;ASICS METASPEED 계열, Nike Vaporfly/Alphafly 계열, adidas Adios Pro 계열, PUMA Deviate NITRO Elite 계열&lt;/td&gt;
&lt;td&gt;첫 러닝화로는 우선순위가 낮다. 10km 기록을 노리고, 데일리 신발이 이미 있고, 빠른 훈련에 적응한 뒤에 고려한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-note-box hb-green&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;러닝화 구매 체크&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오후나 저녁에 신어본다. 엄지발가락 앞에 손가락 한 마디 정도 여유를 둔다. 매장 안에서 걷기만 하지 말고 가능하면 짧게 뛰어본다. 새 신발은 대회 당일 처음 신지 않는다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 러닝 전 준비운동: 정적 스트레칭보다 동적 워밍업&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;달리기 전에는 오래 버티는 정적 스트레칭보다 몸을 깨우는 동적 워밍업이 더 적합하다. 목표는 근육을 길게 늘리는 것이 아니라 심박을 천천히 올리고, 발목, 고관절, 햄스트링, 종아리, 어깨를 러닝 리듬에 맞게 준비시키는 것이다.&lt;/p&gt;
&lt;figure class=&quot;hb-figure&quot;&gt;
&lt;div class=&quot;hb-stretch-grid&quot;&gt;
&lt;div class=&quot;hb-stretch-card&quot;&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Jumpingjacks.gif&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; &lt;img src=&quot;https://commons.wikimedia.org/wiki/Special:FilePath/Jumpingjacks.gif&quot; alt=&quot;팔과 다리를 동시에 벌리고 모으는 점핑잭 동작&quot; /&gt; &lt;/a&gt;
&lt;div&gt;&lt;b&gt;점핑잭 30초&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;심박을 가볍게 올리는 시작 동작이다. 어깨가 불편하면 팔을 완전히 머리 위로 올리지 않아도 된다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-stretch-card&quot;&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:High_knees.gif&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; &lt;img src=&quot;https://commons.wikimedia.org/wiki/Special:FilePath/High_knees.gif&quot; alt=&quot;무릎을 번갈아 높게 들어 올리는 하이니 동작&quot; /&gt; &lt;/a&gt;
&lt;div&gt;&lt;b&gt;하이니 20~30초&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무릎을 억지로 높이기보다 발소리를 줄인다. 상체를 세우고 팔치기 리듬을 함께 만든다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-stretch-card&quot;&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Walking_lunges_4.svg&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; &lt;img src=&quot;https://commons.wikimedia.org/wiki/Special:FilePath/Walking_lunges_4.svg&quot; alt=&quot;앞으로 내딛으며 무릎을 굽히는 워킹 런지 동작&quot; /&gt; &lt;/a&gt;
&lt;div&gt;&lt;b&gt;워킹 런지 6~10걸음&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보폭을 과하게 넓히지 않는다. 무릎이 안쪽으로 무너지지 않게 하고, 고관절 앞쪽을 깨운다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-stretch-card&quot;&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Bodyweight_Squats.gif&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; &lt;img src=&quot;https://commons.wikimedia.org/wiki/Special:FilePath/Bodyweight_Squats.gif?width=600&quot; alt=&quot;무릎과 고관절을 굽혔다 펴는 맨몸 스쿼트 동작&quot; /&gt; &lt;/a&gt;
&lt;div&gt;&lt;b&gt;맨몸 스쿼트 8~12회&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엉덩이와 허벅지를 깨우는 동작이다. 깊이보다 무릎 정렬과 발바닥 전체로 누르는 감각을 우선한다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-stretch-card&quot;&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Exercise_Heel_Raise_One_Leg.png&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; &lt;img src=&quot;https://commons.wikimedia.org/wiki/Special:FilePath/Exercise_Heel_Raise_One_Leg.png?width=900&quot; alt=&quot;한 발로 뒤꿈치를 들어 올리는 카프 레이즈 동작&quot; /&gt; &lt;/a&gt;
&lt;div&gt;&lt;b&gt;카프 레이즈 10~15회&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;종아리와 아킬레스건을 갑자기 쓰지 않도록 준비한다. 난도가 높으면 두 발로 시작한다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-stretch-card&quot;&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Lunge-CDC_strength_training_for_older_adults.gif&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; &lt;img src=&quot;https://commons.wikimedia.org/wiki/Special:FilePath/Lunge-CDC_strength_training_for_older_adults.gif&quot; alt=&quot;런지 자세로 고관절과 하체를 준비하는 동작&quot; /&gt; &lt;/a&gt;
&lt;div&gt;&lt;b&gt;짧은 런지 리듬 6~8회&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대회 전이나 강훈련 전에는 깊게 버티지 말고 짧게 움직인다. 몸이 따뜻해진 뒤 가속주로 연결한다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;러닝 전에는 오래 버티는 정적 스트레칭보다 움직이는 워밍업이 적합하다. 위 이미지는 외부 공개 라이선스 이미지와 CDC 공개 도메인 GIF를 사용했다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;5분 가볍게 걷거나 아주 천천히 조깅한다.&lt;/li&gt;
&lt;li&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;발목 돌리기, 다리 앞뒤 흔들기, 고관절 열기, 워킹 런지를 한다.&lt;/li&gt;
&lt;li&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;무릎 올리기, 엉덩이 차기, 팔 흔들기로 리듬을 만든다.&lt;/li&gt;
&lt;li&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;강훈련이나 대회 전에는 60~100m 가속주를 2~3회 넣는다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 러닝 후 스트레칭: 20~30초, 통증 없는 범위&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;달리기 후에는 심박이 천천히 내려오도록 5분 정도 걷고, 그 다음 정적 스트레칭을 한다. 스트레칭은 아픈 만큼 밀어붙이는 훈련이 아니다. 당기는 느낌은 괜찮지만 찌르는 통증은 멈춰야 한다.&lt;/p&gt;
&lt;figure class=&quot;hb-figure&quot;&gt;
&lt;div class=&quot;hb-stretch-grid&quot;&gt;
&lt;div class=&quot;hb-stretch-card&quot;&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:The_Calf_Stretch_110402-A-XD329-017.jpg&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; &lt;img src=&quot;https://commons.wikimedia.org/wiki/Special:FilePath/The_Calf_Stretch_110402-A-XD329-017.jpg?width=900&quot; alt=&quot;벽을 짚고 한쪽 다리를 뒤로 뻗어 종아리를 늘리는 종아리 스트레칭&quot; /&gt; &lt;/a&gt;
&lt;div&gt;&lt;b&gt;종아리 스트레칭&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벽을 짚고 뒤쪽 다리 무릎을 편다. 발뒤꿈치가 들리지 않게 바닥을 누르며 종아리 뒤쪽을 늘린다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-stretch-card&quot;&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Hamstring_stretch-CDC_strength_training_for_older_adults.gif&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; &lt;img src=&quot;https://commons.wikimedia.org/wiki/Special:FilePath/Hamstring_stretch-CDC_strength_training_for_older_adults.gif&quot; alt=&quot;한쪽 다리를 앞으로 뻗고 상체를 숙여 허벅지 뒤쪽을 늘리는 햄스트링 스트레칭&quot; /&gt; &lt;/a&gt;
&lt;div&gt;&lt;b&gt;햄스트링 스트레칭&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한쪽 다리를 앞으로 뻗고 상체를 천천히 숙인다. 허리를 둥글게 말기보다 엉덩이를 뒤로 빼는 느낌이 좋다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-stretch-card&quot;&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Lunge-CDC_strength_training_for_older_adults.gif&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; &lt;img src=&quot;https://commons.wikimedia.org/wiki/Special:FilePath/Lunge-CDC_strength_training_for_older_adults.gif&quot; alt=&quot;한쪽 다리를 앞으로 내딛고 골반을 낮춰 고관절 앞쪽을 늘리는 런지 스트레칭&quot; /&gt; &lt;/a&gt;
&lt;div&gt;&lt;b&gt;고관절/장요근 스트레칭&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;런지 자세에서 골반을 정면으로 두고 천천히 낮춘다. 뒤쪽 다리의 고관절 앞부분이 부드럽게 당기면 충분하다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-stretch-card&quot;&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Quad_stretch-CDC_strength_training_for_older_adults.gif&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; &lt;img src=&quot;https://commons.wikimedia.org/wiki/Special:FilePath/Quad_stretch-CDC_strength_training_for_older_adults.gif&quot; alt=&quot;서서 한쪽 발목을 잡고 허벅지 앞쪽을 늘리는 대퇴사두근 스트레칭&quot; /&gt; &lt;/a&gt;
&lt;div&gt;&lt;b&gt;대퇴사두근 스트레칭&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한쪽 발목을 잡고 무릎을 아래로 둔다. 허리가 꺾이지 않게 복부에 살짝 힘을 주고 허벅지 앞쪽을 늘린다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-stretch-card&quot;&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Backstretch-CDC_strength_training_for_older_adults.gif&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; &lt;img src=&quot;https://commons.wikimedia.org/wiki/Special:FilePath/Backstretch-CDC_strength_training_for_older_adults.gif&quot; alt=&quot;의자에 앉아 상체를 숙이며 허리와 등 뒤쪽을 늘리는 허리 스트레칭&quot; /&gt; &lt;/a&gt;
&lt;div&gt;&lt;b&gt;허리/등 스트레칭&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앉은 자세에서 상체를 편하게 숙인다. 허리 통증이 있는 날에는 깊게 누르지 말고 호흡이 편한 범위까지만 간다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-stretch-card&quot;&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Piriformis_stretch.jpg&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; &lt;img src=&quot;https://commons.wikimedia.org/wiki/Special:FilePath/Piriformis_stretch.jpg?width=900&quot; alt=&quot;한쪽 다리를 반대쪽 무릎 위에 올려 둔근과 이상근을 늘리는 스트레칭&quot; /&gt; &lt;/a&gt;
&lt;div&gt;&lt;b&gt;둔근/이상근 스트레칭&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한쪽 발목을 반대쪽 무릎 위에 올리고 상체를 천천히 숙인다. 엉덩이 바깥쪽이 당기면 충분하다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-stretch-card&quot;&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Chest_stretch-CDC_strength_training_for_older_adults.gif&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; &lt;img src=&quot;https://commons.wikimedia.org/wiki/Special:FilePath/Chest_stretch-CDC_strength_training_for_older_adults.gif&quot; alt=&quot;양팔을 뒤로 열어 가슴과 어깨 앞쪽을 늘리는 가슴 스트레칭&quot; /&gt; &lt;/a&gt;
&lt;div&gt;&lt;b&gt;가슴/어깨 앞쪽 스트레칭&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;양팔을 뒤로 열어 가슴을 넓힌다. 팔을 억지로 꺾기보다 어깨가 내려간 상태에서 앞쪽이 시원하게 열리면 된다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;기존 아이콘형 그림을 실제 동작 이미지로 교체했다. 종아리는 미군 공개 도메인 사진, 다수 동작은 CDC 공개 도메인 운동 GIF를 사용했고, 둔근/이상근은 Wikimedia Commons의 CC BY-SA 이미지를 사용했다. 각 동작은 20~30초, 좌우 1~2회만 통증 없는 범위에서 진행한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 사진 루틴은 종아리, 햄스트링, 고관절/장요근, 대퇴사두근, 허리/등, 둔근/이상근, 가슴/어깨 앞쪽 순서로 구성했다. 강의 목록에 있던 어깨, 뒷목, 온몸 펴주기는 사진 루틴 뒤에 짧게 추가해도 좋다. 폼롤러가 있다면 종아리, 허벅지 앞쪽, 둔근을 가볍게 풀어도 좋다. 단, 폼롤러로 통증 부위를 세게 누르는 것이 회복은 아니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 초보 러너 주간 훈련: 약, 중강, 약, 강&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초보자가 5km를 넘어 7km, 10km로 가려면 매일 같은 강도로 달리면 안 된다. 몸은 반복으로 성장하지만, 반복 강도가 계속 높으면 회복할 시간이 없다. 강의에서 말한 &lt;b&gt;강, 약, 중강, 약&lt;/b&gt;의 리듬을 주간 계획으로 바꾸면 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;7km 벽을 넘기 위한 주간 루틴&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;요일&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;강도&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;훈련&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;목적&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;월요일&lt;/td&gt;
&lt;td&gt;약&lt;/td&gt;
&lt;td&gt;2km 아주 편하게&lt;/td&gt;
&lt;td&gt;주간 시작, 몸 깨우기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;수요일&lt;/td&gt;
&lt;td&gt;중강&lt;/td&gt;
&lt;td&gt;3~4km, 평소보다 약간 빠르게&lt;/td&gt;
&lt;td&gt;속도와 리듬 적응&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;금요일&lt;/td&gt;
&lt;td&gt;약&lt;/td&gt;
&lt;td&gt;2km 편하게, 스트레칭 충분히&lt;/td&gt;
&lt;td&gt;회복과 연결성 유지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;토요일 또는 일요일&lt;/td&gt;
&lt;td&gt;강&lt;/td&gt;
&lt;td&gt;6km 도전, 익숙해지면 7km&lt;/td&gt;
&lt;td&gt;심리적 벽 넘기&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 연속성이다. 7km가 어렵다면 6km를 여러 번 편하게 만들고, 그다음 6.5km, 7km로 간다. 한 번에 너무 멀리 뛰는 것보다, 지난 한 달 동안 가장 길었던 거리보다 조금만 더 가는 편이 안전하다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9. 10km 45분 목표 페이스 계산&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10km 45분은 1km마다 4분 30초를 유지해야 한다. 초보자에게 이 목표는 가볍지 않다. 이미 10km를 50분 전후로 완주할 수 있고, 5km를 22분 전후로 달릴 수 있을 때 도전하는 편이 현실적이다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;10km 45분 페이스표&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;거리&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;누적 시간&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;운영 포인트&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1km&lt;/td&gt;
&lt;td&gt;4:30&lt;/td&gt;
&lt;td&gt;흥분해서 4:10으로 들어가지 않는다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3km&lt;/td&gt;
&lt;td&gt;13:30&lt;/td&gt;
&lt;td&gt;호흡은 빠르지만 통제 가능해야 한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5km&lt;/td&gt;
&lt;td&gt;22:30&lt;/td&gt;
&lt;td&gt;여기서 이미 힘들면 45분은 어렵다. 페이스를 안정시킨다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8km&lt;/td&gt;
&lt;td&gt;36:00&lt;/td&gt;
&lt;td&gt;보폭을 넓히지 말고 팔 리듬으로 버틴다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10km&lt;/td&gt;
&lt;td&gt;45:00&lt;/td&gt;
&lt;td&gt;마지막 1km는 남은 힘을 쓰되 자세를 무너뜨리지 않는다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초반 오버페이스는 10km에서 가장 흔한 실패다. 1~2km를 너무 빠르게 달리면 7km 이후 몸이 급격히 잠긴다. 처음 2km는 목표 페이스와 같거나 5초 정도 느리게 들어가고, 3~8km에서 리듬을 유지한 뒤 마지막 2km에서 판단한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;10. 대회 10일 전부터: 10km 기준 테이퍼&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마라톤 풀코스에서 쓰는 &amp;ldquo;10일 전 7km 레이스페이스&amp;rdquo; 같은 이야기를 10km 대회에 그대로 가져오면 과할 수 있다. 10km 목표가 4분 30초/km라면, 초보자는 10일 전에 7km를 전부 4분 30초로 밀기보다 &lt;b&gt;총 7km 안에서 목표 페이스 구간을 나눠 넣는 방식&lt;/b&gt;이 안전하다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;10km 대회 10일 전부터 훈련 계획&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;시점&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;훈련&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;이유&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;D-10&lt;/td&gt;
&lt;td&gt;총 7km: 2km 조깅, 3km @ 4:30/km, 1km 조깅, 1km @ 4:30/km&lt;/td&gt;
&lt;td&gt;목표 페이스 감각을 확인하되 피로를 크게 남기지 않는다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D-7&lt;/td&gt;
&lt;td&gt;5~6km 이지런, 20초 가속주 4회&lt;/td&gt;
&lt;td&gt;훈련량을 줄이기 시작한다. 다리를 무겁게 만들지 않는다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D-5&lt;/td&gt;
&lt;td&gt;3~4km 조깅 또는 휴식&lt;/td&gt;
&lt;td&gt;수면과 회복을 우선한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D-3&lt;/td&gt;
&lt;td&gt;4km 조깅, 200m 가볍게 빠르게 3회&lt;/td&gt;
&lt;td&gt;속도 감각만 살리고 끝낸다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D-1&lt;/td&gt;
&lt;td&gt;휴식 또는 15~20분 산책성 조깅&lt;/td&gt;
&lt;td&gt;처음 하는 훈련, 새 신발, 새 보강운동은 금지다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;hb-note-box&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이미 4:30 페이스가 편한 러너라면&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;D-10에 2km 워밍업 후 5km를 4:30/km로 달리고 1km 쿨다운을 해도 된다. 하지만 초보자라면 &amp;ldquo;성공적으로 끝내는 감각&amp;rdquo;이 더 중요하다. 대회 직전 훈련은 몸을 새로 만드는 시간이 아니라, 이미 만든 몸을 가볍게 정리하는 시간이다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;11. 훈련 종류 확장: 템포런과 인터벌만 있는 게 아니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초보자가 기록을 올릴 때 가장 자주 하는 실수는 모든 훈련을 &amp;ldquo;그냥 힘들게&amp;rdquo; 만드는 것이다. 10km 훈련은 이지런, 롱런, 스트라이드, 파틀렉, 언덕 반복, 템포런, 인터벌, 레이스페이스런을 목적별로 나눠야 한다. 그래야 강한 날은 강하게, 약한 날은 정말 약하게 만들 수 있다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;10km 목표자를 위한 훈련 종류별 사용법&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;훈련&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;목적&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;10km 45분 목표 예시&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;초보자 기준&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;이지런&lt;/td&gt;
&lt;td&gt;러닝 경제성, 회복, 주간 거리의 바탕&lt;/td&gt;
&lt;td&gt;20~45분, 대화 가능한 페이스. 4:30 목표자도 5:45~6:40/km까지 충분히 느려도 된다.&lt;/td&gt;
&lt;td&gt;가장 많이 해야 하는 훈련이다. 느리게 달리는 능력이 강훈련을 버티게 만든다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;회복주&lt;/td&gt;
&lt;td&gt;피로 제거, 다음 훈련을 위한 연결&lt;/td&gt;
&lt;td&gt;15~30분 아주 천천히 또는 걷기 섞기&lt;/td&gt;
&lt;td&gt;기록을 내는 날이 아니다. 다리가 무거우면 과감히 산책으로 바꾼다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;롱런&lt;/td&gt;
&lt;td&gt;지구력, 7km 이후 무너짐 방지&lt;/td&gt;
&lt;td&gt;45~75분 편하게. 초보자는 6km, 7km, 8km 순서로 확장&lt;/td&gt;
&lt;td&gt;거리 욕심보다 다음날 회복 여부가 기준이다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;스트라이드&lt;/td&gt;
&lt;td&gt;자세, 빠른 다리 회전, 질주 감각&lt;/td&gt;
&lt;td&gt;20초 빠르게 x 4~8회, 사이 40~60초 걷기 또는 조깅&lt;/td&gt;
&lt;td&gt;전력질주가 아니다. 80~90% 느낌으로 짧고 가볍게 끝낸다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;파틀렉&lt;/td&gt;
&lt;td&gt;속도 변화 적응, 지루함 해소&lt;/td&gt;
&lt;td&gt;1분 빠르게 + 2분 천천히 x 6~8세트&lt;/td&gt;
&lt;td&gt;정확한 거리보다 리듬이 중요하다. 공원, 한강, 트레드밀 모두 가능하다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;언덕 반복&lt;/td&gt;
&lt;td&gt;둔근, 종아리, 추진력, 자세 안정&lt;/td&gt;
&lt;td&gt;20~45초 오르막 x 4~8회, 내려오며 완전 회복&lt;/td&gt;
&lt;td&gt;내리막을 빠르게 달리지 않는다. 무릎 부담이 커질 수 있다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;프로그레션런&lt;/td&gt;
&lt;td&gt;후반 페이스 운영, 오버페이스 방지&lt;/td&gt;
&lt;td&gt;30분 달리기: 10분 편하게, 10분 보통, 10분 약간 빠르게&lt;/td&gt;
&lt;td&gt;끝으로 갈수록 빨라지되 마지막도 전력질주로 만들지 않는다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;템포런&lt;/td&gt;
&lt;td&gt;젖산역치, 빠른 지속 능력&lt;/td&gt;
&lt;td&gt;2km 워밍업, 4~5km @ 4:45~4:55/km, 1km 쿨다운&lt;/td&gt;
&lt;td&gt;숨은 차지만 무너지지 않아야 한다. 끝나고 &amp;ldquo;조금 더 할 수 있다&amp;rdquo;가 맞다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;인터벌&lt;/td&gt;
&lt;td&gt;스피드, 심폐 자극, 빠른 페이스 적응&lt;/td&gt;
&lt;td&gt;400m x 6~8회, 목표 페이스보다 빠르게. 사이 100~200m 회복 조깅&lt;/td&gt;
&lt;td&gt;처음부터 12회 이상 하지 않는다. 페이스가 무너지면 반복 수를 줄인다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;레이스페이스런&lt;/td&gt;
&lt;td&gt;대회 페이스를 몸에 저장&lt;/td&gt;
&lt;td&gt;1km x 4회 @ 4:30/km, 세트 사이 400m 조깅&lt;/td&gt;
&lt;td&gt;대회 2~3주 전부터 유용하다. 매주 길게 밀어붙이면 피로가 누적된다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;크로스트레이닝&lt;/td&gt;
&lt;td&gt;충격은 줄이고 심폐 유지&lt;/td&gt;
&lt;td&gt;실내 자전거, 수영, 일립티컬 30~45분&lt;/td&gt;
&lt;td&gt;미세먼지, 장마, 부상 복귀 초기에는 달리기 대체재로 쓴다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주 4회 러닝 기준으로는 강훈련을 1회만 넣는 편이 안전하다. 예를 들어 월요일 이지런, 수요일 훈련주, 금요일 회복주, 주말 롱런이 기본 뼈대다. 수요일 훈련주는 매주 같은 것을 반복하지 말고 &lt;b&gt;스트라이드 &amp;rarr; 템포런 &amp;rarr; 파틀렉 또는 언덕 반복 &amp;rarr; 레이스페이스런&lt;/b&gt;처럼 돌려 쓰면 지루함과 부상 위험을 동시에 줄일 수 있다.&lt;/p&gt;
&lt;div class=&quot;hb-note-box hb-green&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;초보자 훈련 배치 원칙&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강훈련 후 회복은 훈련의 일부다. 세트당 5~7분이 필요할 정도로 강한 훈련을 했다면 다음날은 반드시 약하게 간다. 초보자는 인터벌 자체보다 회복 부족으로 더 자주 다친다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;12. 대회 전 식사와 카보로딩: 10km는 과식하지 않는다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카보로딩은 보통 90분 이상 지속되는 고강도 지구성 경기에서 더 의미가 크다. 10km를 45분~70분 안팎으로 뛰는 초보 러너라면 풀코스 마라톤처럼 2~3일 동안 억지로 탄수화물을 많이 먹을 필요는 없다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;10km 대회 전 식사 기준&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;시점&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;추천&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;피하기&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;D-7~D-3&lt;/td&gt;
&lt;td&gt;평소 식사 유지, 수면과 수분 관리&lt;/td&gt;
&lt;td&gt;갑작스러운 식단 변경, 과한 음주&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D-2~D-1&lt;/td&gt;
&lt;td&gt;밥, 빵, 국수, 감자처럼 익숙한 탄수화물을 평소보다 조금 늘린다.&lt;/td&gt;
&lt;td&gt;너무 기름진 음식, 과한 섬유질, 처음 먹는 보충제&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;대회 3시간 전&lt;/td&gt;
&lt;td&gt;바나나, 에너지바, 흰밥, 토스트처럼 소화 잘 되는 음식&lt;/td&gt;
&lt;td&gt;과식, 매운 음식, 카페인을 처음 시도하기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;대회 중&lt;/td&gt;
&lt;td&gt;45분 목표라면 젤은 필수는 아니다. 60분 이상이거나 심리적으로 필요하면 훈련 때 먹어본 젤만 사용한다.&lt;/td&gt;
&lt;td&gt;대회 당일 처음 먹는 카페인 젤&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반식이요법이나 탄수화물 고갈 후 로딩 같은 방식은 초보자에게 추천하지 않는다. 대회 전에는 특별한 방법보다 속이 편한 평소 음식이 더 강하다. 기록은 새로운 식단 실험이 아니라 꾸준히 쌓은 훈련과 안정적인 컨디션에서 나온다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;13. 대회 당일 준비물과 워밍업 타임라인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대회 당일은 낯선 일이 많다. 장소 이동, 화장실 줄, 물품 보관, 출발 대기, 주변 러너의 속도감까지 모두 변수가 된다. 그래서 준비물과 시간표를 전날 정리해두는 것이 좋다.&lt;/p&gt;
&lt;figure class=&quot;hb-figure&quot;&gt;10km 대회 당일 타임라인-3시간가벼운 식사-60분화장실, 짐 보관-40분10~20분 조깅-25분질주 2~3회출발첫 1km 침착하게초보자는 3~4km 워밍업보다 10~20분 조깅 + 동적 체조 + 짧은 가속주가 더 안전하다.
&lt;figcaption&gt;10km 대회는 풀코스보다 워밍업이 중요하다. 단, 초보자는 워밍업에서 체력을 써버리지 않도록 &amp;ldquo;몸이 따뜻해질 정도&amp;rdquo;만 한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;div class=&quot;hb-checklist&quot;&gt;
&lt;div&gt;&lt;b&gt;전날 준비물&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;러닝화, 양말, 유니폼, 배번, 옷핀 또는 레이스벨트, 러닝워치, 모자, 바셀린, 물, 젤, 여벌 옷, 작은 수건.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;b&gt;당일 금지&lt;/b&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새 신발, 새 양말, 새 젤, 새 카페인, 새 스트레칭, 새 페이스 전략. 대회 당일은 실험실이 아니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;14. 보강운동: 60분 달리기를 위한 서킷&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;달리기를 오래 하려면 다리만 강하면 안 된다. 발목, 종아리, 엉덩이, 코어가 같이 버텨야 한다. 강의에서 나온 서킷 트레이닝을 초보자용으로 낮추면 아래처럼 시작할 수 있다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;초보 러너 서킷 트레이닝&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;운동&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;초보자 방식&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;주의점&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;피치 동작&lt;/td&gt;
&lt;td&gt;제자리에서 발을 가볍게 빠르게 바꾼다.&lt;/td&gt;
&lt;td&gt;상체를 세우고 발소리를 줄인다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;엎드려 발바꾸기&lt;/td&gt;
&lt;td&gt;마운틴 클라이머를 천천히 한다.&lt;/td&gt;
&lt;td&gt;허리가 꺾이지 않게 복부에 힘을 준다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;리듬 스쿼트&lt;/td&gt;
&lt;td&gt;반동을 작게 쓰며 10~15회&lt;/td&gt;
&lt;td&gt;무릎이 안쪽으로 무너지지 않게 한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;트위스트&lt;/td&gt;
&lt;td&gt;상체 회전으로 코어 자극&lt;/td&gt;
&lt;td&gt;허리를 억지로 꺾지 않는다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;하이 피치&lt;/td&gt;
&lt;td&gt;20초만 빠르게&lt;/td&gt;
&lt;td&gt;숨이 너무 차면 즉시 쉬어간다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;다리 올려 손뼉치기&lt;/td&gt;
&lt;td&gt;무릎을 올리고 손뼉을 친다.&lt;/td&gt;
&lt;td&gt;균형이 흔들리면 속도를 낮춘다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;점프 스쿼트&lt;/td&gt;
&lt;td&gt;초보자는 일반 스쿼트로 대체 가능&lt;/td&gt;
&lt;td&gt;무릎 통증이 있으면 점프는 하지 않는다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 20초 운동, 40초 휴식으로 1라운드만 한다. 익숙해지면 2라운드로 늘린다. 러닝을 이미 힘들게 한 날에는 보강운동까지 세게 하지 않는다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;15. 지루함과 런태기 극복&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;러닝은 몸보다 마음이 먼저 그만두는 날이 많다. 지루함이 오면 의지력만 탓하지 말고 환경을 바꿔야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;누군가와 함께 달린다.&lt;/b&gt; 지인과 약속하거나 러닝 크루에 들어가면 시작 장벽이 낮아진다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;새로운 도전을 만든다.&lt;/b&gt; 5km 완주, 7km 넘기, 10km 대회, 여행 러닝처럼 목표를 바꾼다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;전날 복장을 준비한다.&lt;/b&gt; 아침 러닝이 어렵다면 내일 입을 옷을 미리 꺼내둔다. 극단적으로는 러닝 복장에 가까운 편한 옷으로 잠들어도 된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;겨울에는 방법을 바꾼다.&lt;/b&gt; 방한 장비를 갖추거나, 너무 춥고 미끄러운 날은 헬스장 트레드밀을 쓴다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;러닝은 명상과 일기를 함께 할 수 있는 운동이다. 달리는 동안 &amp;ldquo;위에서 나를 내려다본다&amp;rdquo;는 느낌으로 내 호흡, 자세, 감정을 3자 입장에서 관찰해보자. 불안이 클수록 오늘의 작은 책임을 정하는 게 도움이 된다. 아침에 짧게라도 일기를 쓰고, 오늘 할 러닝 또는 회복을 정하면 하루가 덜 흔들린다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;16. 부상은 실패가 아니라 피드백이다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부상이 오면 &amp;ldquo;나는 러닝에 안 맞나?&amp;rdquo;라고 생각하기 쉽다. 하지만 대부분의 초보 러닝 부상은 재능 문제가 아니라 강도, 회복, 신발, 보폭, 수면, 지면, 훈련량 중 하나가 어긋난 결과다.&lt;/p&gt;
&lt;div class=&quot;hb-note-box&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;부상 원인 체크 질문&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 한 번에 달린 거리가 갑자기 늘었나? 평소보다 빠른 훈련을 연속으로 했나? 새 신발로 긴 거리를 뛰었나? 수면이 부족했나? 보폭을 넓혀서 기록을 내려고 했나? 통증을 무시하고 계속 뛰었나?&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복귀는 가장 쉬운 페이스와 가장 짧은 거리부터 시작한다. 20분 걷기, 1분 뛰고 2분 걷기, 2km 조깅처럼 몸이 다시 신뢰를 쌓을 시간을 줘야 한다. 실패할수록 성장한다는 말은 억지 긍정이 아니다. 원인을 찾고 수정해서 돌아오는 과정이 러너를 더 단단하게 만든다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;17. 국내 주요 마라톤 대회와 초보자의 선택&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;국내 주요 대회는 매년 일정이 바뀔 수 있으니 접수 전 공식 홈페이지를 확인해야 한다. 2026년 기준으로 확인한 주요 일정은 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;hb-table-wrap&quot;&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;&lt;caption&gt;2026년 국내 주요 마라톤 일정&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;대회&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;2026년 확인 일정&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;초보자 메모&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;서울마라톤, 동아마라톤&lt;/td&gt;
&lt;td&gt;2026년 3월 15일 일요일&lt;/td&gt;
&lt;td&gt;대표적인 봄 대회. 10km와 풀코스 분위기가 크다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;조선일보 춘천마라톤&lt;/td&gt;
&lt;td&gt;2026년 10월 25일 일요일로 안내되는 참고 일정&lt;/td&gt;
&lt;td&gt;흔히 가을 대회로 알려져 있다. 7월이 아니라 보통 10월 마지막 일요일 흐름이다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JTBC 서울마라톤&lt;/td&gt;
&lt;td&gt;2026년 11월 1일 일요일&lt;/td&gt;
&lt;td&gt;가을 대형 대회. 10km 부문도 있어 초보자 첫 대회 후보로 좋다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큰 대회만 답은 아니다. 작은 규모 대회는 출발 대기가 짧고, 분위기가 덜 압박적이며, 첫 완주 경험을 만들기 좋다. 여행과 결합해 하루 이틀 일정으로 다녀오면 러닝이 단순 운동이 아니라 삶의 이벤트가 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;18. 마지막으로: 초보 러너의 우선순위&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;러닝을 잘하고 싶다면 더 세게 달리는 법보다 덜 망가지는 법을 먼저 배워야 한다. 착지는 이름보다 보폭이 중요하고, 호흡은 방법보다 페이스가 중요하다. 신발은 브랜드보다 발에 맞는지가 중요하고, 대회 준비는 새로운 비법보다 익숙한 루틴이 중요하다.&lt;/p&gt;
&lt;div class=&quot;hb-badges&quot;&gt;&lt;span class=&quot;hb-badge&quot;&gt;보폭 줄이기&lt;/span&gt; &lt;span class=&quot;hb-badge&quot;&gt;페이스 유지&lt;/span&gt; &lt;span class=&quot;hb-badge&quot;&gt;동적 워밍업&lt;/span&gt; &lt;span class=&quot;hb-badge&quot;&gt;정적 쿨다운&lt;/span&gt; &lt;span class=&quot;hb-badge&quot;&gt;새것 금지&lt;/span&gt; &lt;span class=&quot;hb-badge&quot;&gt;통증은 신호&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 2km도 충분하다. 그다음 3km, 5km, 7km, 10km로 간다. 어느 날은 비를 맞고, 어느 날은 트레드밀 위에서 뛰고, 어느 날은 쉬어간다. 그렇게 쌓인 날들이 결국 기록이 된다.&lt;/p&gt;
&lt;section class=&quot;hb-source&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고 자료&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.mayoclinic.org/healthy-lifestyle/fitness/in-depth/exercise/art-20045517&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Mayo Clinic, Aerobic exercise: How to warm up and cool down&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mcpress.mayoclinic.org/nutrition-fitness/to-prevent-running-injuries-avoid-these-common-mistakes/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Mayo Clinic Press, To prevent running injuries, avoid these common mistakes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pubmed.ncbi.nlm.nih.gov/32813597/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Xu et al., Effects of Foot Strike Techniques on Running Biomechanics, Sports Health, 2021&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pubmed.ncbi.nlm.nih.gov/34527750/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Burke et al., Risk Factors for Injuries in Runners: Foot Strike Technique, Orthopaedic Journal of Sports Medicine, 2021&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.acsm.org/docs/default-source/files-for-resource-library/running-shoes.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ACSM, Selecting Running Shoes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.airnow.gov/aqi/aqi-basics/using-air-quality-index&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;AirNow, Using the Air Quality Index&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.centerfornutritionandathletics.org/wp-content/uploads/2017/07/ACSM-Webinar-Feb-2017_Gaesser_FINAL2.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ACSM sports nutrition material, carbohydrate loading for events longer than 90 minutes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://webassets.nyrr.org/nyrrsitecoreblob/nyrr/pdf/training-guides/10k_training_plan_beginner_rd41.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;NYRR, 10K Training Plan Beginner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://webassets.nyrr.org/nyrrsitecoreblob/nyrr/pdf/training-guides/hm-training-plan_conservative-rd1.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;NYRR, Half Marathon Training Plan Conservative, training glossary including strides, fartlek, and hill repeats&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Jumpingjacks.gif&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Wikimedia Commons, Jumpingjacks.gif by Wensceslao, CC BY-SA 4.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:High_knees.gif&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Wikimedia Commons, High knees.gif by Wensceslao, CC BY-SA 4.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Walking_lunges_4.svg&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Wikimedia Commons, Walking lunges 4.svg by Everkinetic, CC BY-SA 3.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Bodyweight_Squats.gif&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Wikimedia Commons, Bodyweight Squats.gif by Danielflefil, CC BY-SA 4.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Exercise_Heel_Raise_One_Leg.png&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Wikimedia Commons, Exercise Heel Raise One Leg.png by BruceBlaus, CC BY-SA 4.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:The_Calf_Stretch_110402-A-XD329-017.jpg&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Wikimedia Commons, The Calf Stretch, U.S. Army public domain image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Hamstring_stretch-CDC_strength_training_for_older_adults.gif&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Wikimedia Commons, Hamstring stretch, CDC public domain GIF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Lunge-CDC_strength_training_for_older_adults.gif&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Wikimedia Commons, Lunge, CDC public domain GIF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Quad_stretch-CDC_strength_training_for_older_adults.gif&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Wikimedia Commons, Quad stretch, CDC public domain GIF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Backstretch-CDC_strength_training_for_older_adults.gif&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Wikimedia Commons, Backstretch, CDC public domain GIF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Chest_stretch-CDC_strength_training_for_older_adults.gif&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Wikimedia Commons, Chest stretch, CDC public domain GIF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Piriformis_stretch.jpg&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Wikimedia Commons, Piriformis stretch.jpg by Kpa1563, CC BY-SA 3.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://news.seoul.go.kr/culture/archives/531848&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;서울특별시, 2026 서울마라톤대회 안내&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://marathon.jtbc.com/39&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JTBC 서울마라톤, 2026 대회 안내&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://runstyles.com/events/chosun-chuncheon-marathon/2026&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;RunStyles, 2026 조선일보 춘천마라톤 참고 일정&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.on.com/en-us/products/cloudmonster-2-m-3mf3104/mens&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;On, Cloudmonster 2 공식 제품 정보&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.brooksrunning.com/en_us/mens/shoes/road-running-shoes/ghost-18/110493.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Brooks, Ghost 18 공식 제품 정보&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.saucony.com/en/ride-18/59943M.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Saucony, Ride 18 공식 제품 정보&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://about.nike.com/newsroom/releases/nike-vomero-18-official-images&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Nike, Vomero 18 공식 발표 자료&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.newbalance.com/pd/fresh-foam-x-1080v14/M108014O-D-09.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;New Balance, Fresh Foam X 1080v14 공식 제품 정보&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.rei.com/product/242661/hoka-clifton-10-road-running-shoes-mens&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;REI, HOKA Clifton 10 제품 정보&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.asics.com/us/en-us/novablast--5/p/ANA_20058504302.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ASICS, Novablast 5 공식 제품 정보&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://corp.asics.com//en/press/article/discover-remarkable-stability-and-comfort-with-the-new-gt-2000tm-13-&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ASICS, GT-2000 13 공식 발표 자료&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://corp.asics.com//en/press/article/the-gel-kayanotm-32-shoe-delivers-premium-stability-with-plush-comfort&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ASICS, GEL-KAYANO 32 공식 발표 자료&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.rei.com/product/C08594/saucony-guide-18-road-running-shoes-mens&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;REI, Saucony Guide 18 제품 정보&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.altrarunning.com/en-us/road/mens-experience-form/AL0A85NT.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Altra, Experience Form 공식 제품 정보&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.newbalance.com/pd/fuelcell-rebel-v5/MFCXLD5-D-115.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;New Balance, FuelCell Rebel v5 공식 제품 정보&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://us.puma.com/us/en/pd/velocity-nitro-3-mens-running-shoes/377748&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PUMA, Velocity NITRO 3 공식 제품 정보&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://news.adidas.com/running/adidas-launches-supernova-rise-2---built-to-provide-even-more-comfort-all-in-a-lighter-package/s/664bbf38-10a6-449e-b2b9-b9b7d3cdeb86&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;adidas, Supernova Rise 2 공식 발표 자료&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://us.puma.com/us/en/pd/deviate-nitro%E2%84%A2-3-mens-running-shoes/309707&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PUMA, Deviate NITRO 3 공식 제품 정보&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://news.adidas.com/sports/adidas-launches-new-adizero-boston-13---designed-for-fast-training-runs/S/0ca9243c-a53d-47a6-8e7c-31e4e2d77357&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;adidas, Adizero Boston 13 공식 발표 자료&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.asics.com/us/en-us/product/magic-speed-4/p/ANA_1011B875-402.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ASICS, Magic Speed 4 공식 제품 정보&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://usa.mizuno.com/running-wave-rider-29-mens?pr_rd_page=1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Mizuno, Wave Rider 29 공식 제품 정보&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.newbalance.com/pd/fuelcell-supercomp-trainer-v3/WRCXV4-50692.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;New Balance, FuelCell SuperComp Trainer v3 공식 제품 정보&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.altrarunning.com/en-us/road/mens-paradigm-7/AL0A82C5.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Altra, Paradigm 7 공식 제품 정보&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.altrarunning.com/en-us/road/mens-torin-8/AL0A85QE.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Altra, Torin 8 공식 제품 정보&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.altrarunning.com/en-us/road/mens-escalante-4/AL0A85NE.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Altra, Escalante 4 공식 제품 정보&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;p class=&quot;hb-disclaimer&quot; data-ke-size=&quot;size16&quot;&gt;이 글은 일반적인 러닝 정보 정리이며 개인의 질환, 통증, 체력 수준을 대신 진단하지 않는다. 기존 질환이 있거나 통증이 반복된다면 전문가 상담을 먼저 받자.&lt;/p&gt;
&lt;/article&gt;</description>
      <category>Exercise/running</category>
      <category>10km마라톤</category>
      <category>대회준비</category>
      <category>러닝</category>
      <category>러닝스트레칭</category>
      <category>러닝자세</category>
      <category>러닝화추천</category>
      <category>마라톤준비</category>
      <category>초보러너</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/92</guid>
      <comments>https://onethingflow.tistory.com/entry/beginner-running-10km-marathon-guide#entry92comment</comments>
      <pubDate>Mon, 8 Jun 2026 20:30:35 +0900</pubDate>
    </item>
    <item>
      <title>멱등성(Idempotency): 결제&amp;middot;주문 API를 안전하게 만드는 백엔드 설계와 AI 학습 회고</title>
      <link>https://onethingflow.tistory.com/entry/%EB%A9%B1%EB%93%B1%EC%84%B1Idempotency-%EA%B2%B0%EC%A0%9C%C2%B7%EC%A3%BC%EB%AC%B8-API%EB%A5%BC-%EC%95%88%EC%A0%84%ED%95%98%EA%B2%8C-%EB%A7%8C%EB%93%9C%EB%8A%94-%EB%B0%B1%EC%97%94%EB%93%9C-%EC%84%A4%EA%B3%84%EC%99%80-AI-%ED%95%99%EC%8A%B5-%ED%9A%8C%EA%B3%A0</link>
      <description>&lt;p style=&quot;color: #333333;&quot; data-ke-size=&quot;size16&quot;&gt;멱등성(Idempotency)은 백엔드 API를 공부할 때 처음에는 추상적으로 느껴지지만, 결제&amp;middot;주문&amp;middot;쿠폰 발급처럼 돈이나 재고가 움직이는 기능에서는 거의 필수 안전장치다. 사용자는 버튼을 한 번 눌렀다고 생각하지만, 실제 시스템에서는 같은 요청이 여러 번 도착할 수 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글은 성장 가속도와 AI Leverage 과제에 맞춰, 멱등성을 1시간 동안 집중 학습한 내용을 제출형 콘텐츠로 정리한 것이다. 메인 본문, 코드 스케치, AI 프롬프트 기록을 분리해 구성했다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 컨셉 딥다이브: 멱등성이 왜 중요한가&lt;/h2&gt;
&lt;div style=&quot;background-color: #f7f9fc;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;300자 내외 요약&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멱등성은 같은 요청이 한 번 처리되든 여러 번 재시도되든 서버의 최종 상태가 같게 만드는 성질이다. 결제&amp;middot;주문 API에서는 더블 클릭, 네트워크 타임아웃, PG 재시도 때문에 같은 요청이 반복될 수 있다. 멱등성이 없으면 주문&amp;middot;결제&amp;middot;쿠폰이 중복 생성된다. 보통 Idempotency-Key로 최초 처리 결과를 저장해 재시도 때 같은 응답을 돌려주고, DB Unique 제약&amp;middot;트랜잭션&amp;middot;상태 머신으로 최종 중복을 막는다.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP 표준 문서인 RFC 9110은 멱등성을 &amp;ldquo;같은 요청을 여러 번 보내도 서버에 의도한 효과가 한 번 보낸 것과 같은 성질&amp;rdquo;로 설명한다. GET, PUT, DELETE 같은 메서드는 HTTP 의미론상 멱등적일 수 있지만, 실무에서 특히 중요한 것은 POST 기반의 결제&amp;middot;주문 생성 API에 멱등성을 별도로 설계하는 일이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 사용자가 결제 버튼을 눌렀는데 서버 응답을 받기 전에 네트워크가 끊겼다고 하자. 사용자는 실패했다고 생각해 다시 시도할 수 있다. 하지만 첫 요청이 실제로는 서버에서 성공했을 수도 있다. 이때 서버가 두 번째 요청을 새로운 주문으로 처리하면 중복 결제나 중복 주문이 발생한다.&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fff8e6; color: #5a4500;&quot; data-ke-style=&quot;style1&quot;&gt;멱등성은 &amp;ldquo;요청이 절대 중복되지 않는다&amp;rdquo;는 낙관이 아니라, &amp;ldquo;중복 요청이 와도 최종 결과가 깨지지 않게 한다&amp;rdquo;는 방어적 설계다.&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 일반적인 구현 방식&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멱등성을 구현하는 방식은 여러 가지지만, 결제&amp;middot;주문 처리에서 자주 쓰는 방법은 다음과 같다.&lt;/p&gt;
&lt;div&gt;멱등성 구현 방식 비교방식 핵심 아이디어 장점 주의점
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Idempotency-Key 저장&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;클라이언트가 고유 키를 보내고, 서버는 최초 처리 결과를 저장한 뒤 같은 키가 오면 같은 결과를 반환한다.&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;네트워크 재시도와 더블 클릭을 안전하게 처리하기 좋다.&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;같은 키로 다른 요청 본문을 보내는 오용을 막기 위해 요청 해시를 함께 비교해야 한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;DB Unique Constraint&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;주문 번호, 결제 요청 키, 사용자-쿠폰 조합처럼 중복되면 안 되는 값에 고유 제약을 둔다.&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;애플리케이션 버그가 있어도 DB가 최후의 방어선이 된다.&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;제약 위반을 단순 에러로 끝내지 말고 기존 결과 조회로 연결해야 한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;상태 머신&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;주문을 CREATED, PAID, FAILED, CANCELED 같은 상태로 관리하고 허용된 전이만 수행한다.&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;결제 콜백, 재시도, 취소 요청이 중복되어도 상태가 예측 가능하다.&lt;/td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;외부 PG, 메시지 큐, 배치 복구까지 같은 상태 규칙을 공유해야 한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Stripe 공식 문서도 Idempotency-Key를 사용해 재시도 요청이 같은 작업을 두 번 수행하지 않도록 하고, 같은 키의 최초 결과를 저장해 이후 요청에 반환하는 방식을 설명한다. 또 같은 키가 다른 파라미터와 함께 재사용되면 오용으로 보고 에러를 내는 방식도 중요하다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 코드 스케치: 선착순 쿠폰 발급 API&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선착순 쿠폰 발급 API에서는 &amp;ldquo;재고가 0보다 클 때만 차감한다&amp;rdquo;, &amp;ldquo;한 사용자는 같은 쿠폰을 한 번만 받는다&amp;rdquo;, &amp;ldquo;같은 Idempotency-Key 요청은 같은 결과를 받는다&amp;rdquo;가 핵심이다. 아래는 Kotlin 스타일의 의사코드다.&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot; style=&quot;background-color: #1f2430; color: #eef2ff;&quot;&gt;&lt;code&gt;// 핵심 테이블 가정
// idempotency_request(idempotency_key unique, request_hash, status, response_body)
// coupon(id primary key, remaining)
// coupon_issue(id primary key, coupon_id, user_id, unique(coupon_id, user_id))

fun issueCoupon(
    userId: Long,
    couponId: Long,
    idempotencyKey: String,
    requestHash: String
): IssueResponse {
    require(idempotencyKey.isNotBlank())

    val existing = idempotencyRepository.findByKey(idempotencyKey)
    if (existing != null) {
        if (existing.requestHash != requestHash) {
            throw ConflictException(&quot;same idempotency key, different payload&quot;)
        }
        if (existing.status == &quot;COMPLETED&quot;) {
            return existing.responseBody.toIssueResponse()
        }
        throw RetryLaterException(&quot;same request is still processing&quot;)
    }

    val claimed = idempotencyRepository.tryCreate(
        key = idempotencyKey,
        requestHash = requestHash,
        status = &quot;PROCESSING&quot;
    )
    if (!claimed) {
        return issueCoupon(userId, couponId, idempotencyKey, requestHash)
    }

    return transaction {
        try {
            val alreadyIssued =
                couponIssueRepository.findByUserAndCoupon(userId, couponId)

            if (alreadyIssued != null) {
                return@transaction completeIdempotentRequest(
                    idempotencyKey,
                    IssueResponse(status = &quot;ALREADY_ISSUED&quot;, issueId = alreadyIssued.id)
                )
            }

            val decreased = couponRepository.decreaseIfAvailable(couponId)
            // SQL 예시:
            // UPDATE coupon SET remaining = remaining - 1
            // WHERE id = :couponId AND remaining &amp;gt; 0

            if (!decreased) {
                return@transaction completeIdempotentRequest(
                    idempotencyKey,
                    IssueResponse(status = &quot;SOLD_OUT&quot;, issueId = null)
                )
            }

            val issue = couponIssueRepository.insert(userId, couponId)

            completeIdempotentRequest(
                idempotencyKey,
                IssueResponse(status = &quot;SUCCESS&quot;, issueId = issue.id)
            )
        } catch (e: UniqueConstraintViolationException) {
            val issue = couponIssueRepository.findByUserAndCoupon(userId, couponId)
            completeIdempotentRequest(
                idempotencyKey,
                IssueResponse(status = &quot;ALREADY_ISSUED&quot;, issueId = issue.id)
            )
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스케치에서 중요한 방어선은 세 겹이다. 첫째, Idempotency-Key로 같은 요청의 결과를 재사용한다. 둘째, 쿠폰 재고 차감은 remaining &amp;gt; 0 조건을 가진 DB 원자 Update로 처리한다. 셋째, coupon_id + user_id Unique Constraint로 한 사용자의 중복 발급을 DB가 최종적으로 막는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 운영에서는 PROCESSING 상태가 오래 남는 경우도 처리해야 한다. 서버가 재고를 차감하기 전에 죽었는지, 발급 행까지 만들고 응답 저장 전에 죽었는지에 따라 복구 방식이 달라진다. 그래서 오래된 PROCESSING 요청은 배치 작업으로 비즈니스 테이블을 확인한 뒤 COMPLETED 또는 FAILED로 보정하는 흐름이 필요하다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. AI의 도움을 받은 부분과 수정한 부분&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI에게 처음 질문했을 때 가장 도움이 된 부분은 추상적인 개념을 실제 실패 사례로 바꿔준 점이었다. &amp;ldquo;멱등성은 같은 연산을 여러 번 해도 결과가 같다&amp;rdquo;는 정의만 보면 감이 약했는데, 결제 타임아웃, 더블 클릭, 메시지 큐 재전달, PG 콜백 중복 같은 사례로 연결하니 왜 필요한지 선명해졌다.&lt;/p&gt;
&lt;div style=&quot;background-color: #fbfbfb;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;채택한 부분&lt;/b&gt;: Idempotency-Key 저장, 요청 파라미터 해시 비교, 최초 응답 재사용, DB Unique Constraint를 최후의 방어선으로 두는 아이디어를 채택했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;수정한 부분&lt;/b&gt;: AI는 처음에 Redis Lock을 비교적 쉽게 제안했지만, 나는 선착순 쿠폰 발급의 최종 정합성은 DB 조건부 Update와 Unique Constraint로 보장하는 쪽이 더 단순하다고 판단했다. Redis는 트래픽 완충에는 유용하지만, &amp;ldquo;정확한 발급 결과&amp;rdquo;의 최종 기준은 DB에 두는 편이 복구가 쉽다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 회고: AI as a Co-pilot&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 학습에서 AI는 학습 속도를 크게 높여줬다. 특히 내가 &amp;ldquo;멱등성&amp;rdquo;이라는 키워드만 알고 있을 때, AI는 관련 개념을 결제 API, 주문 생성, 재고 차감, 메시지 큐 중복 처리로 확장해 주었다. 또 내가 놓칠 수 있는 엣지 케이스를 질문으로 던지게 만들었다. 예를 들면 &amp;ldquo;같은 Idempotency-Key인데 요청 본문이 다르면 어떻게 할 것인가?&amp;rdquo;, &amp;ldquo;처리 중 서버가 죽으면 PROCESSING 상태는 어떻게 회복할 것인가?&amp;rdquo; 같은 질문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 AI 답변은 비판적으로 봐야 했다. AI는 종종 &amp;ldquo;Exactly once&amp;rdquo;라는 표현을 쉽게 쓰지만, 분산 시스템에서 완전한 Exactly once는 매우 어렵고 대부분은 At-least-once 전달 위에 멱등한 Consumer를 설계하는 방식에 가깝다. 또한 샘플 코드는 Unique Constraint, 트랜잭션 범위, 장애 복구 배치가 빠져 있는 경우가 있었다. 그래서 최종 답변에는 공식 문서의 정의와 실무적인 실패 모드를 함께 확인해 반영했다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 사용한 AI 프롬프트 전체&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 이번 멱등성 학습과 코드 스케치 과정에서 사용한 프롬프트 기록이다.&lt;/p&gt;
&lt;div style=&quot;background-color: #fbfbfb;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Prompt 1&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백엔드 API 설계에서 멱등성(Idempotency)이 무엇인지 HTTP 메서드 관점과 결제/주문 API 관점으로 나누어 설명해줘. 단순 정의 말고, 실제 장애 사례와 연결해서 이해하고 싶어.&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #fbfbfb;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Prompt 2&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결제 버튼을 눌렀는데 네트워크 타임아웃이 발생한 상황을 예로 들어, 멱등성이 없을 때 어떤 문제가 생기는지 단계별로 설명해줘.&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #fbfbfb;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Prompt 3&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Idempotency-Key를 사용한 API 설계를 설명해줘. 서버는 어떤 값을 저장해야 하고, 같은 키로 요청이 다시 오면 어떤 응답을 반환해야 해?&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #fbfbfb;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Prompt 4&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 Idempotency-Key인데 요청 body가 다르면 어떻게 처리하는 게 좋은지 알려줘. Stripe 같은 결제 API는 이 문제를 어떻게 다루는지도 함께 설명해줘.&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #fbfbfb;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Prompt 5&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선착순 쿠폰 발급 API를 설계한다고 가정하고, 멱등성을 보장하는 핵심 로직을 Kotlin 의사코드로 작성해줘. 조건은 쿠폰 재고 초과 발급 금지, 사용자당 1회 발급, 같은 요청 재시도 시 같은 결과 반환이야.&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #fbfbfb;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Prompt 6&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Redis Lock, DB Unique Constraint, DB 조건부 Update 방식의 장단점을 비교해줘. 선착순 쿠폰 발급에서는 어떤 방식을 최종 정합성 기준으로 삼는 게 좋은지 Trade-off 중심으로 설명해줘.&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #fbfbfb;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Prompt 7&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 작성한 멱등성 코드 스케치에서 실무적으로 빠지기 쉬운 엣지 케이스를 찾아줘. 특히 서버 장애, PROCESSING 상태 고착, 중복 메시지, Unique Constraint 위반 처리 관점에서 검토해줘.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 최종 정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멱등성은 &amp;ldquo;중복 요청을 막는 기능&amp;rdquo;이라기보다 &amp;ldquo;중복 요청이 와도 비즈니스 결과가 깨지지 않게 하는 설계 원칙&amp;rdquo;에 가깝다. 결제, 주문, 쿠폰, 티켓처럼 한 번의 실수가 비용으로 이어지는 API에서는 클라이언트 재시도, 서버 재시도, 메시지 재전달을 정상적인 상황으로 보고 설계해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI는 이 개념을 빠르게 넓혀 이해하는 데 좋은 도구였다. 다만 AI가 준 답을 그대로 믿기보다, 공식 문서의 정의와 DB 제약 조건, 트랜잭션, 장애 복구 관점으로 다시 검증할 때 학습이 깊어졌다. 나에게 AI Leverage는 답을 대신 쓰게 하는 것이 아니라, 더 좋은 질문을 더 빨리 찾게 해주는 도구에 가까웠다.&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p style=&quot;color: #888888;&quot; data-ke-size=&quot;size16&quot;&gt;이 글은 백엔드 API 설계 학습과 과제 제출을 돕기 위한 기술 정리 글입니다. 실제 결제&amp;middot;주문 시스템에서는 결제사의 API 정책, 장애 복구 정책, 개인정보 처리 기준, 내부 감사 요구사항에 따라 구현 세부사항이 달라질 수 있습니다.&lt;/p&gt;</description>
      <category>AI</category>
      <category>ai활용</category>
      <category>api설계</category>
      <category>ChatGPT</category>
      <category>Idempotency</category>
      <category>결제API</category>
      <category>멱등성</category>
      <category>백엔드</category>
      <category>주문처리</category>
      <category>쿠폰발급</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/90</guid>
      <comments>https://onethingflow.tistory.com/entry/%EB%A9%B1%EB%93%B1%EC%84%B1Idempotency-%EA%B2%B0%EC%A0%9C%C2%B7%EC%A3%BC%EB%AC%B8-API%EB%A5%BC-%EC%95%88%EC%A0%84%ED%95%98%EA%B2%8C-%EB%A7%8C%EB%93%9C%EB%8A%94-%EB%B0%B1%EC%97%94%EB%93%9C-%EC%84%A4%EA%B3%84%EC%99%80-AI-%ED%95%99%EC%8A%B5-%ED%9A%8C%EA%B3%A0#entry90comment</comments>
      <pubDate>Mon, 8 Jun 2026 12:40:55 +0900</pubDate>
    </item>
    <item>
      <title>Supabase, Firebase, MongoDB 등 어떤 데이터베이스 총정리</title>
      <link>https://onethingflow.tistory.com/entry/Supabase-Firebase-MongoDB-%EB%93%B1-%EC%96%B4%EB%96%A4-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%B4%9D%EC%A0%95%EB%A6%AC</link>
      <description>&lt;style&gt;
.hb-post{max-width:760px;margin:0 auto;line-height:1.85;font-size:17px;color:#222;word-break:keep-all;}
.hb-post h2{margin:2.4em 0 .7em;font-size:1.32em;line-height:1.4;font-weight:700;padding-bottom:.35em;border-bottom:2px solid #eee;}
.hb-post h3{margin:1.8em 0 .5em;font-size:1.1em;font-weight:700;}
.hb-post p{margin:0 0 1.15em;}
.hb-post code{background:#f4f5f7;border:1px solid #e6e8eb;border-radius:4px;padding:.08em .4em;font-size:.92em;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;color:#c7254e;}
.hb-post .hb-lead{font-size:1.06em;color:#333;}
.hb-post .hb-note-box{background:#f7f9fc;border:1px solid #e3e9f2;border-left:4px solid #4a7dff;border-radius:8px;padding:1.1em 1.3em;margin:1.6em 0;}
.hb-post .hb-note-box p{margin:0 0 .6em;}
.hb-post .hb-note-box p:last-child{margin-bottom:0;}
.hb-post .hb-checklist{background:#fafafa;border:1px solid #eee;border-radius:8px;padding:1.1em 1.3em;margin:1.6em 0;}
.hb-post .hb-checklist p{margin:0 0 .9em;}
.hb-post .hb-checklist p:last-child{margin-bottom:0;}
.hb-post blockquote.hb-pull{margin:1.6em 0;padding:.9em 1.2em;background:#fff8e6;border-left:4px solid #f5b301;border-radius:6px;font-size:1.08em;font-weight:600;color:#5a4500;}
.hb-post ul,.hb-post ol{margin:0 0 1.2em;padding-left:1.4em;}
.hb-post li{margin:.4em 0;}
.hb-post .hb-table-wrap{overflow-x:auto;margin:1.6em 0;-webkit-overflow-scrolling:touch;}
.hb-post table{border-collapse:collapse;width:100%;font-size:.95em;min-width:520px;}
.hb-post th,.hb-post td{border:1px solid #e2e5e9;padding:.7em .8em;text-align:left;vertical-align:top;}
.hb-post thead th{background:#f2f4f7;font-weight:700;}
.hb-post tbody tr:nth-child(even){background:#fafbfc;}
.hb-post caption{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);}
.hb-post .hb-references{margin-top:2.6em;padding-top:1.2em;border-top:1px solid #eee;font-size:.95em;}
.hb-post .hb-references a{color:#2a5bd7;text-decoration:none;}
.hb-post .hb-references a:hover{text-decoration:underline;}
.hb-post .hb-disclaimer{margin-top:1.6em;font-size:.88em;color:#888;}
&lt;/style&gt;

&lt;article class=&quot;hb-post&quot;&gt;
  &lt;p class=&quot;hb-lead&quot;&gt;웹앱을 만들 때 데이터베이스 선택은 생각보다 빨리 현실 문제가 된다. 처음에는 “사용자 데이터만 저장하면 되겠지”라고 생각하지만, 로그인, 권한, 실시간 동기화, 검색, 통계, 백업까지 들어오면 단순히 유명한 서비스를 고르는 것만으로는 부족하다.&lt;/p&gt;

  &lt;p&gt;특히 개인 개발자나 작은 팀은 Supabase와 Firebase 사이에서 많이 고민한다. 둘 다 백엔드를 빠르게 만들 수 있게 도와주지만, 내부의 데이터 모델과 개발 방식은 꽤 다르다. 여기에 Neon, MongoDB Atlas, Cloudflare D1 같은 선택지도 함께 비교해야 실제 프로젝트에 맞는 결정을 할 수 있다.&lt;/p&gt;

  &lt;p&gt;이 글은 특정 서비스를 홍보하려는 글이 아니다. 내가 영어 학습 앱을 만들면서 직접 고민했던 기준을 바탕으로, 데이터베이스를 처음 고르는 사람이 실수하지 않도록 Supabase와 Firebase를 중심으로 차이를 쉽게 정리했다. 제품 정보는 2026년 6월 기준 각 서비스의 공식 문서를 확인해 작성했으며, 가격처럼 자주 바뀌는 항목은 반드시 원문을 다시 확인하길 권한다.&lt;/p&gt;

  &lt;div class=&quot;hb-note-box&quot;&gt;
    &lt;p&gt;&lt;strong&gt;짧은 결론부터 말하면&lt;/strong&gt;&lt;/p&gt;
    &lt;p&gt;데이터가 표처럼 나뉘고 서로 관계가 많다면 Supabase나 Neon처럼 PostgreSQL 기반 선택지가 이해하기 쉽다. 반대로 모바일 앱, 실시간 업데이트, 오프라인 동기화, 문서 단위 저장이 중요하면 Firebase의 Firestore가 편할 수 있다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2&gt;먼저, Supabase와 Firebase는 “DB 하나”가 아니다&lt;/h2&gt;

  &lt;p&gt;Supabase와 Firebase를 비교할 때 가장 흔한 오해가 있다. 둘 다 단순한 데이터베이스 상품 하나가 아니라, 앱을 만들기 위한 백엔드 플랫폼에 가깝다는 점이다.&lt;/p&gt;

  &lt;p&gt;Supabase는 PostgreSQL 데이터베이스를 중심에 두고 Auth(인증), Storage(파일 저장), Realtime(실시간), Edge Functions 같은 기능을 함께 제공하는 오픈소스 플랫폼이다. 공식 문서에서도 모든 Supabase 프로젝트는 추상화된 무언가가 아니라 “완전한 PostgreSQL 데이터베이스”를 갖는다고 설명한다.&lt;/p&gt;

  &lt;p&gt;Firebase는 Google의 앱 개발 플랫폼이다. Authentication, Firestore, Realtime Database, Storage, Cloud Functions, Hosting, Analytics 같은 여러 기능을 묶어 제공한다. 그중 데이터베이스 비교에서 가장 자주 등장하는 것은 Cloud Firestore와 Realtime Database다.&lt;/p&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;Supabase, Firebase, Firebase SQL Connect의 대표 데이터베이스와 데이터 모델 비교&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;구분&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;대표 데이터베이스&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;데이터 모델&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;플랫폼 성격&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Supabase&lt;/td&gt;
          &lt;td&gt;PostgreSQL&lt;/td&gt;
          &lt;td&gt;관계형(SQL)&lt;/td&gt;
          &lt;td&gt;Postgres 중심의 오픈소스 백엔드 플랫폼&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Firebase&lt;/td&gt;
          &lt;td&gt;Cloud Firestore, Realtime Database&lt;/td&gt;
          &lt;td&gt;문서형(NoSQL)&lt;/td&gt;
          &lt;td&gt;모바일·웹 앱을 위한 Google 백엔드 플랫폼&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Firebase SQL Connect&lt;/td&gt;
          &lt;td&gt;Cloud SQL for PostgreSQL&lt;/td&gt;
          &lt;td&gt;관계형(SQL)&lt;/td&gt;
          &lt;td&gt;Firebase 안에서 PostgreSQL을 쓰는 별도 선택지&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;p&gt;여기서 알아둘 최신 변화가 하나 있다. Firebase에도 PostgreSQL 기반 관계형 데이터베이스 서비스가 있다. 이전에는 &lt;strong&gt;Firebase Data Connect&lt;/strong&gt;라는 이름이었는데, 2026년 4월 Cloud Next에서 &lt;strong&gt;Firebase SQL Connect&lt;/strong&gt;로 명칭이 바뀌었다. 내부적으로는 Cloud SQL for PostgreSQL을 사용한다. 그래서 “Firebase는 무조건 NoSQL만 가능하다”라고 말하면 더 이상 정확하지 않다.&lt;/p&gt;

  &lt;p&gt;다만 일반적인 Firebase 앱 개발에서 가장 많이 쓰이는 데이터베이스는 여전히 Firestore다. 그래서 이 글에서는 실무에서 흔히 비교하는 기준대로 Supabase의 PostgreSQL과 Firebase의 Firestore를 중심으로 설명하되, SQL Connect도 필요한 곳에서 함께 언급하겠다.&lt;/p&gt;

  &lt;h2&gt;SQL과 NoSQL 차이를 실제 앱 기준으로 이해하기&lt;/h2&gt;

  &lt;p&gt;SQL과 NoSQL이라는 말은 어렵게 들리지만, 처음에는 “내 데이터가 어떻게 생겼는가”로 판단하면 충분하다.&lt;/p&gt;

  &lt;blockquote class=&quot;hb-pull&quot;&gt;SQL은 여러 표 사이의 관계를 다루기 좋고, NoSQL은 문서 단위로 빠르게 저장하고 동기화하기 좋다.&lt;/blockquote&gt;

  &lt;p&gt;SQL 데이터베이스는 엑셀 시트를 여러 장 만들고, 그 시트들을 서로 연결한다고 생각하면 쉽다. 예를 들어 쇼핑몰이라면 사용자, 상품, 주문, 결제, 배송 주소가 서로 연결된다. 이런 데이터는 중복을 줄이고 관계를 명확히 만드는 것이 중요하다.&lt;/p&gt;

  &lt;p&gt;NoSQL 데이터베이스는 JSON 문서를 모아두는 구조에 가깝다. 채팅 앱에서 메시지 하나, 알림 하나, 피드 글 하나를 문서로 저장하는 식이다. 문서 자체가 화면에 바로 필요한 정보를 충분히 담고 있으면 개발이 빨라진다.&lt;/p&gt;

  &lt;p&gt;어느 한쪽이 무조건 더 좋은 것은 아니다. SQL은 관계가 명확해지는 대신 처음에 설계가 필요하다. NoSQL은 시작이 빠른 대신, 데이터 관계가 복잡해질수록 중복 저장과 쿼리 설계를 신경 써야 한다.&lt;/p&gt;

  &lt;h2&gt;한눈에 보는 데이터베이스 선택표&lt;/h2&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;Supabase, Firebase Firestore, Firebase SQL Connect, Neon, MongoDB Atlas, Cloudflare D1 비교&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;선택지&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;쉽게 말하면&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;잘 맞는 프로젝트&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;주의할 점&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Supabase&lt;/td&gt;
          &lt;td&gt;PostgreSQL에 Auth·API·Storage·Realtime을 붙인 플랫폼&lt;/td&gt;
          &lt;td&gt;SaaS, 관리자 페이지, 학습 기록, 예약, 결제, 권한 관리&lt;/td&gt;
          &lt;td&gt;RLS 정책을 정확히 이해해야 한다&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Firebase Firestore&lt;/td&gt;
          &lt;td&gt;실시간 동기화에 강한 문서형 NoSQL 데이터베이스&lt;/td&gt;
          &lt;td&gt;모바일 앱, 채팅, 알림, 실시간 피드, 빠른 MVP&lt;/td&gt;
          &lt;td&gt;JOIN 중심의 SQL과 다르게 설계해야 한다&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Firebase SQL Connect&lt;/td&gt;
          &lt;td&gt;Firebase 안에서 쓰는 PostgreSQL 기반 관계형 서비스&lt;/td&gt;
          &lt;td&gt;Firebase 인증과 함께 관계형 데이터가 필요한 앱&lt;/td&gt;
          &lt;td&gt;Firestore와 개발 방식이 달라 별도 학습이 필요하다&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Neon&lt;/td&gt;
          &lt;td&gt;서버리스 PostgreSQL 데이터베이스&lt;/td&gt;
          &lt;td&gt;백엔드는 직접 만들고 DB만 Postgres로 쓰고 싶을 때&lt;/td&gt;
          &lt;td&gt;Auth·Storage까지 한 번에 주는 플랫폼은 아니다&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;MongoDB Atlas&lt;/td&gt;
          &lt;td&gt;관리형 MongoDB 문서 데이터베이스&lt;/td&gt;
          &lt;td&gt;유연한 문서 구조, 콘텐츠 메타데이터, 가변 속성 데이터&lt;/td&gt;
          &lt;td&gt;문서에 넣을 것과 분리할 것을 정해야 한다&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Cloudflare D1&lt;/td&gt;
          &lt;td&gt;Workers·Pages와 쓰기 좋은 서버리스 SQL 데이터베이스&lt;/td&gt;
          &lt;td&gt;Cloudflare Workers 기반 API, 가벼운 SQL 저장소&lt;/td&gt;
          &lt;td&gt;대형 앱 백엔드 전체를 대신하는 플랫폼은 아니다&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;p&gt;이 표에서 봐야 할 것은 브랜드 이름이 아니라 “내 앱의 데이터가 어떤 모양인가”다. 같은 로그인 기능이 있어도 학습 기록 앱과 채팅 앱은 데이터베이스 선택 기준이 달라진다.&lt;/p&gt;

  &lt;h2&gt;Supabase가 좋은 경우: 관계가 많은 데이터&lt;/h2&gt;

  &lt;p&gt;Supabase의 가장 큰 장점은 PostgreSQL을 그대로 쓴다는 점이다. 테이블, 외래 키, 인덱스, JOIN, 트랜잭션, 뷰, 함수 같은 관계형 데이터베이스 기능을 제대로 사용할 수 있다.&lt;/p&gt;

  &lt;p&gt;예를 들어 사용자가 있고, 사용자가 여러 프로젝트를 만들고, 각 프로젝트 안에 태스크가 있고, 태스크마다 댓글과 파일이 붙는다고 해보자. 이 구조는 관계형 데이터베이스로 표현하기 쉽다. &lt;code&gt;users&lt;/code&gt;, &lt;code&gt;projects&lt;/code&gt;, &lt;code&gt;tasks&lt;/code&gt;, &lt;code&gt;comments&lt;/code&gt;, &lt;code&gt;files&lt;/code&gt; 테이블을 만들고 서로 연결하면 된다.&lt;/p&gt;

  &lt;div class=&quot;hb-note-box&quot;&gt;
    &lt;p&gt;&lt;strong&gt;Supabase를 먼저 검토할 만한 경우&lt;/strong&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;데이터를 표로 나누면 구조가 자연스럽다.&lt;/li&gt;
      &lt;li&gt;사용자별 권한과 공개 범위를 엄격하게 나눠야 한다.&lt;/li&gt;
      &lt;li&gt;관리자 페이지나 대시보드를 만들 계획이 있다.&lt;/li&gt;
      &lt;li&gt;통계, 필터, 정렬, 검색 조건이 점점 늘어날 가능성이 있다.&lt;/li&gt;
      &lt;li&gt;SQL을 직접 보고 디버깅하는 편이 마음이 편하다.&lt;/li&gt;
      &lt;li&gt;나중에 다른 PostgreSQL 서비스로 옮길 가능성도 고려한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;

  &lt;p&gt;Supabase에서 반드시 이해해야 할 개념은 &lt;strong&gt;RLS, 즉 Row Level Security&lt;/strong&gt;다. 브라우저에서 Supabase 클라이언트로 데이터에 직접 접근하는 구조라면 “이 사용자는 자기 데이터만 읽을 수 있다” 같은 규칙을 데이터베이스 레벨에서 걸어야 한다. 공식 문서도 외부에 노출되는 스키마의 테이블에는 RLS를 활성화하도록 강하게 권장한다.&lt;/p&gt;

  &lt;p&gt;RLS는 강력하지만 처음에는 어렵다. 정책을 잘못 만들면 데이터가 전혀 보이지 않거나, 반대로 보여서는 안 되는 데이터가 노출될 수 있다. 그래서 Supabase를 쓴다면 테이블 설계만큼이나 권한 정책 설계를 신중하게 해야 한다.&lt;/p&gt;

  &lt;h2&gt;Firebase Firestore가 좋은 경우: 실시간 앱과 모바일 경험&lt;/h2&gt;

  &lt;p&gt;Firebase Firestore는 문서형 NoSQL 데이터베이스다. 공식 문서에 따르면 Firestore는 모바일·웹·서버 개발을 위한 확장 가능한 NoSQL 클라우드 데이터베이스이며, 실시간 리스너와 오프라인 지원을 제공한다.&lt;/p&gt;

  &lt;p&gt;Firestore의 매력은 앱 화면과 데이터 흐름이 잘 맞을 때 크게 느껴진다. 예를 들어 채팅방 화면에서 새 메시지가 오면 즉시 화면에 추가되어야 한다. 이런 경우 문서 하나가 메시지 하나가 되고, 클라이언트는 해당 컬렉션을 구독하면 된다.&lt;/p&gt;

  &lt;div class=&quot;hb-note-box&quot;&gt;
    &lt;p&gt;&lt;strong&gt;Firebase Firestore를 먼저 검토할 만한 경우&lt;/strong&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;모바일 앱 중심으로 개발한다.&lt;/li&gt;
      &lt;li&gt;실시간 업데이트가 앱의 핵심 경험이다.&lt;/li&gt;
      &lt;li&gt;오프라인 상태에서도 읽기·쓰기가 어느 정도 자연스럽게 동작해야 한다.&lt;/li&gt;
      &lt;li&gt;데이터가 문서 단위로 읽히고 쓰인다.&lt;/li&gt;
      &lt;li&gt;Firebase Authentication, Cloud Messaging, Analytics와 함께 쓰고 싶다.&lt;/li&gt;
      &lt;li&gt;SQL보다 SDK와 보안 규칙 중심 개발이 편하다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;

  &lt;p&gt;다만 Firestore는 SQL처럼 JOIN을 중심으로 생각하는 데이터베이스가 아니다. 화면에서 필요한 데이터를 빠르게 가져오기 위해 일부 데이터를 문서에 중복 저장하는 설계를 하기도 한다. 이 방식은 성능과 개발 속도에는 도움이 되지만, 중복된 데이터의 동기화를 직접 관리해야 할 때가 있다.&lt;/p&gt;

  &lt;p&gt;예를 들어 게시글 목록에 작성자 이름을 바로 보여주고 싶다면, 게시글 문서 안에 &lt;code&gt;authorName&lt;/code&gt;을 함께 넣을 수 있다. 하지만 사용자가 이름을 바꾸면 기존 게시글 문서들의 작성자 이름도 함께 업데이트할지 결정해야 한다. Firestore에서는 이런 데이터 중복이 자연스러운 설계가 될 수 있지만, SQL에 익숙한 사람에게는 처음에 낯설다.&lt;/p&gt;

  &lt;h2&gt;같은 영어 학습 앱을 두 방식으로 설계해보면&lt;/h2&gt;

  &lt;p&gt;내가 Supabase를 선택한 이유는 영어 학습 앱의 데이터가 문서보다 테이블에 가까웠기 때문이다. 단어장, 문장 암기장, 복습 기록, 사용자 설정, 학습 통계가 서로 연결되어 있었다.&lt;/p&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;영어 학습 앱을 Supabase PostgreSQL과 Firestore로 설계할 때의 차이&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;기능&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;Supabase·PostgreSQL식 설계&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;Firestore식 설계&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;단어장&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;vocabulary&lt;/code&gt; 테이블에 사용자 ID·단어·뜻·예문·복습 상태 저장&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;users/{userId}/vocabulary/{wordId}&lt;/code&gt; 문서로 저장&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;복습 기록&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;study_history&lt;/code&gt; 테이블에 단어 ID와 날짜별 결과 저장&lt;/td&gt;
          &lt;td&gt;단어 문서의 하위 컬렉션 또는 별도 기록 컬렉션으로 저장&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;통계&lt;/td&gt;
          &lt;td&gt;SQL 집계 쿼리로 날짜별·단어별·사용자별 통계 조회&lt;/td&gt;
          &lt;td&gt;미리 계산한 통계 문서를 따로 저장하는 방식이 필요할 수 있음&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;권한&lt;/td&gt;
          &lt;td&gt;RLS 정책으로 &lt;code&gt;auth.uid()&lt;/code&gt;와 &lt;code&gt;user_id&lt;/code&gt; 비교&lt;/td&gt;
          &lt;td&gt;Firestore Security Rules로 사용자 경로와 인증 정보를 비교&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;p&gt;둘 다 구현할 수 있다. 하지만 “오늘 복습할 단어”, “지난 7일간 틀린 단어”, “사용자별 누적 학습량”처럼 통계성 조회가 늘어날수록 나는 SQL 쪽이 더 이해하기 쉬웠다. 그래서 이 앱에서는 Supabase가 더 잘 맞았다.&lt;/p&gt;

  &lt;p&gt;반대로 실시간 채팅, 위치 공유, 짧은 알림 피드가 중심이었다면 Firebase를 먼저 선택했을 가능성이 높다. 앱의 성격이 바뀌면 좋은 데이터베이스도 바뀐다.&lt;/p&gt;

  &lt;h2&gt;비용은 “가격표 숫자”보다 과금 단위를 봐야 한다&lt;/h2&gt;

  &lt;p&gt;데이터베이스 비교에서 가격은 중요하지만, 특정 금액만 보고 판단하면 위험하다. 클라우드 서비스 가격은 자주 바뀌고, 무료 제공량도 지역이나 플랜에 따라 달라질 수 있다. 그래서 글을 읽는 시점에는 반드시 공식 가격 페이지를 확인해야 한다.&lt;/p&gt;

  &lt;p&gt;대신 잘 변하지 않는 비교 기준은 “과금 단위”다. 어떤 서비스는 읽기·쓰기 횟수에 민감하고, 어떤 서비스는 저장 용량이나 컴퓨트 시간에 더 영향을 받는다.&lt;/p&gt;

  &lt;div class=&quot;hb-table-wrap&quot;&gt;
    &lt;table&gt;
      &lt;caption&gt;데이터베이스 서비스별 비용 비교에서 확인해야 할 과금 기준&lt;/caption&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope=&quot;col&quot;&gt;서비스&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;비용을 볼 때 중요한 기준&lt;/th&gt;
          &lt;th scope=&quot;col&quot;&gt;초기 프로젝트에서 체크할 점&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Supabase&lt;/td&gt;
          &lt;td&gt;프로젝트 플랜, 데이터베이스 리소스, 저장소, 대역폭&lt;/td&gt;
          &lt;td&gt;무료 플랜 제한과 백업, 팀 사용, 스토리지 사용량 확인&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Firestore&lt;/td&gt;
          &lt;td&gt;문서 읽기·쓰기·삭제, 저장 용량, 네트워크&lt;/td&gt;
          &lt;td&gt;목록 화면에서 불필요한 문서 읽기가 많이 발생하지 않는지 확인&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Neon&lt;/td&gt;
          &lt;td&gt;컴퓨트 사용량, 저장 용량, 브랜칭 사용 방식&lt;/td&gt;
          &lt;td&gt;서버리스 Postgres가 내 백엔드 구조와 맞는지 확인&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;MongoDB Atlas&lt;/td&gt;
          &lt;td&gt;클러스터 크기, 저장 용량, 백업, 네트워크&lt;/td&gt;
          &lt;td&gt;무료·소형 클러스터로 시작해도 운영 요구사항을 따져보기&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;Cloudflare D1&lt;/td&gt;
          &lt;td&gt;쿼리 수, 저장 용량, Workers·Pages 사용량&lt;/td&gt;
          &lt;td&gt;Cloudflare Workers 기반 앱인지 먼저 확인&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;p&gt;예를 들어 Firestore에서는 화면 하나를 열 때 몇 개의 문서를 읽는지가 비용과 성능 모두에 영향을 준다. Supabase나 Neon 같은 Postgres 기반 서비스에서는 쿼리 최적화, 인덱스, 연결 방식이 중요해진다. 비용 비교는 “어디가 싸다”보다 “내 앱이 어떤 방식으로 많이 쓰는가”를 기준으로 해야 한다.&lt;/p&gt;

  &lt;h2&gt;마이그레이션과 잠금(lock-in) 효과도 미리 생각하자&lt;/h2&gt;

  &lt;p&gt;처음에는 작은 프로젝트라도 나중에 옮겨야 할 수 있다. 이때 PostgreSQL 기반 서비스는 표준 SQL과 Postgres 생태계를 활용할 수 있다는 장점이 있다. Supabase에서 Neon이나 다른 관리형 Postgres로 옮기는 일은 서비스별 기능을 얼마나 썼는지에 따라 난이도가 달라지지만, 데이터베이스 자체가 Postgres라는 점은 분명한 강점이다.&lt;/p&gt;

  &lt;p&gt;Firestore는 Firebase 생태계와 강하게 연결되어 있다. Security Rules, 문서 경로, SDK 사용 방식, 실시간 리스너 구조까지 앱 코드에 녹아들기 쉽다. 덕분에 개발 속도는 빠르지만, 나중에 완전히 다른 데이터베이스로 옮길 때는 데이터 모델과 앱 코드를 함께 바꿔야 할 수 있다.&lt;/p&gt;

  &lt;p&gt;이 말은 Firebase를 피하라는 뜻이 아니다. 오히려 Firebase가 잘 맞는 앱에서는 이 통합성이 큰 장점이다. 다만 장기 운영을 생각한다면 “나중에 옮길 수 있는가”보다 “옮길 필요가 생겼을 때 어느 부분을 다시 설계해야 하는가”를 미리 알고 시작하는 편이 좋다.&lt;/p&gt;

  &lt;h2&gt;Neon, MongoDB Atlas, Cloudflare D1은 언제 보면 좋을까&lt;/h2&gt;

  &lt;p&gt;Supabase와 Firebase만 비교하면 선택지가 단순해 보이지만, 실제로는 다른 데이터베이스가 더 깔끔한 경우도 있다.&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;Neon&lt;/strong&gt;은 서버리스 PostgreSQL이다. 백엔드는 Next.js API, Express, NestJS, Laravel, Django 같은 방식으로 직접 만들고, 데이터베이스만 관리형 Postgres로 쓰고 싶을 때 좋다. Supabase의 Auth나 Storage까지는 필요 없고, Postgres 자체와 브랜칭, 서버리스 운영 경험이 중요하다면 비교해볼 만하다.&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;MongoDB Atlas&lt;/strong&gt;는 관리형 MongoDB 서비스다. 문서형 데이터베이스가 자연스러운 앱, 예를 들어 상품마다 속성이 많이 다르거나 콘텐츠 메타데이터가 유연하게 바뀌는 서비스에서 편하다. Firestore도 문서형이지만, MongoDB Atlas는 Firebase 앱 플랫폼이 아니라 MongoDB 데이터베이스 운영에 초점이 있는 서비스라고 보면 된다.&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;Cloudflare D1&lt;/strong&gt;은 Cloudflare Workers와 Pages 프로젝트에서 쓰기 좋은 서버리스 SQL 데이터베이스다. SQLite의 SQL 의미를 기반으로 하고, Workers에서 가볍게 쿼리하기 좋다. 이미 Cloudflare 생태계로 API를 만들고 있다면 매력적이지만, 인증·파일 저장·복잡한 백엔드 기능까지 한 번에 해결해주는 플랫폼으로 보면 곤란하다.&lt;/p&gt;

  &lt;h2&gt;선택 전에 꼭 던져볼 질문&lt;/h2&gt;

  &lt;ol&gt;
    &lt;li&gt;내 데이터는 표에 가까운가, 문서에 가까운가?&lt;/li&gt;
    &lt;li&gt;사용자·결제·주문·기록처럼 서로 연결되는 데이터가 많은가?&lt;/li&gt;
    &lt;li&gt;실시간 업데이트가 핵심 기능인가, 있으면 좋은 정도인가?&lt;/li&gt;
    &lt;li&gt;모바일 오프라인 지원이 중요한가?&lt;/li&gt;
    &lt;li&gt;데이터를 SQL로 직접 조회하고 분석해야 하는가?&lt;/li&gt;
    &lt;li&gt;인증·파일 저장·서버리스 함수까지 한 플랫폼에서 해결하고 싶은가?&lt;/li&gt;
    &lt;li&gt;초기 개발 속도와 장기 유지보수 중 무엇이 더 중요한가?&lt;/li&gt;
    &lt;li&gt;나중에 다른 데이터베이스로 옮겨야 할 가능성이 있는가?&lt;/li&gt;
    &lt;li&gt;팀원이 SQL에 익숙한가, SDK와 문서 모델에 익숙한가?&lt;/li&gt;
    &lt;li&gt;비용은 저장 용량보다 읽기·쓰기 횟수에 더 민감한 구조인가?&lt;/li&gt;
  &lt;/ol&gt;

  &lt;p&gt;이 질문에 답하면 선택지는 꽤 좁혀진다. 데이터베이스 선택은 유행을 따라가는 일이 아니라, 내 데이터의 모양과 앱의 사용 패턴을 맞추는 일이다.&lt;/p&gt;

  &lt;h2&gt;내 기준의 최종 정리&lt;/h2&gt;

  &lt;div class=&quot;hb-checklist&quot;&gt;
    &lt;p&gt;&lt;strong&gt;Supabase를 고를 때&lt;/strong&gt;&lt;br&gt;관계형 데이터가 많고, SQL로 구조를 명확히 잡고 싶고, 사용자별 권한을 데이터베이스 레벨에서 관리하고 싶을 때 좋다. 학습 기록, SaaS, 관리자 대시보드, 예약, 결제, CRM처럼 테이블 관계가 선명한 서비스에 잘 맞는다.&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;Firebase Firestore를 고를 때&lt;/strong&gt;&lt;br&gt;모바일 앱 중심이고, 실시간 동기화와 오프라인 경험이 중요하며, 문서 단위로 데이터를 읽고 쓰는 앱에 잘 맞는다. 채팅, 알림, 간단한 피드, 실시간 협업처럼 화면 변화가 빠른 앱에서 강하다.&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;Firebase SQL Connect를 볼 때&lt;/strong&gt;&lt;br&gt;Firebase 생태계는 유지하고 싶지만, Firestore보다 관계형 데이터 모델이 필요한 경우에 검토할 만하다. Firebase Authentication과 PostgreSQL 기반 관계형 데이터를 함께 쓰고 싶은 팀에게 의미가 있다.&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;Neon을 볼 때&lt;/strong&gt;&lt;br&gt;백엔드는 직접 만들고, 데이터베이스만 서버리스 Postgres로 쓰고 싶을 때 좋다. Supabase의 전체 플랫폼보다 데이터베이스 중심 선택이 필요할 때 비교하면 된다.&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;MongoDB Atlas를 볼 때&lt;/strong&gt;&lt;br&gt;문서 구조가 자연스럽고, 데이터 형태가 자주 바뀌거나 항목마다 속성이 다른 서비스에 적합하다. 다만 관계가 많은 앱에서는 문서 설계를 신중히 해야 한다.&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;Cloudflare D1을 볼 때&lt;/strong&gt;&lt;br&gt;Cloudflare Workers나 Pages 기반으로 가벼운 SQL 데이터 저장소가 필요할 때 좋다. Cloudflare 생태계 밖의 일반적인 앱 백엔드 전체를 대체하려는 목적이라면 다른 선택지도 함께 봐야 한다.&lt;/p&gt;
  &lt;/div&gt;

  &lt;h2&gt;자주 하는 오해&lt;/h2&gt;

  &lt;h3&gt;1. Supabase는 Firebase의 완전한 대체품인가?&lt;/h3&gt;
  &lt;p&gt;비슷한 문제를 해결하지만 완전히 같은 제품은 아니다. Supabase는 Postgres 중심이고, Firebase는 모바일·웹 앱 플랫폼으로서 실시간 동기화와 Google 생태계 통합이 강하다.&lt;/p&gt;

  &lt;h3&gt;2. Firebase는 SQL을 전혀 못 쓰는가?&lt;/h3&gt;
  &lt;p&gt;아니다. Firebase SQL Connect(옛 Data Connect)는 Cloud SQL for PostgreSQL 기반 관계형 데이터베이스 서비스를 제공한다. 다만 일반적인 Firestore 개발 방식과는 다르다.&lt;/p&gt;

  &lt;h3&gt;3. NoSQL은 SQL보다 쉬운가?&lt;/h3&gt;
  &lt;p&gt;처음 시작은 쉬울 수 있지만, 데이터가 커지고 관계가 많아지면 설계 난이도가 올라간다. 특히 중복 저장, 보안 규칙, 쿼리 제한을 이해해야 한다.&lt;/p&gt;

  &lt;h3&gt;4. PostgreSQL을 쓰면 무조건 확장성이 떨어지는가?&lt;/h3&gt;
  &lt;p&gt;그렇지 않다. PostgreSQL은 오래 검증된 데이터베이스이고, Supabase와 Neon 같은 서비스는 운영 부담을 줄여준다. 다만 실시간 모바일 동기화 같은 특정 경험은 Firebase가 더 빠르게 제공할 수 있다.&lt;/p&gt;

  &lt;h3&gt;5. 개인 프로젝트에서는 무엇을 고르면 좋은가?&lt;/h3&gt;
  &lt;p&gt;학습 목적이고 데이터가 표처럼 보인다면 Supabase를 추천하기 쉽고, 모바일 실시간 앱을 빨리 만들고 싶다면 Firebase가 편하다. 이미 Next.js나 백엔드를 직접 만들고 있다면 Neon도 좋은 선택지다.&lt;/p&gt;

  &lt;h2&gt;결론: 데이터베이스 선택은 유행이 아니라 데이터 모양의 문제다&lt;/h2&gt;

  &lt;p&gt;Supabase와 Firebase는 둘 다 훌륭한 도구다. 하지만 같은 문제를 같은 방식으로 해결하지 않는다.&lt;/p&gt;

  &lt;p&gt;Supabase는 PostgreSQL을 중심으로 관계형 데이터를 명확하게 다루고 싶은 사람에게 잘 맞는다. SQL, 테이블 관계, RLS, 관리자 화면, 통계 조회가 중요하다면 좋은 선택이다.&lt;/p&gt;

  &lt;p&gt;Firebase Firestore는 실시간 앱과 모바일 경험에 강하다. 문서 단위 데이터, 실시간 리스너, 오프라인 지원, Firebase 생태계와의 통합이 중요하다면 매우 빠르게 개발할 수 있다.&lt;/p&gt;

  &lt;p&gt;Neon, MongoDB Atlas, Cloudflare D1은 각각 Postgres 중심, 문서형 데이터 중심, Cloudflare Workers 중심이라는 분명한 색깔이 있다. 그래서 선택할 때는 먼저 내 앱의 데이터가 어떻게 생겼는지 그려보는 것이 가장 좋다.&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;내 데이터가 표처럼 보이면 SQL 계열을, 문서처럼 보이고 실시간 화면 변화가 중요하면 NoSQL 계열을 먼저 검토하자. 이 기준 하나만 잡아도 데이터베이스 선택에서 크게 헤매지 않는다.&lt;/strong&gt;&lt;/p&gt;

  &lt;section class=&quot;hb-references&quot;&gt;
    &lt;h2&gt;참고한 공식 문서&lt;/h2&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://supabase.com/docs/guides/database/overview&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Supabase Database Overview&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://supabase.com/docs/guides/database/postgres/row-level-security&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Supabase Row Level Security&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://firebase.google.com/docs/firestore&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Firebase Cloud Firestore 문서&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://firebase.google.com/docs/sql-connect&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Firebase SQL Connect 문서&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://neon.com/docs/introduction&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Neon 공식 문서&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.mongodb.com/docs/atlas/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;MongoDB Atlas 공식 문서&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://developers.cloudflare.com/d1/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Cloudflare D1 공식 문서&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
    &lt;p class=&quot;hb-disclaimer&quot;&gt;※ 이 글은 개인 개발 경험과 2026년 6월 기준 공식 문서를 참고해 작성한 정보성 콘텐츠입니다. 제품 사양과 가격은 변경될 수 있으니 도입 전 각 서비스의 공식 문서를 다시 확인하시기 바랍니다.&lt;/p&gt;
  &lt;/section&gt;
&lt;/article&gt;</description>
      <category>AI</category>
      <category>Firebase</category>
      <category>데이터베이스 #SUPABASE #MONGODB</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/89</guid>
      <comments>https://onethingflow.tistory.com/entry/Supabase-Firebase-MongoDB-%EB%93%B1-%EC%96%B4%EB%96%A4-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%B4%9D%EC%A0%95%EB%A6%AC#entry89comment</comments>
      <pubDate>Sun, 7 Jun 2026 00:56:07 +0900</pubDate>
    </item>
    <item>
      <title>옵시디언 PC 안드로이드 동기화 방법 총정리(Google Drive + Syncthing)</title>
      <link>https://onethingflow.tistory.com/entry/%EC%98%B5%EC%8B%9C%EB%94%94%EC%96%B8-PC-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EB%8F%99%EA%B8%B0%ED%99%94-%EB%B0%A9%EB%B2%95-%EC%B4%9D%EC%A0%95%EB%A6%ACGoogle-Drive-Syncthing</link>
      <description>&lt;!--
Title: 옵시디언 PC·노트북·안드로이드 동기화 완전 정리: Google Drive + Syncthing 실전 설정과 오류 해결
Tags: 옵시디언, Obsidian, Syncthing, Syncthing-Fork, Google Drive, 구글 드라이브, 안드로이드 동기화, 노트 동기화
--&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;obsidian-sync-post&quot; style=&quot;max-width: 700px; margin: 0 auto; padding: 0 24px 80px; color: #333; font-family: AppleSDGothicNeo, Pretendard-Regular, sans-serif; line-height: 1.82;&quot;&gt;
&lt;div style=&quot;display: inline-block; margin: 0 0 18px; padding: 4px 14px; border-radius: 20px; background: #ede8f8; color: #5b3fa8; font-size: 14px; font-weight: bold;&quot;&gt;Obsidian &amp;middot; Windows &amp;middot; Android&lt;/div&gt;
&lt;h1 style=&quot;margin: 0 0 12px; color: #1a1a1a; font-size: 34px; line-height: 1.28; letter-spacing: 0;&quot;&gt;옵시디언 PC&amp;middot;노트북&amp;middot;안드로이드 동기화 완전 정리&lt;/h1&gt;
&lt;p style=&quot;margin: 0 0 20px; color: #555; font-size: 18px; line-height: 1.7;&quot; data-ke-size=&quot;size16&quot;&gt;Google Drive와 Syncthing을 같이 쓸 때 헷갈리는 지점, 특히 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Up to Date&lt;/code&gt;, &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Disconnected&lt;/code&gt;, &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Paused&lt;/code&gt;, &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;sync-conflict&lt;/code&gt;를 실제 설정 흐름대로 정리했다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 28px; color: #888; font-size: 14px;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 28px; color: #888; font-size: 14px;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 28px; color: #888; font-size: 14px;&quot; data-ke-size=&quot;size16&quot;&gt;2026년 6월 21일 업데이트 &amp;middot; Windows PC/노트북 + Android 기준 &amp;middot; 약 15분&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 18px;&quot; data-ke-size=&quot;size16&quot;&gt;기존 컴퓨터와 안드로이드 휴대폰에서 쓰던 Obsidian Vault를 새 노트북에도 연결해야 했다. 처음에는 Syncthing 화면에서 폴더가 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Up to Date&lt;/code&gt;로 떠서 설정이 끝난 줄 알았다. 그런데 휴대폰은 계속 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Disconnected&lt;/code&gt;였고, 파일은 움직이지 않았다.&lt;/p&gt;
&lt;p style=&quot;margin: 0 0 26px;&quot; data-ke-size=&quot;size16&quot;&gt;Device ID, Folder ID, Windows 방화벽, 배터리 설정을 하나씩 확인했지만 원인은 더 단순했다. 휴대폰 Syncthing-Fork에서 새 노트북 기기와 Obsidian 폴더가 둘 다 &lt;b&gt;Paused 상태&lt;/b&gt;였다. Windows 화면의 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Pause&lt;/code&gt; 버튼은 &quot;누르면 멈춤&quot;이라는 뜻이고, Android 화면의 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Paused&lt;/code&gt; 표시는 &quot;이미 멈춰 있음&quot;이라는 뜻이다. 이 차이 때문에 꽤 오래 돌아갔다.&lt;/p&gt;
&lt;div style=&quot;margin: 30px 0; overflow: hidden; border-radius: 8px; background: #1e1e2e; color: #cdd6f4;&quot;&gt;
&lt;div style=&quot;padding: 9px 16px; background: rgba(255,255,255,.06); color: #fff; font-weight: bold;&quot;&gt;먼저 결론&lt;/div&gt;
&lt;div style=&quot;padding: 20px;&quot;&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;기존 컴퓨터와 새 노트북은 &lt;b&gt;동일한 Google Drive Vault 폴더&lt;/b&gt;를 사용한다. 그리고 휴대폰은 Google Drive 폴더를 직접 여는 대신, 노트북과 &lt;b&gt;Syncthing-Fork&lt;/b&gt;로 양방향 동기화한다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;margin: 28px 0 38px; padding: 22px 24px; border: 1px solid rgba(124,92,191,.2); border-radius: 12px; background: #fff;&quot;&gt;
&lt;div style=&quot;margin-bottom: 12px; color: #1a1a1a; font-size: 20px; font-weight: 800;&quot;&gt;목차&lt;/div&gt;
&lt;ol style=&quot;margin: 0; padding-left: 20px;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;a style=&quot;color: #5b3fa8; text-decoration: none;&quot; href=&quot;#final-structure&quot;&gt;최종 동기화 구조&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #5b3fa8; text-decoration: none;&quot; href=&quot;#google-drive-folder&quot;&gt;같은 Google Drive 폴더를 써야 하는 이유&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #5b3fa8; text-decoration: none;&quot; href=&quot;#offline&quot;&gt;Google Drive 오프라인 설정&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #5b3fa8; text-decoration: none;&quot; href=&quot;#syncthing-basic&quot;&gt;Syncthing 기본 설정&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #5b3fa8; text-decoration: none;&quot; href=&quot;#id-difference&quot;&gt;Device ID와 Folder ID 구분&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #5b3fa8; text-decoration: none;&quot; href=&quot;#paused&quot;&gt;Up to Date인데 연결되지 않았던 이유&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #5b3fa8; text-decoration: none;&quot; href=&quot;#conflicts&quot;&gt;14 conflicts 처리 방법&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #5b3fa8; text-decoration: none;&quot; href=&quot;#checklist&quot;&gt;최종 점검표&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h2 id=&quot;final-structure&quot; style=&quot;margin: 42px 0 14px; color: #1a1a1a; font-size: 26px; line-height: 1.35;&quot; data-ke-size=&quot;size26&quot;&gt;1. 최종 동기화 구조&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 구성은 한 문장으로 말하면, &lt;b&gt;Windows끼리는 Google Drive, Android는 Syncthing&lt;/b&gt;이다.&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot; style=&quot;margin: 22px 0; padding: 20px; overflow-x: auto; border-radius: 8px; background: #1e1e2e; color: #cdd6f4; font-size: 15px; line-height: 1.75;&quot;&gt;&lt;code&gt;기존 컴퓨터 ⇄ Google Drive ⇄ 새 노트북
                                  ⇅ Syncthing
                              안드로이드폰&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;overflow-x: auto; margin: 24px 0;&quot;&gt;
&lt;table style=&quot;width: 100%; min-width: 620px; border-collapse: collapse; font-size: 15px;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;구간&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;담당&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;역할&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;기존 컴퓨터 &amp;harr; 새 노트북&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;Google Drive for desktop&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;같은 클라우드 Vault를 두 Windows 기기에 반영&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;새 노트북 &amp;harr; 안드로이드폰&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;Syncthing / Syncthing-Fork&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;노트북의 Google Drive 폴더와 휴대폰 내부 폴더를 양방향 동기화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;Obsidian&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;각 기기의 로컬 폴더 열기&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;실제 노트 작성과 편집&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;휴대폰에서 수정한 노트는 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;휴대폰 &amp;rarr; 노트북 &amp;rarr; Google Drive &amp;rarr; 기존 컴퓨터&lt;/code&gt; 순서로 전달된다. 반대로 기존 컴퓨터에서 수정한 노트는 Google Drive를 거쳐 노트북에 내려오고, 노트북이 켜져 있을 때 Syncthing으로 휴대폰까지 전달된다.&lt;/p&gt;
&lt;div style=&quot;margin: 24px 0; padding: 18px 20px; border-radius: 8px; background: #fef3eb;&quot;&gt;&lt;b&gt;중요한 전제&lt;/b&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;노트북이 꺼져 있으면 휴대폰 변경 사항은 기존 컴퓨터로 바로 넘어가지 않는다. 노트북이 켜지고 Google Drive와 Syncthing이 모두 실행되어야 밀린 변경 사항이 이어서 반영된다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;google-drive-folder&quot; style=&quot;margin: 42px 0 14px; color: #1a1a1a; font-size: 26px; line-height: 1.35;&quot; data-ke-size=&quot;size26&quot;&gt;2. 같은 Google Drive 폴더를 써야 하는 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 Windows 기기에서 아래처럼 같은 Vault를 열면 된다. 드라이브 문자는 컴퓨터마다 달라도 괜찮다. 핵심은 Google Drive 안에서 &lt;b&gt;같은 클라우드 폴더&lt;/b&gt;여야 한다는 점이다.&lt;/p&gt;
&lt;pre class=&quot;livescript&quot; style=&quot;margin: 22px 0; padding: 20px; overflow-x: auto; border-radius: 8px; background: #1e1e2e; color: #cdd6f4; font-size: 15px; line-height: 1.75;&quot;&gt;&lt;code&gt;G:\내 드라이브\obsidian_vault_real_v1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Obsidian_PC&lt;/code&gt;, &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Obsidian_Laptop&lt;/code&gt;처럼 폴더를 두 벌 만들면 어느 쪽이 진짜 최신인지 매번 확인해야 한다. 그 두 폴더를 다시 Syncthing으로 맞추기 시작하면 구조가 꼬인다. 백업용 복사본은 따로 만들 수 있지만, 실제로 글을 쓰는 Vault는 하나로 유지하는 편이 훨씬 안전하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 여기서 조심해야 할 점이 있다. &quot;Google Drive와 Syncthing을 같이 쓰면 무조건 안 된다&quot;가 아니다. 문제가 되는 것은 &lt;b&gt;같은 두 기기 사이를 Google Drive와 Syncthing이 동시에 물고 있는 구조&lt;/b&gt;다. 이 글의 구성은 역할을 나눴다. Windows PC끼리는 Google Drive, 노트북과 Android 사이만 Syncthing이다.&lt;/p&gt;
&lt;h2 id=&quot;offline&quot; style=&quot;margin: 42px 0 14px; color: #1a1a1a; font-size: 26px; line-height: 1.35;&quot; data-ke-size=&quot;size26&quot;&gt;3. Google Drive 폴더를 오프라인으로 설정하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Obsidian은 로컬 폴더 안의 Markdown 파일을 직접 읽고 쓴다. 그래서 Google Drive 스트리밍 모드에서 파일이 필요할 때만 내려오는 상태라면, Vault 파일이 늦게 열리거나 일부 파일이 아직 없는 것처럼 보일 수 있다. Vault 폴더는 오프라인 사용 가능 상태로 두는 편이 좋다.&lt;/p&gt;
&lt;ol style=&quot;margin: 18px 0; padding-left: 22px;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Windows 파일 탐색기에서 Obsidian Vault 폴더로 이동한다.&lt;/li&gt;
&lt;li&gt;Vault 폴더를 우클릭한다.&lt;/li&gt;
&lt;li&gt;Windows 11에서는 필요하면 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;더 많은 옵션 표시&lt;/code&gt;를 누른다.&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Google Drive &amp;rarr; 오프라인 액세스 &amp;rarr; 오프라인으로 사용 가능&lt;/code&gt;을 선택한다.&lt;/li&gt;
&lt;li&gt;초록색 체크 표시가 뜰 때까지 기다린다.&lt;/li&gt;
&lt;/ol&gt;
&lt;div style=&quot;margin: 24px 0; padding: 18px 20px; border-radius: 8px; background: #e8f5ee;&quot;&gt;&lt;b&gt;스트리밍과 미러링의 차이&lt;/b&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;스트리밍은 클라우드에 있는 파일을 필요한 만큼만 로컬에 둔다. 미러링은 클라우드와 컴퓨터 양쪽에 파일을 둔다. Google 문서에 따르면 미러링한 파일과 폴더는 기본적으로 오프라인에서 사용할 수 있고, 스트리밍을 쓸 때는 필요한 항목을 오프라인 사용 가능으로 지정할 수 있다.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Available offline&lt;/code&gt;은 충돌 방지 기능이 아니다. 두 기기가 오프라인 상태에서 같은 Markdown 파일을 따로 수정하면, 나중에 한쪽 수정 내용을 별도로 정리해야 할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;syncthing-basic&quot; style=&quot;margin: 42px 0 14px; color: #1a1a1a; font-size: 26px; line-height: 1.35;&quot; data-ke-size=&quot;size26&quot;&gt;4. Windows에 Syncthing 설치하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Windows에 Syncthing을 설치하고 실행하면 보통 아래 주소에서 관리 화면이 열린다.&lt;/p&gt;
&lt;pre class=&quot;dts&quot; style=&quot;margin: 22px 0; padding: 20px; overflow-x: auto; border-radius: 8px; background: #1e1e2e; color: #cdd6f4; font-size: 15px; line-height: 1.75;&quot;&gt;&lt;code&gt;http://127.0.0.1:8384/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;127.0.0.1&lt;/code&gt;은 현재 컴퓨터 자신을 뜻하고, &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;8384&lt;/code&gt;는 Syncthing 웹 관리 화면 포트다. 파일 동기화에 쓰이는 대표 포트는 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;22000&lt;/code&gt;이다. 그래서 브라우저에서 관리 화면이 열린다고 해서 휴대폰과 파일 동기화까지 성공했다는 뜻은 아니다.&lt;/p&gt;
&lt;div style=&quot;margin: 24px 0; padding: 18px 20px; border-radius: 8px; background: #fef3eb;&quot;&gt;&lt;b&gt;주소를 헷갈리지 말기&lt;/b&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;Syncthing의 기본 GUI Listen Address는 공식 문서 기준 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;127.0.0.1:8384&lt;/code&gt;다. 기본 접속은 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;http://&lt;/code&gt;로 열면 된다.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;id-difference&quot; style=&quot;margin: 42px 0 14px; color: #1a1a1a; font-size: 26px; line-height: 1.35;&quot; data-ke-size=&quot;size26&quot;&gt;5. Device ID와 Folder ID를 구분하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 설정할 때 가장 많이 헷갈리는 부분이다. 이름이 비슷하지만 역할이 완전히 다르다.&lt;/p&gt;
&lt;div style=&quot;overflow-x: auto; margin: 24px 0;&quot;&gt;
&lt;table style=&quot;width: 100%; min-width: 640px; border-collapse: collapse; font-size: 15px;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;용어&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;예시&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;의미&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;Device ID&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;HWCM5W6-...&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;기기 자체를 식별하는 긴 고유번호&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;Folder ID&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;obsidian-drive&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;여러 기기에서 같은 동기화 폴더임을 맞추는 값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;Folder Label&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Obsidian_Drive_notebook&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;화면에 보이는 이름. 기기마다 달라도 된다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;Folder Path&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;G:\내 드라이브\...&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;해당 기기에서 실제 파일이 있는 위치&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Device ID는 양쪽에서 서로 등록해야 한다. 기존 컴퓨터에 휴대폰이 등록되어 있어도, 새 Windows 설치나 새 Syncthing 설치는 별도의 Device ID를 가진다. 예전 기기 이름이 목록에 있다고 해서 새 노트북이 등록된 것은 아니다.&lt;/p&gt;
&lt;h2 id=&quot;notebook-folder&quot; style=&quot;margin: 42px 0 14px; color: #1a1a1a; font-size: 26px; line-height: 1.35;&quot; data-ke-size=&quot;size26&quot;&gt;6. 노트북 폴더 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노트북 Syncthing에서 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Add Folder&lt;/code&gt;를 누르고 다음처럼 설정한다.&lt;/p&gt;
&lt;div style=&quot;overflow-x: auto; margin: 24px 0;&quot;&gt;
&lt;table style=&quot;width: 100%; min-width: 560px; border-collapse: collapse; font-size: 15px;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th style=&quot;width: 34%; padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;Folder Label&lt;/th&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Obsidian_Drive_notebook&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;Folder ID&lt;/th&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;obsidian-drive&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;Folder Path&lt;/th&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;G:\내 드라이브\obsidian_vault_real_v1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;Folder Type&lt;/th&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Send &amp;amp; Receive&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;Sharing&lt;/th&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;휴대폰 체크&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Introducer&lt;/code&gt;나 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Auto Accept&lt;/code&gt;는 이 구성에 필요하지 않다. 자동으로 다른 기기나 폴더를 늘릴 목적이 없다면 끄고 관리하는 쪽이 이해하기 쉽다.&lt;/p&gt;
&lt;h2 id=&quot;android-folder&quot; style=&quot;margin: 42px 0 14px; color: #1a1a1a; font-size: 26px; line-height: 1.35;&quot; data-ke-size=&quot;size26&quot;&gt;7. 안드로이드 폴더 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안드로이드에서는 Windows의 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;G:&lt;/code&gt; 드라이브를 직접 쓰지 않는다. 휴대폰 내부 저장소에 별도 폴더를 만들고, 그 폴더를 Obsidian Android에서 Vault로 연다.&lt;/p&gt;
&lt;pre class=&quot;gradle&quot; style=&quot;margin: 22px 0; padding: 20px; overflow-x: auto; border-radius: 8px; background: #1e1e2e; color: #cdd6f4; font-size: 15px; line-height: 1.75;&quot;&gt;&lt;code&gt;[int]/Documents/Obsidian-Drive&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;overflow-x: auto; margin: 24px 0;&quot;&gt;
&lt;table style=&quot;width: 100%; min-width: 560px; border-collapse: collapse; font-size: 15px;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th style=&quot;width: 34%; padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;Folder Label&lt;/th&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Obsidian-notebook&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;Folder ID&lt;/th&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;obsidian-drive&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;Folder Path&lt;/th&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;[int]/Documents/Obsidian-Drive&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;Folder Type&lt;/th&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Send &amp;amp; Receive&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;Shared Device&lt;/th&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;새 노트북&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식 Syncthing Android 앱은 2024년 12월 릴리스를 끝으로 중단됐다. Android에서는 현재 커뮤니티 포크인 &lt;b&gt;Syncthing-Fork&lt;/b&gt;를 쓰는 편이 현실적이다. 설치 후 동기화가 끝나면 Obsidian Android에서 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Open folder as vault&lt;/code&gt;를 선택하고 위 내부 저장소 폴더를 열면 된다.&lt;/p&gt;
&lt;h2 id=&quot;paused&quot; style=&quot;margin: 42px 0 14px; color: #1a1a1a; font-size: 26px; line-height: 1.35;&quot; data-ke-size=&quot;size26&quot;&gt;8. Up to Date인데 휴대폰이 연결되지 않았던 진짜 이유&lt;/h2&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1750&quot; data-origin-height=&quot;814&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MQ6pe/dJMcaijsRGe/51Gex6F6H578uCKQq1gsYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MQ6pe/dJMcaijsRGe/51Gex6F6H578uCKQq1gsYK/img.png&quot; data-alt=&quot;휴대폰이 Disconnected 상태였다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MQ6pe/dJMcaijsRGe/51Gex6F6H578uCKQq1gsYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMQ6pe%2FdJMcaijsRGe%2F51Gex6F6H578uCKQq1gsYK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1750&quot; height=&quot;814&quot; data-origin-width=&quot;1750&quot; data-origin-height=&quot;814&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;휴대폰이 Disconnected 상태였다&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;Windows 화면에서 폴더가 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Up to Date&lt;/code&gt;로 표시됐다. 하지만 오른쪽 Remote Devices 쪽 휴대폰은 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Disconnected&lt;/code&gt;였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Up to Date&lt;/code&gt;는 현재 노트북의 해당 폴더가 자기 기준으로 최신이라는 뜻일 수 있다. 휴대폰까지 연결됐다는 뜻은 아니다. 원격 기기 상태도 별도로 봐야 한다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;2048&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blMYst/dJMcagF0p4G/geJEkhmYYCKFbpMtoYArdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blMYst/dJMcagF0p4G/geJEkhmYYCKFbpMtoYArdK/img.png&quot; data-alt=&quot;휴대폰이 Paused 상태였다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blMYst/dJMcagF0p4G/geJEkhmYYCKFbpMtoYArdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblMYst%2FdJMcagF0p4G%2FgeJEkhmYYCKFbpMtoYArdK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;945&quot; height=&quot;2048&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;2048&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;휴대폰이 Paused 상태였다.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;휴대폰 Syncthing-Fork의 Devices 탭을 보니 기존 컴퓨터와 새 노트북이 모두 보라색 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Paused&lt;/code&gt; 상태였다. 특히 새 노트북인 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Obsidian-notebook&lt;/code&gt;이 멈춰 있었으니, Windows에서는 계속 연결할 수 없었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;2048&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7zD3a/dJMcagF0p6E/m7zrS1UEX6KoIOBLRHE5Y0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7zD3a/dJMcagF0p6E/m7zrS1UEX6KoIOBLRHE5Y0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7zD3a/dJMcagF0p6E/m7zrS1UEX6KoIOBLRHE5Y0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7zD3a%2FdJMcagF0p6E%2Fm7zrS1UEX6KoIOBLRHE5Y0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;945&quot; height=&quot;2048&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;2048&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;Folders 탭을 확인하니 폴더 자체도 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Paused&lt;/code&gt;였다. 앱 전체가 켜져 있어도 개별 기기나 개별 폴더가 일시정지되어 있으면 파일은 전송되지 않는다.&lt;/p&gt;
&lt;div style=&quot;margin: 24px 0; padding: 18px 20px; border-radius: 8px; background: #e8f5ee;&quot;&gt;&lt;b&gt;해결 순서&lt;/b&gt;
&lt;ol style=&quot;margin: 0; padding-left: 20px;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;휴대폰 Syncthing-Fork의 Devices 탭을 연다.&lt;/li&gt;
&lt;li&gt;새 노트북 기기를 눌러 Resume 또는 일시정지 해제를 선택한다.&lt;/li&gt;
&lt;li&gt;Folders 탭에서 Obsidian 폴더도 Resume한다.&lt;/li&gt;
&lt;li&gt;기존 데스크톱을 Google Drive만으로 쓸 계획이라면 그 기기는 Paused나 Unused로 둬도 된다.&lt;/li&gt;
&lt;li&gt;노트북과 휴대폰 상태가 Connected &amp;rarr; Syncing &amp;rarr; Up to Date로 바뀌는지 확인한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div style=&quot;overflow-x: auto; margin: 24px 0;&quot;&gt;
&lt;table style=&quot;width: 100%; min-width: 560px; border-collapse: collapse; font-size: 15px;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;화면&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;표시&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;실제 의미&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;Windows 버튼&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Pause&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;현재 실행 중이고, 누르면 멈춘다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;Windows 버튼&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Resume&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;현재 멈춰 있고, 누르면 다시 시작한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;Android 상태 글자&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Paused&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;현재 실제로 일시정지되어 있다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h2 id=&quot;power&quot; style=&quot;margin: 42px 0 14px; color: #1a1a1a; font-size: 26px; line-height: 1.35;&quot; data-ke-size=&quot;size26&quot;&gt;9. 휴대폰 실행 조건도 확인하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Syncthing-Fork의 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Settings &amp;rarr; Run Conditions &amp;rarr; Power Source&lt;/code&gt;에서는 실행 조건을 정할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;overflow-x: auto; margin: 24px 0;&quot;&gt;
&lt;table style=&quot;width: 100%; min-width: 520px; border-collapse: collapse; font-size: 15px;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;선택지&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;의미&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;AC power&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;충전 중에만 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;AC and battery power&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;충전 여부와 관계없이 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;Battery power&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;충전하지 않을 때 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;상시 동기화를 원하면 AC and battery power가 편하다. 다만 이 설정이 맞아도 개별 기기나 폴더가 Paused라면 동기화는 되지 않는다. 그래서 전원 조건보다 먼저 Devices와 Folders의 Pause 상태를 보는 것이 좋다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;u&gt; 나는 핸드폰의 왼쪽 위 메뉴에서 Web GUI에 들어가서 RESUME을 눌러서 해결을 하였다.&amp;nbsp;&amp;nbsp; &lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;2048&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4p9IF/dJMcajvUzui/z2kaopkIagxUwPf3RDSiu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4p9IF/dJMcajvUzui/z2kaopkIagxUwPf3RDSiu0/img.png&quot; data-alt=&quot;여기서 Web GuI에 들어가서 Resume을 누르면 해결이 된다!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4p9IF/dJMcajvUzui/z2kaopkIagxUwPf3RDSiu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4p9IF%2FdJMcajvUzui%2Fz2kaopkIagxUwPf3RDSiu0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;945&quot; height=&quot;2048&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;2048&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;여기서 Web GuI에 들어가서 Resume을 누르면 해결이 된다!&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 style=&quot;margin: 42px 0 14px; color: #1a1a1a; font-size: 26px; line-height: 1.35;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;diagnosis&quot; style=&quot;margin: 42px 0 14px; color: #1a1a1a; font-size: 26px; line-height: 1.35;&quot; data-ke-size=&quot;size26&quot;&gt;10. Disconnected 상태를 해석하는 법&lt;/h2&gt;
&lt;div style=&quot;overflow-x: auto; margin: 24px 0;&quot;&gt;
&lt;table style=&quot;width: 100%; min-width: 660px; border-collapse: collapse; font-size: 15px;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;표시&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;의미&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #e5e5e5; background: #f6f2ff; text-align: left;&quot;&gt;먼저 볼 것&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;Last seen: Never&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;한 번도 연결된 적 없음&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;양쪽 Device ID, 앱 실행, 같은 네트워크&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;과거 시간이 있는 Last seen&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;예전에는 연결됐지만 지금은 끊김&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;Paused, 전원 조건, Wi-Fi 변경&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;Connected (Unused)&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;기기는 연결됐지만 공유 폴더 없음&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;Folder Sharing 체크&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;Out of Sync (0%)&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;메타데이터는 보이나 전송 시작 안 됨&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;기기와 폴더 Resume 여부&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;Up to Date&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;해당 범위의 파일 상태가 최신&lt;/td&gt;
&lt;td style=&quot;padding: 12px; border: 1px solid #e5e5e5;&quot;&gt;원격 기기도 같은 상태인지 별도 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네트워크 문제를 확인하고 싶다면 휴대폰의 현재 Wi-Fi IP를 확인한 뒤 Windows PowerShell에서 아래처럼 테스트할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;margin: 22px 0; padding: 20px; overflow-x: auto; border-radius: 8px; background: #1e1e2e; color: #cdd6f4; font-size: 15px; line-height: 1.75;&quot;&gt;&lt;code&gt;Test-NetConnection 192.168.45.165 -Port 22000&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;TcpTestSucceeded : True&lt;/code&gt;면 네트워크 경로는 열려 있다. &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;False&lt;/code&gt;라면 휴대폰 Syncthing 엔진이 포트를 열지 않았거나, VPN, 게스트 Wi-Fi, 공유기 격리 설정이 기기 간 통신을 막고 있을 수 있다. 단, 기기나 폴더가 Paused인 것이 보이면 먼저 Resume부터 해야 한다.&lt;/p&gt;
&lt;h2 id=&quot;conflicts&quot; style=&quot;margin: 42px 0 14px; color: #1a1a1a; font-size: 26px; line-height: 1.35;&quot; data-ke-size=&quot;size26&quot;&gt;11. 화면에 나타난 14 conflicts는 무엇인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;휴대폰 화면에는 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;14 conflicts&lt;/code&gt;가 표시됐다. 파일 이름도 아래처럼 생겼다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot; style=&quot;margin: 22px 0; padding: 20px; overflow-x: auto; border-radius: 8px; background: #1e1e2e; color: #cdd6f4; font-size: 15px; line-height: 1.75;&quot;&gt;&lt;code&gt;원본파일.sync-conflict-20260610-215135-MAVBV6P.md&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 단순 오류 파일이 아니다. Syncthing은 같은 파일이 두 기기에서 서로 다르게 수정되면 한쪽을 지워버리지 않고 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;sync-conflict&lt;/code&gt; 파일로 보존한다. 즉, 나중에 사람이 보고 어느 내용을 살릴지 결정하라는 뜻이다.&lt;/p&gt;
&lt;div style=&quot;margin: 24px 0; padding: 18px 20px; border-radius: 8px; background: #fef3eb;&quot;&gt;&lt;b&gt;바로 삭제하지 말기&lt;/b&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;14개를 확인하지 않고 한꺼번에 삭제하면 휴대폰이나 과거 컴퓨터에서만 작성했던 문장을 잃을 수 있다.&lt;/p&gt;
&lt;/div&gt;
&lt;ol style=&quot;margin: 18px 0; padding-left: 22px;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Vault 전체를 날짜가 들어간 ZIP 파일로 백업한다.&lt;/li&gt;
&lt;li&gt;원본 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;.md&lt;/code&gt; 파일과 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;sync-conflict&lt;/code&gt; 파일을 각각 연다.&lt;/li&gt;
&lt;li&gt;필요한 문단을 원본 노트에 합친다.&lt;/li&gt;
&lt;li&gt;병합한 노트가 노트북과 휴대폰 양쪽에서 Up to Date인지 확인한다.&lt;/li&gt;
&lt;li&gt;그다음 불필요한 충돌 파일을 삭제한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Syncthing의 폴더 설정에서 File Versioning을 켜면 다른 기기에서 받은 변경으로 파일이 교체되거나 삭제될 때 이전 버전을 남길 수 있다. 기본값은 버전 관리 없음이다. 옵시디언 노트처럼 작은 텍스트 파일이 많은 Vault라면 최소한 Trash Can이나 Simple File Versioning 정도는 켜두는 편이 마음이 편하다.&lt;/p&gt;
&lt;h2 id=&quot;rules&quot; style=&quot;margin: 42px 0 14px; color: #1a1a1a; font-size: 26px; line-height: 1.35;&quot; data-ke-size=&quot;size26&quot;&gt;12. 충돌을 줄이는 실제 사용 규칙&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Google Drive와 Syncthing을 함께 쓴다고 해서 항상 충돌하는 것은 아니다. 충돌은 대개 변경 사항이 전달되기 전에 같은 파일을 여러 기기에서 각각 수정할 때 생긴다.&lt;/p&gt;
&lt;ol style=&quot;margin: 18px 0; padding-left: 22px;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;같은 노트를 두 기기에서 동시에 열어 수정하지 않는다.&lt;/li&gt;
&lt;li&gt;기기를 바꾸기 전 Google Drive와 Syncthing이 모두 동기화 완료인지 본다.&lt;/li&gt;
&lt;li&gt;Obsidian을 종료한 직후 바로 다른 기기에서 같은 노트를 열지 말고 잠시 기다린다.&lt;/li&gt;
&lt;li&gt;노트북과 휴대폰의 Devices, Folders가 Paused가 아닌지 가끔 확인한다.&lt;/li&gt;
&lt;li&gt;Google Drive와 Syncthing이 같은 두 기기를 중복으로 연결하지 않게 한다.&lt;/li&gt;
&lt;li&gt;정기적으로 Vault 전체를 ZIP으로 백업한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동기화는 백업이 아니다. 한 기기에서 삭제한 파일은 삭제 상태도 다른 기기로 전달될 수 있다. 별도 ZIP 백업은 실수로 지우거나 충돌 정리를 잘못했을 때 돌아갈 지점을 만들어준다.&lt;/p&gt;
&lt;h2 id=&quot;tablet&quot; style=&quot;margin: 42px 0 14px; color: #1a1a1a; font-size: 26px; line-height: 1.35;&quot; data-ke-size=&quot;size26&quot;&gt;13. 태블릿을 추가한다면&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안드로이드 태블릿도 휴대폰과 같은 방식으로 연결할 수 있다. 태블릿에 Syncthing-Fork를 설치하고, 노트북과 태블릿의 Device ID를 서로 등록한 뒤, 노트북 폴더의 Sharing에서 태블릿을 체크하면 된다.&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot; style=&quot;margin: 22px 0; padding: 20px; overflow-x: auto; border-radius: 8px; background: #1e1e2e; color: #cdd6f4; font-size: 15px; line-height: 1.75;&quot;&gt;&lt;code&gt;기존 컴퓨터 ⇄ Google Drive ⇄ 새 노트북
                                  ├─ Syncthing ⇄ 휴대폰
                                  └─ Syncthing ⇄ 태블릿&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;휴대폰과 태블릿의 변경 사항이 Google Drive와 기존 컴퓨터로 넘어가려면 역시 노트북이 켜져 있어야 한다.&lt;/p&gt;
&lt;h2 id=&quot;checklist&quot; style=&quot;margin: 42px 0 14px; color: #1a1a1a; font-size: 26px; line-height: 1.35;&quot; data-ke-size=&quot;size26&quot;&gt;14. 최종 점검표&lt;/h2&gt;
&lt;div style=&quot;margin: 20px 0 30px; padding: 22px 24px; border: 1px solid rgba(124,92,191,.2); border-radius: 12px; background: #fff;&quot;&gt;
&lt;ul style=&quot;margin: 0; padding-left: 20px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기존 컴퓨터와 새 노트북이 동일한 Google Drive Vault를 연다.&lt;/li&gt;
&lt;li&gt;두 Windows 기기에서 Vault가 오프라인 사용 가능 상태다.&lt;/li&gt;
&lt;li&gt;노트북과 휴대폰에 서로의 Device ID가 등록됐다.&lt;/li&gt;
&lt;li&gt;Folder ID가 양쪽 모두 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;obsidian-drive&lt;/code&gt;로 같다.&lt;/li&gt;
&lt;li&gt;노트북 Folder Path가 실제 Google Drive Vault를 가리킨다.&lt;/li&gt;
&lt;li&gt;휴대폰 Folder Path가 실제 Android 내부 저장소 Vault를 가리킨다.&lt;/li&gt;
&lt;li&gt;휴대폰의 새 노트북 기기가 Paused가 아니다.&lt;/li&gt;
&lt;li&gt;휴대폰의 Obsidian 폴더가 Paused가 아니다.&lt;/li&gt;
&lt;li&gt;휴대폰 Power Source가 원하는 실행 조건으로 되어 있다.&lt;/li&gt;
&lt;li&gt;양쪽 상태가 최종적으로 Up to Date다.&lt;/li&gt;
&lt;li&gt;기존 sync-conflict 파일을 백업 후 검토했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id=&quot;finish&quot; style=&quot;margin: 42px 0 14px; color: #1a1a1a; font-size: 26px; line-height: 1.35;&quot; data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 설정에서 가장 오래 헷갈렸던 부분은 노트북 폴더가 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Up to Date&lt;/code&gt;인데 휴대폰은 계속 &lt;code style=&quot;padding: 1px 6px; border: 1px solid #e5e5e0; border-radius: 4px; background: #f5f5f0;&quot;&gt;Disconnected&lt;/code&gt;였다는 점이다. Folder ID와 Device ID가 맞아도, 휴대폰 쪽에서 기기와 폴더가 Paused라면 연결과 전송은 진행되지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 단순한 구성은 하나의 Google Drive Vault를 두 Windows 기기가 공유하고, 그중 자주 켜두는 노트북 하나만 Android의 Syncthing 통로로 쓰는 방식이다. 여기에 오프라인 사용, Resume 상태 확인, 충돌 파일 검토, 정기 백업까지 붙이면 실제 사용 중 생길 문제를 꽤 많이 줄일 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;sources&quot; style=&quot;margin: 42px 0 14px; color: #1a1a1a; font-size: 26px; line-height: 1.35;&quot; data-ke-size=&quot;size26&quot;&gt;참고한 공식 문서&lt;/h2&gt;
&lt;ul style=&quot;margin: 18px 0; padding-left: 20px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a style=&quot;color: #5b3fa8;&quot; href=&quot;https://obsidian.md/help/sync&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Obsidian Sync 공식 안내&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #5b3fa8;&quot; href=&quot;https://obsidian.md/help/Getting%2Bstarted/Sync%2Byour%2Bnotes%2Bacross%2Bdevices&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Obsidian 기기 간 동기화 방법&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #5b3fa8;&quot; href=&quot;https://support.google.com/drive/answer/13401938?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Google Drive 스트리밍과 미러링&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #5b3fa8;&quot; href=&quot;https://support.google.com/drive/answer/2375012?co=GENIE.Platform%3DDesktop&amp;amp;hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Google Drive 오프라인 파일 사용&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #5b3fa8;&quot; href=&quot;https://docs.syncthing.net/users/firewall.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Syncthing 방화벽과 포트&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #5b3fa8;&quot; href=&quot;https://docs.syncthing.net/users/syncing.html#conflicting-changes&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Syncthing 충돌 처리&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #5b3fa8;&quot; href=&quot;https://docs.syncthing.net/users/versioning.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Syncthing File Versioning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #5b3fa8;&quot; href=&quot;https://github.com/syncthing/syncthing-android&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;공식 Syncthing Android 앱 중단 안내&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #5b3fa8;&quot; href=&quot;https://github.com/researchxxl/syncthing-android&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Syncthing-Fork 저장소&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ailtchrm-ai-chat&quot; style=&quot;color-scheme: initial; forced-color-adjust: initial; math-depth: initial; position-anchor: initial; text-size-adjust: initial; appearance: initial; color: initial; font: initial; font-palette: initial; font-synthesis: initial; position-area: initial; text-orientation: initial; text-rendering: initial; text-spacing-trim: initial; -webkit-font-smoothing: initial; -webkit-locale: initial; -webkit-text-orientation: initial; -webkit-writing-mode: initial; writing-mode: initial; zoom: initial; accent-color: initial; place-content: initial; place-items: initial; place-self: initial; alignment-baseline: initial; anchor-name: initial; anchor-scope: initial; animation-composition: initial; animation: initial; animation-trigger: initial; app-region: initial; aspect-ratio: initial; backdrop-filter: initial; backface-visibility: initial; background: initial; background-blend-mode: initial; baseline-shift: initial; baseline-source: initial; block-size: initial; border-block: initial; border: initial; border-radius: initial; border-collapse: initial; border-end-end-radius: initial; border-end-start-radius: initial; border-inline: initial; border-shape: initial; border-start-end-radius: initial; border-start-start-radius: initial; box-decoration-break: initial; box-shadow: initial; break-after: initial; break-before: initial; break-inside: initial; buffered-rendering: initial; caption-side: initial; caret-animation: initial; caret-color: initial; caret-shape: initial; clear: initial; clip: initial; clip-path: initial; clip-rule: initial; color-interpolation: initial; color-interpolation-filters: initial; color-rendering: initial; columns: initial; column-fill: initial; gap: initial; rule-break: initial; rule: initial; rule-inset: initial; rule-visibility-items: initial; column-span: initial; contain: initial; contain-intrinsic-block-size: initial; contain-intrinsic-size: initial; contain-intrinsic-inline-size: initial; container: initial; content: initial; content-visibility: initial; corner-shape: initial; corner-block-end-shape: initial; corner-block-start-shape: initial; counter-increment: initial; counter-reset: initial; counter-set: initial; cursor: initial; cx: initial; cy: initial; d: initial; dominant-baseline: initial; dynamic-range-limit: initial; empty-cells: initial; field-sizing: initial; fill: initial; fill-opacity: initial; fill-rule: initial; filter: initial; flex: initial; flex-wrap: initial; float: initial; flood-color: initial; flood-opacity: initial; grid: initial; grid-area: initial; height: initial; hyphenate-character: initial; hyphenate-limit-chars: initial; hyphens: initial; image-orientation: initial; image-rendering: initial; initial-letter: initial; inline-size: initial; inset-block: initial; inset-inline: initial; interactivity: initial; interest-delay: initial; interpolate-size: initial; isolation: initial; left: initial; letter-spacing: initial; lighting-color: initial; line-break: initial; list-style: initial; margin-block: initial; margin: initial; margin-inline: initial; marker: initial; mask: initial; mask-type: initial; math-shift: initial; math-style: initial; max-block-size: initial; max-inline-size: initial; max-width: initial; min-block-size: initial; min-height: initial; min-inline-size: initial; min-width: initial; mix-blend-mode: initial; object-fit: initial; object-position: initial; object-view-box: initial; offset: initial; opacity: initial; order: initial; orphans: initial; outline: initial; outline-offset: initial; overflow-anchor: initial; overflow-block: initial; overflow-clip-margin: initial; overflow-inline: initial; overflow-wrap: initial; overlay: initial; overscroll-behavior-block: initial; overscroll-behavior-inline: initial; overscroll-behavior: initial; padding-block: initial; padding: initial; padding-inline: initial; page: initial; page-orientation: initial; paint-order: initial; perspective: initial; perspective-origin: initial; position-try: initial; position-visibility: initial; print-color-adjust: initial; quotes: initial; r: initial; reading-flow: initial; reading-order: initial; resize: initial; rotate: initial; ruby-align: initial; ruby-position: initial; rule-overlap: initial; rx: initial; ry: initial; scale: initial; scroll-behavior: initial; scroll-initial-target: initial; scroll-margin-block: initial; scroll-margin: initial; scroll-margin-inline: initial; scroll-marker-group: initial; scroll-padding-block: initial; scroll-padding: initial; scroll-padding-inline: initial; scroll-snap-align: initial; scroll-snap-stop: initial; scroll-snap-type: initial; scroll-target-group: initial; scroll-timeline: initial; scrollbar-color: initial; scrollbar-gutter: initial; scrollbar-width: initial; shape-image-threshold: initial; shape-margin: initial; shape-outside: initial; shape-rendering: initial; size: initial; speak: initial; stop-color: initial; stop-opacity: initial; stroke: initial; stroke-dasharray: initial; stroke-dashoffset: initial; stroke-linecap: initial; stroke-linejoin: initial; stroke-miterlimit: initial; stroke-opacity: initial; stroke-width: initial; tab-size: initial; table-layout: initial; text-align: initial; text-align-last: initial; text-anchor: initial; text-autospace: initial; text-box: initial; text-combine-upright: initial; text-decoration: initial; text-decoration-skip-ink: initial; text-emphasis: initial; text-emphasis-position: initial; text-indent: initial; text-justify: initial; text-overflow: initial; text-shadow: initial; text-transform: initial; text-underline-offset: initial; text-underline-position: initial; text-wrap: initial; timeline-scope: initial; timeline-trigger: initial; touch-action: initial; transform: initial; transform-box: initial; transform-origin: initial; transform-style: initial; transition: initial; translate: initial; trigger-scope: initial; user-select: initial; vector-effect: initial; vertical-align: initial; view-timeline: initial; view-transition-class: initial; view-transition-group: initial; view-transition-name: initial; view-transition-scope: initial; visibility: initial; border-spacing: initial; -webkit-box-align: initial; -webkit-box-decoration-break: initial; -webkit-box-direction: initial; -webkit-box-flex: initial; -webkit-box-ordinal-group: initial; -webkit-box-orient: initial; -webkit-box-pack: initial; -webkit-box-reflect: initial; -webkit-line-break: initial; -webkit-line-clamp: initial; -webkit-mask-box-image: initial; -webkit-rtl-ordering: initial; -webkit-ruby-position: initial; -webkit-tap-highlight-color: initial; -webkit-text-combine: initial; -webkit-text-decorations-in-effect: initial; -webkit-text-fill-color: initial; -webkit-text-security: initial; -webkit-text-stroke: initial; -webkit-user-drag: initial; white-space-collapse: initial; widows: initial; width: initial; will-change: initial; word-break: initial; word-spacing: initial; x: initial; y: initial; pointer-events: none !important; display: flex !important; box-sizing: border-box; position: fixed !important; top: 0px !important; right: 0px !important; bottom: 0px !important; max-height: 100% !important; z-index: 2000000000 !important; overflow: hidden; flex-direction: column !important;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;ailtchrm-ai-chat&quot; style=&quot;color-scheme: initial; forced-color-adjust: initial; math-depth: initial; position-anchor: initial; text-size-adjust: initial; appearance: initial; color: initial; font: initial; font-palette: initial; font-synthesis: initial; position-area: initial; text-orientation: initial; text-rendering: initial; text-spacing-trim: initial; -webkit-font-smoothing: initial; -webkit-locale: initial; -webkit-text-orientation: initial; -webkit-writing-mode: initial; writing-mode: initial; zoom: initial; accent-color: initial; place-content: initial; place-items: initial; place-self: initial; alignment-baseline: initial; anchor-name: initial; anchor-scope: initial; animation-composition: initial; animation: initial; animation-trigger: initial; app-region: initial; aspect-ratio: initial; backdrop-filter: initial; backface-visibility: initial; background: initial; background-blend-mode: initial; baseline-shift: initial; baseline-source: initial; block-size: initial; border-block: initial; border: initial; border-radius: initial; border-collapse: initial; border-end-end-radius: initial; border-end-start-radius: initial; border-inline: initial; border-shape: initial; border-start-end-radius: initial; border-start-start-radius: initial; box-decoration-break: initial; box-shadow: initial; break-after: initial; break-before: initial; break-inside: initial; buffered-rendering: initial; caption-side: initial; caret-animation: initial; caret-color: initial; caret-shape: initial; clear: initial; clip: initial; clip-path: initial; clip-rule: initial; color-interpolation: initial; color-interpolation-filters: initial; color-rendering: initial; columns: initial; column-fill: initial; gap: initial; rule-break: initial; rule: initial; rule-inset: initial; rule-visibility-items: initial; column-span: initial; contain: initial; contain-intrinsic-block-size: initial; contain-intrinsic-size: initial; contain-intrinsic-inline-size: initial; container: initial; content: initial; content-visibility: initial; corner-shape: initial; corner-block-end-shape: initial; corner-block-start-shape: initial; counter-increment: initial; counter-reset: initial; counter-set: initial; cursor: initial; cx: initial; cy: initial; d: initial; dominant-baseline: initial; dynamic-range-limit: initial; empty-cells: initial; field-sizing: initial; fill: initial; fill-opacity: initial; fill-rule: initial; filter: initial; flex: initial; flex-wrap: initial; float: initial; flood-color: initial; flood-opacity: initial; grid: initial; grid-area: initial; height: initial; hyphenate-character: initial; hyphenate-limit-chars: initial; hyphens: initial; image-orientation: initial; image-rendering: initial; initial-letter: initial; inline-size: initial; inset-block: initial; inset-inline: initial; interactivity: initial; interest-delay: initial; interpolate-size: initial; isolation: initial; left: initial; letter-spacing: initial; lighting-color: initial; line-break: initial; list-style: initial; margin-block: initial; margin: initial; margin-inline: initial; marker: initial; mask: initial; mask-type: initial; math-shift: initial; math-style: initial; max-block-size: initial; max-inline-size: initial; max-width: initial; min-block-size: initial; min-height: initial; min-inline-size: initial; min-width: initial; mix-blend-mode: initial; object-fit: initial; object-position: initial; object-view-box: initial; offset: initial; opacity: initial; order: initial; orphans: initial; outline: initial; outline-offset: initial; overflow-anchor: initial; overflow-block: initial; overflow-clip-margin: initial; overflow-inline: initial; overflow-wrap: initial; overlay: initial; overscroll-behavior-block: initial; overscroll-behavior-inline: initial; overscroll-behavior: initial; padding-block: initial; padding: initial; padding-inline: initial; page: initial; page-orientation: initial; paint-order: initial; perspective: initial; perspective-origin: initial; position-try: initial; position-visibility: initial; print-color-adjust: initial; quotes: initial; r: initial; reading-flow: initial; reading-order: initial; resize: initial; rotate: initial; ruby-align: initial; ruby-position: initial; rule-overlap: initial; rx: initial; ry: initial; scale: initial; scroll-behavior: initial; scroll-initial-target: initial; scroll-margin-block: initial; scroll-margin: initial; scroll-margin-inline: initial; scroll-marker-group: initial; scroll-padding-block: initial; scroll-padding: initial; scroll-padding-inline: initial; scroll-snap-align: initial; scroll-snap-stop: initial; scroll-snap-type: initial; scroll-target-group: initial; scroll-timeline: initial; scrollbar-color: initial; scrollbar-gutter: initial; scrollbar-width: initial; shape-image-threshold: initial; shape-margin: initial; shape-outside: initial; shape-rendering: initial; size: initial; speak: initial; stop-color: initial; stop-opacity: initial; stroke: initial; stroke-dasharray: initial; stroke-dashoffset: initial; stroke-linecap: initial; stroke-linejoin: initial; stroke-miterlimit: initial; stroke-opacity: initial; stroke-width: initial; tab-size: initial; table-layout: initial; text-align: initial; text-align-last: initial; text-anchor: initial; text-autospace: initial; text-box: initial; text-combine-upright: initial; text-decoration: initial; text-decoration-skip-ink: initial; text-emphasis: initial; text-emphasis-position: initial; text-indent: initial; text-justify: initial; text-overflow: initial; text-shadow: initial; text-transform: initial; text-underline-offset: initial; text-underline-position: initial; text-wrap: initial; timeline-scope: initial; timeline-trigger: initial; touch-action: initial; transform: initial; transform-box: initial; transform-origin: initial; transform-style: initial; transition: initial; translate: initial; trigger-scope: initial; user-select: initial; vector-effect: initial; vertical-align: initial; view-timeline: initial; view-transition-class: initial; view-transition-group: initial; view-transition-name: initial; view-transition-scope: initial; visibility: initial; border-spacing: initial; -webkit-box-align: initial; -webkit-box-decoration-break: initial; -webkit-box-direction: initial; -webkit-box-flex: initial; -webkit-box-ordinal-group: initial; -webkit-box-orient: initial; -webkit-box-pack: initial; -webkit-box-reflect: initial; -webkit-line-break: initial; -webkit-line-clamp: initial; -webkit-mask-box-image: initial; -webkit-rtl-ordering: initial; -webkit-ruby-position: initial; -webkit-tap-highlight-color: initial; -webkit-text-combine: initial; -webkit-text-decorations-in-effect: initial; -webkit-text-fill-color: initial; -webkit-text-security: initial; -webkit-text-stroke: initial; -webkit-user-drag: initial; white-space-collapse: initial; widows: initial; width: initial; will-change: initial; word-break: initial; word-spacing: initial; x: initial; y: initial; pointer-events: none !important; display: flex !important; box-sizing: border-box; position: fixed !important; top: 0px !important; right: 0px !important; bottom: 0px !important; max-height: 100% !important; z-index: 2000000000 !important; overflow: hidden; flex-direction: column !important;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;ailtchrm-ai-chat&quot; style=&quot;color-scheme: initial; forced-color-adjust: initial; math-depth: initial; position-anchor: initial; text-size-adjust: initial; appearance: initial; color: initial; font: initial; font-palette: initial; font-synthesis: initial; position-area: initial; text-orientation: initial; text-rendering: initial; text-spacing-trim: initial; -webkit-font-smoothing: initial; -webkit-locale: initial; -webkit-text-orientation: initial; -webkit-writing-mode: initial; writing-mode: initial; zoom: initial; accent-color: initial; place-content: initial; place-items: initial; place-self: initial; alignment-baseline: initial; anchor-name: initial; anchor-scope: initial; animation-composition: initial; animation: initial; animation-trigger: initial; app-region: initial; aspect-ratio: initial; backdrop-filter: initial; backface-visibility: initial; background: initial; background-blend-mode: initial; baseline-shift: initial; baseline-source: initial; block-size: initial; border-block: initial; border: initial; border-radius: initial; border-collapse: initial; border-end-end-radius: initial; border-end-start-radius: initial; border-inline: initial; border-shape: initial; border-start-end-radius: initial; border-start-start-radius: initial; box-decoration-break: initial; box-shadow: initial; break-after: initial; break-before: initial; break-inside: initial; buffered-rendering: initial; caption-side: initial; caret-animation: initial; caret-color: initial; caret-shape: initial; clear: initial; clip: initial; clip-path: initial; clip-rule: initial; color-interpolation: initial; color-interpolation-filters: initial; color-rendering: initial; columns: initial; column-fill: initial; gap: initial; rule-break: initial; rule: initial; rule-inset: initial; rule-visibility-items: initial; column-span: initial; contain: initial; contain-intrinsic-block-size: initial; contain-intrinsic-size: initial; contain-intrinsic-inline-size: initial; container: initial; content: initial; content-visibility: initial; corner-shape: initial; corner-block-end-shape: initial; corner-block-start-shape: initial; counter-increment: initial; counter-reset: initial; counter-set: initial; cursor: initial; cx: initial; cy: initial; d: initial; dominant-baseline: initial; dynamic-range-limit: initial; empty-cells: initial; field-sizing: initial; fill: initial; fill-opacity: initial; fill-rule: initial; filter: initial; flex: initial; flex-wrap: initial; float: initial; flood-color: initial; flood-opacity: initial; grid: initial; grid-area: initial; height: initial; hyphenate-character: initial; hyphenate-limit-chars: initial; hyphens: initial; image-orientation: initial; image-rendering: initial; initial-letter: initial; inline-size: initial; inset-block: initial; inset-inline: initial; interactivity: initial; interest-delay: initial; interpolate-size: initial; isolation: initial; left: initial; letter-spacing: initial; lighting-color: initial; line-break: initial; list-style: initial; margin-block: initial; margin: initial; margin-inline: initial; marker: initial; mask: initial; mask-type: initial; math-shift: initial; math-style: initial; max-block-size: initial; max-inline-size: initial; max-width: initial; min-block-size: initial; min-height: initial; min-inline-size: initial; min-width: initial; mix-blend-mode: initial; object-fit: initial; object-position: initial; object-view-box: initial; offset: initial; opacity: initial; order: initial; orphans: initial; outline: initial; outline-offset: initial; overflow-anchor: initial; overflow-block: initial; overflow-clip-margin: initial; overflow-inline: initial; overflow-wrap: initial; overlay: initial; overscroll-behavior-block: initial; overscroll-behavior-inline: initial; overscroll-behavior: initial; padding-block: initial; padding: initial; padding-inline: initial; page: initial; page-orientation: initial; paint-order: initial; perspective: initial; perspective-origin: initial; position-try: initial; position-visibility: initial; print-color-adjust: initial; quotes: initial; r: initial; reading-flow: initial; reading-order: initial; resize: initial; rotate: initial; ruby-align: initial; ruby-position: initial; rule-overlap: initial; rx: initial; ry: initial; scale: initial; scroll-behavior: initial; scroll-initial-target: initial; scroll-margin-block: initial; scroll-margin: initial; scroll-margin-inline: initial; scroll-marker-group: initial; scroll-padding-block: initial; scroll-padding: initial; scroll-padding-inline: initial; scroll-snap-align: initial; scroll-snap-stop: initial; scroll-snap-type: initial; scroll-target-group: initial; scroll-timeline: initial; scrollbar-color: initial; scrollbar-gutter: initial; scrollbar-width: initial; shape-image-threshold: initial; shape-margin: initial; shape-outside: initial; shape-rendering: initial; size: initial; speak: initial; stop-color: initial; stop-opacity: initial; stroke: initial; stroke-dasharray: initial; stroke-dashoffset: initial; stroke-linecap: initial; stroke-linejoin: initial; stroke-miterlimit: initial; stroke-opacity: initial; stroke-width: initial; tab-size: initial; table-layout: initial; text-align: initial; text-align-last: initial; text-anchor: initial; text-autospace: initial; text-box: initial; text-combine-upright: initial; text-decoration: initial; text-decoration-skip-ink: initial; text-emphasis: initial; text-emphasis-position: initial; text-indent: initial; text-justify: initial; text-overflow: initial; text-shadow: initial; text-transform: initial; text-underline-offset: initial; text-underline-position: initial; text-wrap: initial; timeline-scope: initial; timeline-trigger: initial; touch-action: initial; transform: initial; transform-box: initial; transform-origin: initial; transform-style: initial; transition: initial; translate: initial; trigger-scope: initial; user-select: initial; vector-effect: initial; vertical-align: initial; view-timeline: initial; view-transition-class: initial; view-transition-group: initial; view-transition-name: initial; view-transition-scope: initial; visibility: initial; border-spacing: initial; -webkit-box-align: initial; -webkit-box-decoration-break: initial; -webkit-box-direction: initial; -webkit-box-flex: initial; -webkit-box-ordinal-group: initial; -webkit-box-orient: initial; -webkit-box-pack: initial; -webkit-box-reflect: initial; -webkit-line-break: initial; -webkit-line-clamp: initial; -webkit-mask-box-image: initial; -webkit-rtl-ordering: initial; -webkit-ruby-position: initial; -webkit-tap-highlight-color: initial; -webkit-text-combine: initial; -webkit-text-decorations-in-effect: initial; -webkit-text-fill-color: initial; -webkit-text-security: initial; -webkit-text-stroke: initial; -webkit-user-drag: initial; white-space-collapse: initial; widows: initial; width: initial; will-change: initial; word-break: initial; word-spacing: initial; x: initial; y: initial; pointer-events: none !important; display: flex !important; box-sizing: border-box; position: fixed !important; top: 0px !important; right: 0px !important; bottom: 0px !important; max-height: 100% !important; z-index: 2000000000 !important; overflow: hidden; flex-direction: column !important;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;ailtchrm-ai-chat&quot; style=&quot;color-scheme: initial; forced-color-adjust: initial; math-depth: initial; position-anchor: initial; text-size-adjust: initial; appearance: initial; color: initial; font: initial; font-palette: initial; font-synthesis: initial; position-area: initial; text-orientation: initial; text-rendering: initial; text-spacing-trim: initial; -webkit-font-smoothing: initial; -webkit-locale: initial; -webkit-text-orientation: initial; -webkit-writing-mode: initial; writing-mode: initial; zoom: initial; accent-color: initial; place-content: initial; place-items: initial; place-self: initial; alignment-baseline: initial; anchor-name: initial; anchor-scope: initial; animation-composition: initial; animation: initial; animation-trigger: initial; app-region: initial; aspect-ratio: initial; backdrop-filter: initial; backface-visibility: initial; background: initial; background-blend-mode: initial; baseline-shift: initial; baseline-source: initial; block-size: initial; border-block: initial; border: initial; border-radius: initial; border-collapse: initial; border-end-end-radius: initial; border-end-start-radius: initial; border-inline: initial; border-shape: initial; border-start-end-radius: initial; border-start-start-radius: initial; box-decoration-break: initial; box-shadow: initial; break-after: initial; break-before: initial; break-inside: initial; buffered-rendering: initial; caption-side: initial; caret-animation: initial; caret-color: initial; caret-shape: initial; clear: initial; clip: initial; clip-path: initial; clip-rule: initial; color-interpolation: initial; color-interpolation-filters: initial; color-rendering: initial; columns: initial; column-fill: initial; gap: initial; rule-break: initial; rule: initial; rule-inset: initial; rule-visibility-items: initial; column-span: initial; contain: initial; contain-intrinsic-block-size: initial; contain-intrinsic-size: initial; contain-intrinsic-inline-size: initial; container: initial; content: initial; content-visibility: initial; corner-shape: initial; corner-block-end-shape: initial; corner-block-start-shape: initial; counter-increment: initial; counter-reset: initial; counter-set: initial; cursor: initial; cx: initial; cy: initial; d: initial; dominant-baseline: initial; dynamic-range-limit: initial; empty-cells: initial; field-sizing: initial; fill: initial; fill-opacity: initial; fill-rule: initial; filter: initial; flex: initial; flex-wrap: initial; float: initial; flood-color: initial; flood-opacity: initial; grid: initial; grid-area: initial; height: initial; hyphenate-character: initial; hyphenate-limit-chars: initial; hyphens: initial; image-orientation: initial; image-rendering: initial; initial-letter: initial; inline-size: initial; inset-block: initial; inset-inline: initial; interactivity: initial; interest-delay: initial; interpolate-size: initial; isolation: initial; left: initial; letter-spacing: initial; lighting-color: initial; line-break: initial; list-style: initial; margin-block: initial; margin: initial; margin-inline: initial; marker: initial; mask: initial; mask-type: initial; math-shift: initial; math-style: initial; max-block-size: initial; max-inline-size: initial; max-width: initial; min-block-size: initial; min-height: initial; min-inline-size: initial; min-width: initial; mix-blend-mode: initial; object-fit: initial; object-position: initial; object-view-box: initial; offset: initial; opacity: initial; order: initial; orphans: initial; outline: initial; outline-offset: initial; overflow-anchor: initial; overflow-block: initial; overflow-clip-margin: initial; overflow-inline: initial; overflow-wrap: initial; overlay: initial; overscroll-behavior-block: initial; overscroll-behavior-inline: initial; overscroll-behavior: initial; padding-block: initial; padding: initial; padding-inline: initial; page: initial; page-orientation: initial; paint-order: initial; perspective: initial; perspective-origin: initial; position-try: initial; position-visibility: initial; print-color-adjust: initial; quotes: initial; r: initial; reading-flow: initial; reading-order: initial; resize: initial; rotate: initial; ruby-align: initial; ruby-position: initial; rule-overlap: initial; rx: initial; ry: initial; scale: initial; scroll-behavior: initial; scroll-initial-target: initial; scroll-margin-block: initial; scroll-margin: initial; scroll-margin-inline: initial; scroll-marker-group: initial; scroll-padding-block: initial; scroll-padding: initial; scroll-padding-inline: initial; scroll-snap-align: initial; scroll-snap-stop: initial; scroll-snap-type: initial; scroll-target-group: initial; scroll-timeline: initial; scrollbar-color: initial; scrollbar-gutter: initial; scrollbar-width: initial; shape-image-threshold: initial; shape-margin: initial; shape-outside: initial; shape-rendering: initial; size: initial; speak: initial; stop-color: initial; stop-opacity: initial; stroke: initial; stroke-dasharray: initial; stroke-dashoffset: initial; stroke-linecap: initial; stroke-linejoin: initial; stroke-miterlimit: initial; stroke-opacity: initial; stroke-width: initial; tab-size: initial; table-layout: initial; text-align: initial; text-align-last: initial; text-anchor: initial; text-autospace: initial; text-box: initial; text-combine-upright: initial; text-decoration: initial; text-decoration-skip-ink: initial; text-emphasis: initial; text-emphasis-position: initial; text-indent: initial; text-justify: initial; text-overflow: initial; text-shadow: initial; text-transform: initial; text-underline-offset: initial; text-underline-position: initial; text-wrap: initial; timeline-scope: initial; timeline-trigger: initial; touch-action: initial; transform: initial; transform-box: initial; transform-origin: initial; transform-style: initial; transition: initial; translate: initial; trigger-scope: initial; user-select: initial; vector-effect: initial; vertical-align: initial; view-timeline: initial; view-transition-class: initial; view-transition-group: initial; view-transition-name: initial; view-transition-scope: initial; visibility: initial; border-spacing: initial; -webkit-box-align: initial; -webkit-box-decoration-break: initial; -webkit-box-direction: initial; -webkit-box-flex: initial; -webkit-box-ordinal-group: initial; -webkit-box-orient: initial; -webkit-box-pack: initial; -webkit-box-reflect: initial; -webkit-line-break: initial; -webkit-line-clamp: initial; -webkit-mask-box-image: initial; -webkit-rtl-ordering: initial; -webkit-ruby-position: initial; -webkit-tap-highlight-color: initial; -webkit-text-combine: initial; -webkit-text-decorations-in-effect: initial; -webkit-text-fill-color: initial; -webkit-text-security: initial; -webkit-text-stroke: initial; -webkit-user-drag: initial; white-space-collapse: initial; widows: initial; width: initial; will-change: initial; word-break: initial; word-spacing: initial; x: initial; y: initial; pointer-events: none !important; display: flex !important; box-sizing: border-box; position: fixed !important; top: 0px !important; right: 0px !important; bottom: 0px !important; max-height: 100% !important; z-index: 2000000000 !important; overflow: hidden; flex-direction: column !important;&quot;&gt;&amp;nbsp;&lt;/div&gt;</description>
      <category>AI</category>
      <category>Obsidian sync</category>
      <category>옵시디언 syncthing</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/88</guid>
      <comments>https://onethingflow.tistory.com/entry/%EC%98%B5%EC%8B%9C%EB%94%94%EC%96%B8-PC-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EB%8F%99%EA%B8%B0%ED%99%94-%EB%B0%A9%EB%B2%95-%EC%B4%9D%EC%A0%95%EB%A6%ACGoogle-Drive-Syncthing#entry88comment</comments>
      <pubDate>Wed, 3 Jun 2026 12:36:16 +0900</pubDate>
    </item>
    <item>
      <title>비개발자도 1시간 만에 글로벌 결제 사이트 만드는 법 (Claude Code + PayPal MCP 완전 정복)</title>
      <link>https://onethingflow.tistory.com/entry/%EB%B9%84%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8F%84-1%EC%8B%9C%EA%B0%84-%EB%A7%8C%EC%97%90-%EA%B8%80%EB%A1%9C%EB%B2%8C-%EA%B2%B0%EC%A0%9C-%EC%82%AC%EC%9D%B4%ED%8A%B8-%EB%A7%8C%EB%93%9C%EB%8A%94-%EB%B2%95-Claude-Code-PayPal-MCP-%EC%99%84%EC%A0%84-%EC%A0%95%EB%B3%B5</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 1인 창업자 관련 영상에 대한 내용을 가져왔습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이디어 회의 &amp;rarr; 코딩 &amp;rarr; Firebase 로그인 &amp;rarr; PayPal 결제 테스트까지, 한 번의 세션 안에 다 됩니다. 물론 중간에 삽질도 꽤 했습니다. 특히 PayPal MCP 연결할 때 빨간 에러 때문에 한참 고생했는데, 그 해결법도 이 글에 전부 담았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 소개할 건 &lt;a href=&quot;https://ainightschool.xyz&quot;&gt;Connect AI Lab(제이쌤)&lt;/a&gt;이 공개한 &lt;b&gt;ASCFP 전략&lt;/b&gt;입니다. 처음 들어보신다면 걱정 마세요. 지금부터 초보자도 바로 따라 할 수 있도록 처음부터 끝까지 설명합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ASCFP가 뭔가요?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;A&lt;/b&gt;ntigravity + &lt;b&gt;S&lt;/b&gt;kill + &lt;b&gt;C&lt;/b&gt;laude Code + &lt;b&gt;F&lt;/b&gt;irebase + &lt;b&gt;P&lt;/b&gt;ayPal&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다섯 가지 도구를 조합해서, 기획-개발-결제까지 혼자서 다 하겠다는 전략입니다. 각각 무슨 역할을 하는지 한 줄로 정리하면:&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;도구&lt;/th&gt;
&lt;th&gt;역할&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Antigravity&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;AI 에이전트 실행 환경. &quot;이거 만들어줘&quot; 하면 알아서 처리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Skill&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;에이전트에게 주는 역할 명세서. &quot;너는 수익형 사이트 만드는 전문가야&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Claude Code&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;코딩 특화 AI. 실제 코드 작업과 세부 디자인 수정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Firebase MCP&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;회원가입, 로그인, 데이터베이스를 AI가 자동으로 구축&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;PayPal MCP&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;달러 결제창을 코드 없이 AI가 자동으로 연결&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 다섯 개가 MCP(Model Context Protocol)라는 방식으로 서로 연결되면, Claude Code가 Firebase와 PayPal을 직접 조작할 수 있게 됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;STEP 1. Claude Code 설치하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 Claude Code를 설치해야 합니다. 터미널(맥은 Terminal, 윈도우는 PowerShell)을 열고 아래 명령어를 붙여넣기하고 엔터를 누르면 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;macOS / Linux / WSL 사용자&lt;/h3&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;curl -fsSL https://claude.ai/install.sh | bash&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Windows PowerShell 사용자&lt;/h3&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;irm https://claude.ai/install.ps1 | iex&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Windows CMD 사용자&lt;/h3&gt;
&lt;pre class=&quot;dos&quot;&gt;&lt;code&gt;curl -fsSL https://claude.ai/install.cmd -o install.cmd &amp;amp;&amp;amp; install.cmd &amp;amp;&amp;amp; del install.cmd&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치가 완료되면 터미널에서 &lt;code&gt;claude&lt;/code&gt;를 입력해보세요. 아래처럼 Claude Code 인터페이스가 뜨면 성공입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;팁&lt;/b&gt;: VS Code(비주얼 스튜디오 코드)를 사용하신다면, 확장 프로그램 탭에서 &lt;code&gt;Claude Code&lt;/code&gt;를 검색해 설치하면 에디터 안에서 바로 사용할 수 있어서 훨씬 편합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;STEP 2. Firebase MCP &amp;amp; PayPal MCP 설치하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 핵심입니다. AI에게 Firebase와 PayPal이라는 &quot;도구&quot;를 쥐여주는 과정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Antigravity 또는 Claude Code의 MCP 설정 화면으로 들어가세요.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Firebase MCP&lt;/b&gt;: MCP 스토어에서 Firebase를 찾아 Install 버튼 클릭&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PayPal MCP&lt;/b&gt;: MCP 스토어에서 PayPal을 찾아 Install 버튼 클릭&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PayPal MCP 설정 &amp;mdash; 여기서 막히는 분 많으니 주의하세요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PayPal MCP를 설치하면 두 가지 값을 입력하라고 합니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;PayPal Access Token&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PayPal Environment&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 값을 구하려면 PayPal 개발자 계정이 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;① &lt;a href=&quot;https://developer.paypal.com&quot;&gt;developer.paypal.com&lt;/a&gt; 접속 후 로그인&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;② Sandbox 앱 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상단 메뉴에서 &lt;b&gt;Dashboard &amp;rarr; Applications &amp;rarr; Sandbox&lt;/b&gt;로 이동하고, &lt;b&gt;Create App&lt;/b&gt; 버튼을 클릭합니다. 앱 이름을 적당히 입력하고 생성하면 &lt;b&gt;Client ID&lt;/b&gt;와 &lt;b&gt;Secret Key&lt;/b&gt;가 발급됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;③ Access Token 발급&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터미널에서 아래 명령어를 실행합니다. &lt;code&gt;YOUR_CLIENT_ID&lt;/code&gt;와 &lt;code&gt;YOUR_SECRET&lt;/code&gt;에 위에서 받은 값을 넣으면 됩니다:&lt;/p&gt;
&lt;pre class=&quot;livescript&quot;&gt;&lt;code&gt;curl -s -X POST &quot;https://api-m.sandbox.paypal.com/v1/oauth2/token&quot; \
  -u &quot;YOUR_CLIENT_ID:YOUR_SECRET&quot; \
  -H &quot;Content-Type: application/x-www-form-urlencoded&quot; \
  -d &quot;grant_type=client_credentials&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행하면 아래처럼 JSON 응답이 옵니다. 여기서 &lt;code&gt;access_token&lt;/code&gt; 값을 복사하세요:&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;access_token&quot;: &quot;A21AAK45ZLdriR8stU...(긴 토큰값)&quot;,
  &quot;token_type&quot;: &quot;Bearer&quot;,
  &quot;expires_in&quot;: 32400
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;④ PayPal MCP에 입력&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;PayPal Access Token&lt;/b&gt; 필드: 위에서 복사한 &lt;code&gt;access_token&lt;/code&gt; 값&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PayPal Environment&lt;/b&gt; 필드: &lt;code&gt;sandbox&lt;/code&gt; (테스트 중에는 반드시 소문자로)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Save&lt;/b&gt; 클릭&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⚠️ &lt;b&gt;여기서 빨간 에러가 나는 분들께&lt;/b&gt; &amp;mdash; 저도 여기서 한참 막혔습니다. 에러 메시지가 이렇게 뜬다면:&lt;/p&gt;
&lt;pre class=&quot;subunit&quot;&gt;&lt;code&gt;Error: Error initializing PayPal MCP server: The --tools arguments must be provided.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 &lt;code&gt;@paypal/mcp&lt;/code&gt; 패키지의 버그로, GUI에서는 해결이 안 됩니다. 아래 방법으로 해결하세요:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터미널에서 이 명령어를 실행하세요:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;claude mcp add paypal \
  -e PAYPAL_ACCESS_TOKEN=&quot;여기에_토큰값&quot; \
  -e PAYPAL_ENVIRONMENT=&quot;sandbox&quot; \
  -- npx -y @paypal/mcp --tools=all&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 &lt;code&gt;claude mcp list&lt;/code&gt;를 실행했을 때 &lt;code&gt;paypal: ... ✓ Connected&lt;/code&gt;가 보이면 성공입니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;STEP 3. 수익형 사이트 스킬(Skill) 자동 생성하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 AI에게 &quot;수익형 사이트 만드는 전문가&quot; 역할을 부여할 차례입니다. 이게 바로 &lt;b&gt;Skill&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Antigravity를 열고, 아래 프롬프트를 통째로 복사해서 붙여넣기 후 전송하세요. 그러면 AI가 알아서 필요한 폴더와 파일을 만들어줍니다.&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;# Action Request: Create a New Skill &quot;moneywebsite&quot;

Please create a new directory and a SKILL.md file following the Antigravity Skill Standard specifications.

## 1. Directory Structure

Execute the following command to create the skill directory:
`mkdir -p .agent/skills/moneywebsite`

## 2. File Creation: .agent/skills/moneywebsite/SKILL.md

Create the `SKILL.md` file with the exact content below.

### Content of SKILL.md:

---
name: global-venture-builder
description: Activates when the user wants to build a profitable website, MVP, SaaS, or monetize an idea. It specializes in rapid development, global design standards, and integrating Firebase and PayPal via MCP.
---

# Role: Global Venture Builder (Profit Architect)

## Goal

To rapidly design and develop a high-quality, English-first, monetizable website that integrates backend and payment systems using Model Context Protocol (MCP).

## Persona

- **Identity**: You are a &quot;Profit Architect&quot;&amp;mdash;a senior full-stack developer obsessed with ROI (Return on Investment) and speed-to-market.
- **Tone**: Professional, decisive, and results-oriented. Use English for code/UI, but explain in the user's preferred language.
- **Standard**: &quot;Silicon Valley Quality.&quot; Clean, modern, and trustworthy design.

## Instructions

### Phase 1: Ideation &amp;amp; Strategy

1. **Analyze Request**: If the user has an idea, refine it for profitability. If not, propose a high-margin Micro-SaaS idea.
2. **Target Audience**: Assume a **Global Audience**. All UI text must be in **English**.

### Phase 2: Frontend Development (The Face)

1. **Stack**: Use modern HTML/CSS (Tailwind) or React.
2. **Design Principles**:
    - Minimalist and high-conversion layout.
    - Strong Call-to-Action (CTA) buttons.
    - Responsive (Mobile-first).

### Phase 3: Backend Infrastructure (Firebase MCP)

1. **Requirement**: Do not mock the backend. Use the **Firebase MCP** tool.
2. **Actions**:
    - Set up **Firebase Auth** for user login/signup.
    - Set up **Firestore** to save user data.

### Phase 4: Monetization (PayPal MCP)

1. **Requirement**: The site must make money. Use the **PayPal MCP** tool.
2. **Actions**:
    - Create a payment checkout flow.
    - Integrate PayPal buttons or API for transaction processing.

## Constraints

- **English UI**: The website content must be in English to target the global market.
- **Real Integration**: Always prefer using available MCP tools (Firebase, PayPal) over placeholder code.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전송 후 잠시 기다리면, 왼쪽 파일 탐색기에 &lt;code&gt;.agent/skills/moneywebsite/SKILL.md&lt;/code&gt; 파일이 자동으로 생성됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스킬을 왜 만드나요?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 가지 이유가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, &lt;b&gt;토큰 절약&lt;/b&gt;입니다. AI와 대화가 길어지면 속도가 느려지고 토큰이 낭비됩니다. 새 대화를 시작해야 할 때 스킬 파일이 있으면 &quot;수익형 사이트 만들어줘&quot; 한 마디에 이전 맥락을 전부 불러옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째, &lt;b&gt;정확한 역할 부여&lt;/b&gt;입니다. 스킬 파일에 담긴 지시사항 덕분에 AI가 막연하게 개발하는 게 아니라, Firebase와 PayPal을 반드시 연결하고 영어 UI로 만들고 전환율 높은 레이아웃으로 설계하는 등 처음부터 목표에 맞게 움직입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;STEP 4. 실제로 사이트 만들어보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 준비가 끝났습니다. 이제 진짜 재미있는 부분입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Antigravity를 열고, 모드를 &lt;b&gt;Planning&lt;/b&gt;으로 설정한 뒤 이렇게 입력하세요:&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;수익형 웹사이트 개발하자&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 Antigravity가 &lt;code&gt;skill.md&lt;/code&gt;를 감지하고 &quot;global-venture-builder 스킬을 활성화할까요?&quot; 라고 묻습니다. 활성화하면, AI가 수익화 아이디어를 몇 가지 제안합니다. 예를 들어:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AI 자기소개서 생성기 (건당 결제)&lt;/li&gt;
&lt;li&gt;이력서 기반 맞춤 커버레터 생성기&lt;/li&gt;
&lt;li&gt;글로벌 번역 문서 서비스&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나를 선택하면, AI가 스스로 태스크 목록을 만들고 하나씩 실행합니다. 기다리면 됩니다. 정말로, 그냥 기다리면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완료되면:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;랜딩 페이지 (영어 UI)&lt;/li&gt;
&lt;li&gt;Google 소셜 로그인 (Firebase Auth)&lt;/li&gt;
&lt;li&gt;결제 버튼 (PayPal)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 전부가 연결된 사이트가 생성됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;디자인이 마음에 안 든다면?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 만든 첫 번째 버전은 기능 위주라 디자인이 밋밋할 수 있습니다. 이때는 &lt;b&gt;Claude Code 터미널&lt;/b&gt;에서 이렇게 입력하세요:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;Check our entire project and change the design cleanly. 
UIUX &amp;mdash; so that global users can easily read it, 
with colors that are easy on the eyes.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code가 전체 코드를 분석해서 디자인을 새로 잡아줍니다. Antigravity가 기획과 구조를 잡고, Claude Code가 세부 마감을 한다고 생각하면 됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;STEP 5. 실제 결제 테스트하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사이트가 완성되면 Sandbox 모드에서 테스트 결제를 해볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PayPal 개발자 대시보드에서 &lt;b&gt;Sandbox Accounts&lt;/b&gt;로 이동하면 테스트용 구매자 계정이 있습니다. 그 계정으로 로그인해서 실제 결제 플로우를 따라가보세요. 카드 번호 입력, 승인, 완료 페이지까지 다 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 없으면 PayPal Environment를 &lt;code&gt;sandbox&lt;/code&gt;에서 &lt;code&gt;production&lt;/code&gt;으로 바꾸고, Live 앱의 Client ID/Secret으로 새 토큰을 발급받아 교체하면 실제 결제가 됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이 방법의 진짜 강점 세 가지&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 빠릅니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이디어 회의부터 첫 배포까지 1시간입니다. 처음 세팅(PayPal 계정 등록 등)이 조금 걸리지만, 한 번 해두면 그 다음 서비스는 30분 안에도 나옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 처음부터 글로벌입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영어 UI로 자동 생성되기 때문에 한국어 서비스를 나중에 글로벌화하는 번거로움이 없습니다. PayPal은 200개 이상 국가를 지원하고, 국내 PG사보다 가입이 훨씬 간단합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 실제로 돈이 됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플레이스홀더 코드 없이 Firebase와 PayPal이 실제로 연결됩니다. &quot;나중에 결제 붙이자&quot;가 아니라 처음부터 결제가 되는 사이트가 만들어집니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자주 막히는 포인트 &amp;amp; 해결법 모음&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;① Claude Code 설치 후 &lt;code&gt;claude&lt;/code&gt; 명령어를 쳐도 아무것도 안 나와요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터미널을 완전히 닫고 다시 열어보세요. 환경변수가 새 터미널에서만 적용되는 경우가 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;② PayPal MCP에서 계속 빨간 에러가 떠요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 에러입니다:&lt;/p&gt;
&lt;pre class=&quot;subunit&quot;&gt;&lt;code&gt;Error: The --tools arguments must be provided. : calling &quot;initialize&quot;: EOF.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GUI 화면에서는 해결이 안 됩니다. 터미널에서 아래 명령어로 직접 등록해야 합니다:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;claude mcp add paypal \
  -e PAYPAL_ACCESS_TOKEN=&quot;발급받은_토큰&quot; \
  -e PAYPAL_ENVIRONMENT=&quot;sandbox&quot; \
  -- npx -y @paypal/mcp --tools=all&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;등록 후 &lt;code&gt;claude mcp list&lt;/code&gt; 실행 &amp;rarr; &lt;code&gt;paypal: ... ✓ Connected&lt;/code&gt; 확인&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;③ Access Token이 만료됐다고 나와요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토큰은 약 9시간(32400초)짜리입니다. 만료됐으면 Step 2의 curl 명령어를 다시 실행해서 새 토큰을 발급받으면 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;④ Firebase 로그인은 됐는데 Google 소셜 로그인이 안 돼요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Firebase 콘솔(console.firebase.google.com)에서 Authentication &amp;rarr; Sign-in method &amp;rarr; Google을 활성화했는지 확인하세요. AI가 코드는 만들지만 Firebase 콘솔 설정은 직접 해야 할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;⑤ Antigravity 토큰이 금방 바닥나요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code를 함께 사용하는 게 이래서 좋습니다. 큰 그림(기획, 구조)은 Antigravity로 잡고, 세부 작업(디자인 수정, 버그 수정)은 Claude Code 터미널로 하면 토큰 소비가 훨씬 줄어듭니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 접하면 도구가 많아 복잡해 보이지만, 사실 흐름은 단순합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Antigravity로 계획 &amp;rarr; Claude Code로 실행 &amp;rarr; Firebase로 로그인 &amp;rarr; PayPal로 결제&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 네 단계가 MCP로 연결되어 있어서, 자연어로 말하면 AI가 백엔드와 결제 시스템을 직접 다뤄줍니다. 개발자가 아니어도 됩니다. 코드를 몰라도 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단, 이 모든 걸 처음 한 번은 직접 따라 해봐야 합니다. 읽는 것과 실제로 해보는 건 완전히 다릅니다. 에러도 나고 막히는 구간도 있지만, 그게 있어야 다음에 더 빨리 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원본 가이드와 영상은 여기서 확인하세요:&lt;br /&gt;  &lt;a href=&quot;https://ainightschool.xyz/textbook/global-venture-guide&quot;&gt;ainightschool.xyz/textbook/global-venture-guide&lt;/a&gt;&lt;br /&gt;  &lt;a href=&quot;https://youtu.be/xoY7bOD9Dkc&quot;&gt;YouTube: 클로드 코드 + 페이팔 MCP로 글로벌 서비스 만들기&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;읽어주셔서 감사합니다. 궁금한 점은 댓글로 남겨주세요.&lt;/i&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <category>ClaudeCode #PayPalMCP #Firebase #글로벌창업 #안티그래비티 #바이브코딩 #1인개발 #수익형사이트</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/86</guid>
      <comments>https://onethingflow.tistory.com/entry/%EB%B9%84%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8F%84-1%EC%8B%9C%EA%B0%84-%EB%A7%8C%EC%97%90-%EA%B8%80%EB%A1%9C%EB%B2%8C-%EA%B2%B0%EC%A0%9C-%EC%82%AC%EC%9D%B4%ED%8A%B8-%EB%A7%8C%EB%93%9C%EB%8A%94-%EB%B2%95-Claude-Code-PayPal-MCP-%EC%99%84%EC%A0%84-%EC%A0%95%EB%B3%B5#entry86comment</comments>
      <pubDate>Sat, 23 May 2026 17:51:37 +0900</pubDate>
    </item>
    <item>
      <title>yolov10, rtdetr A-Z까지 알아보자</title>
      <link>https://onethingflow.tistory.com/entry/yolov10-rtdetr-A-Z%EA%B9%8C%EC%A7%80-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt; ️ YOLOv10의 구조 및 탐지 과정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YOLOv10의 가장 큰 목표는, YOLO가 오랫동안 의존해왔던 1) '&lt;b&gt;앵커 박스(템플릿)&lt;/b&gt;'의 번거로움과 2) '&lt;b&gt;NMS(청소부)&lt;/b&gt;'라는 속도 저하 요인을 모두 제거하여, &lt;b&gt;더 빠르고 간결한 'End-to-End' 모델&lt;/b&gt;을 만드는 것이었습니다.&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[1단계] 백본 (Backbone - 특징 추출)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;구조:&lt;/b&gt; 최적화된 &lt;b&gt;CSPNet&lt;/b&gt; (YOLO의 전통적인 CNN 구조)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;설명:&lt;/b&gt; 이미지를 입력받아, '선', '모서리', '질감' 같은 기본 특징부터 '바퀴 모양', '눈 모양' 같은 복잡한 시각 특징까지 추출합니다. 이 단계는 강력한 &lt;b&gt;특징 추출&lt;/b&gt;에 집중하며, 이는 기존 YOLO 모델들과 유사한 방식입니다.&lt;/li&gt;
&lt;li&gt;CT 영상을 여러 해상도로 분석합니다. 작은 출혈부터 큰 출혈까지 놓치지 않기 위해서입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[2단계] 넥 (Neck - 정보 통합)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;구조:&lt;/b&gt; &lt;b&gt;PANet&lt;/b&gt; (Path Aggregation Network)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;설명:&lt;/b&gt; 백본이 추출한 특징들을 섞어주는 '믹서기'입니다. '작은 물체'를 잘 찾는 고해상도 정보(초기 레이어)와 '큰 물체'를 잘 찾는 저해상도 정보(후기 레이어)를 효율적으로 융합합니다. 이를 통해 뒤따르는 헤드(뇌)가 모든 크기의 물체를 균형 있게 잘 찾도록 돕습니다.&lt;/li&gt;
&lt;li&gt;위아래 정보를 섞어서 더 정확한 위치를 파악합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[3단계] 헤드 (Head - 최종 판단): ⭐️ YOLOv10의 핵심 혁신 ⭐️&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YOLOv10의 모든 혁신은 이 '헤드' 부분에 집중되어 있습니다. 여기서 &lt;b&gt;앵커 박스&lt;/b&gt;와 &lt;b&gt;NMS&lt;/b&gt;라는 두 가지 오래된 문제를 해결합니다.&lt;br /&gt;위치와 종류를 파악합니다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;1. '앵커 프리'로 앵커 박스(Anchor Box) 문제 해결:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;기존 문제 (YOLOv3~v7):&lt;/b&gt; '앵커 박스'라는 미리 정의된 '템플릿'을 사용했습니다. 이 방식은 데이터셋이 바뀔 때마다 K-means 클러스터링 같은 복잡한 '사전 준비' 작업으로 템플릿을 다시 계산해야 하는 &lt;b&gt;번거로움&lt;/b&gt;이 있었습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;YOLOv10의 해결 (Anchor-Free):&lt;/b&gt; '템플릿' 자체를 완전히 없앴습니다. 따라서 '사전 준비' 작업이 필요 없어졌습니다. 대신 모델이 물체의 중심점에서 '왼쪽/오른쪽/위/아래' 경계선까지의 **'거리'**를 직접 예측하는 방식으로 바뀌어, 훨씬 유연하고 간결해졌습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2. '이중 헤드'로 NMS(중복 제거) 문제 해결:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;기존 문제 (YOLOv1~v8):&lt;/b&gt; 앵커 기반이든 앵커 프리든, 한 물체에 대해 수십 개의 '중복된 박스'가 쏟아져 나왔습니다. 이 중복을 정리하기 위해 **'NMS(청소부)'**라는 '후처리' 과정이 필수였고, 이 NMS 자체가 &lt;b&gt;속도 저하의 주범&lt;/b&gt;이었습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;YOLOv10의 해결 (Dual Head):&lt;/b&gt; 훈련(공부) 방식 자체를 바꿔서 '청소부'를 해고했습니다. 훈련 시 헤드(뇌)를 2개 사용합니다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;느슨한 헤드 (One-to-Many): &lt;/b&gt;하나의 '고양이(정답)'를 찾을 때, 100% 완벽한 예측(칸) 1개만 &quot;정답&quot;이라고 하지 않습니다.대신, &quot;이 고양이일 가능성이 높은&quot; (예: 정답과 꽤 많이 겹치는) 상위 후보 5개(예시)를 모두 '긍정적인 신호(정답)'로 간주하고 보상(칭찬)을 줍니다.(AI가 특징을 풍부하게 배우도록 도움)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;엄격한 헤드 (One-to-One):&lt;/b&gt; &lt;b&gt;동시에&lt;/b&gt;, &quot;저 고양이 1마리는 3행 5열 &lt;b&gt;너 하나만&lt;/b&gt; 맡아!&quot;라고 1:1로 담당자를 '강제 할당'합니다. 예측 시 엄격한 헤드만 사용해 &quot;물체 하나당=박스 하나&quot;의 깔끔한 예측을 수행합니다.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[4단계] 탐지 과정 (결과)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;훈련이 끝나면, '느슨한 헤드'는 버리고 실제 예측 시에는 '엄격한 헤드(One-to-One)'만 사용합니다.&lt;/li&gt;
&lt;li&gt;이 '엄격한 헤드'는 이미 &quot;물체 하나당 = 담당자 하나&quot;라고 1:1로 말하도록 훈련되었습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;최종 결과:&lt;/b&gt; 예측할 때 애초에 중복된 박스가 거의 나오지 않으므로, 'NMS(청소부)'가 필요 없는(&lt;b&gt;NMS-Free&lt;/b&gt;) 깔끔한 결과물이 &lt;b&gt;'한 번에(End-to-End)'&lt;/b&gt; 나옵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  1부: 기존 DETR의 작동 원리 (똑똑했지만 느렸던 '번역가')&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YOLO와 달리, DETR(DEtection TRansformer)은 &quot;객체 탐지를 '번역' 문제로 풀자!&quot;는 완전히 새로운 철학으로 시작했습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;A. DETR의 기본 작동 원리 (A-Z)&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;[1단계] 백본 (Backbone - 특징 추출 ):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;구조:&lt;/b&gt; CNN (예: ResNet)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;설명:&lt;/b&gt; 이미지를 입력받아 '특징 맵(요약본)'을 만듭니다. 여기서 &lt;b&gt;가장 큰 문제&lt;/b&gt;가 발생합니다. DETR은 백본이 만든 여러 요약본 중, &lt;b&gt;오직 '최종 저해상도 요약본(C5)' 1장&lt;/b&gt;만 사용했습니다. (예: 20x20 크기 맵)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;문제점:&lt;/b&gt; 이 1장의 맵에는 '전체 맥락'은 담겨있지만, 이미지가 너무 압축(뭉개짐)되어 &lt;b&gt;'작은 물체' 정보가 완전히 사라졌습니다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[2단계] 인코더 (Encoder - 1차 브레인스토밍): ⭐️ DETR의 '느린 주범' ⭐️&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;구조:&lt;/b&gt; 트랜스포머 인코더&lt;/li&gt;
&lt;li&gt;&lt;b&gt;설명:&lt;/b&gt; 1단계에서 만든 1장의 '저해상도 맵'(예: 20x20 = 400개 픽셀)을 넣습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;작동:&lt;/b&gt; '셀프 어텐션(Self-Attention)'이라는 '전체 회의'를 시작합니다. 400개의 픽셀이 &quot;나는 나머지 399개 픽셀과 각각 얼마나 관련이 깊지?&quot;를 &lt;b&gt;모두(All-to-All) 비교&lt;/b&gt;합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;계산:&lt;/b&gt; (400 x 400) = 160,000번의 비교가 일어납니다. 이 &lt;span data-math=&quot;N \times N&quot;&gt;N x N&lt;/span&gt;&amp;nbsp;계산은 &lt;b&gt;끔찍하게 느렸습니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;결과:&lt;/b&gt; 느리지만, &quot;저기 '바퀴' 픽셀은 멀리 떨어진 '핸들' 픽셀과 '자동차'라는 맥락으로 연결된다&quot;는 '전체 맥락'을 파악해냅니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[3단계] 디코더와 쿼리 (Decoder &amp;amp; Queries - 2차 회의):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;구조:&lt;/b&gt; 트랜스포머 디코더 + 객체 쿼리(Object Queries)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;설명:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;'탐정(쿼리)':&lt;/b&gt; AI는 100개(예시)의 '빈 질문 카드(탐정)'를 미리 준비합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;질문:&lt;/b&gt; 100명의 탐정들이 디코더에 들어가, 2단계에서 만든 '전체 맥락'을 참조(Cross-Attention)합니다. &quot;1번 탐정, 네가 맡을 물체는 뭐고 어디 있니?&quot;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;답변:&lt;/b&gt; 각 탐정은 &quot;내가 전체 맥락을 훑어보니, '고양이'를 찾았고 좌표는 (x, y, w, h)인 것 같다&quot;라고 답을 채워 넣습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[4단계] 탐지 과정 (결과):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;헝가리안 매칭:&lt;/b&gt; 100개의 예측(답변)과 실제 정답(예: 고양이 1, 자동차 1)을 1:1로 짝짓습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;[1번 탐정 -&amp;gt; 고양이] (정답)&lt;/li&gt;
&lt;li&gt;[2번 탐정 -&amp;gt; 자동차] (정답)&lt;/li&gt;
&lt;li&gt;[3~100번 탐정 -&amp;gt; 객체 없음(No Object)] (정답)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;결과:&lt;/b&gt; 처음부터 1:1로 짝지어지므로, NMS(중복 제거)가 원천적으로 필요 없었습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;최종 평가:&lt;/b&gt; NMS가 없는 완벽한 End-to-End 모델이었지만, 2단계의 '전체 회의'가 너무 느리고 '작은 물체'를 못 찾는 치명적인 단점이 있었습니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  2부: RT-DETR의 구조 및 탐지 과정 (A-Z)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RT-DETR(Real-Time DETR)의 목표는 &quot;DETR의 NMS-Free 장점은 유지하되, (1)속도를 빠르게, (2)작은 물체도 잘 찾게 만들자!&quot;는 것이었습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;[1단계] 백본 (Backbone - CNN 특징 추출):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;구조:&lt;/b&gt; &lt;b&gt;HGNetv2&lt;/b&gt; (최적화된 CNN)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;설명:&lt;/b&gt; 이미지를 훑어보며 '요약본'을 만듭니다. &lt;b&gt;여기서 핵심!&lt;/b&gt; 기존 DETR과 달리, 1장의 맵만 쓰는 게 아니라 &lt;b&gt;3가지 크기(해상도)의 요약본&lt;/b&gt;을 모두 저장합니다. 먼저 CNN으로 CT 영상의 특징을 추출합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;C3 (고해상도):&lt;/b&gt; '작은 물체' 정보가 살아있음. (예: 80x80)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C4 (중해상도):&lt;/b&gt; '중간 물체' 정보. (예: 40x40)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C5 (저해상도):&lt;/b&gt; '전체 맥락' 정보. (예: 20x20)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[2단계] 하이브리드 인코더 (Hybrid Encoder - ⭐️ RT-DETR의 핵심 혁신 ⭐️):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;구조:&lt;/b&gt; Efficient Hybrid Encoder (AIFI + CCFM)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;설명:&lt;/b&gt; &quot;어떻게 3개의 맵을 쓰면서도 빠를 수 있지?&quot;에 대한 답입니다. &lt;b&gt;'비싼 작업'과 '싼 작업'을 분리&lt;/b&gt;했습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;A. 비싼 작업 (AIFI - 트랜스포머 회의):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;회의(셀프 어텐션)&quot;는 계산량이 너무 비싸니까(&lt;span data-math=&quot;N \times N&quot;&gt;N x N&lt;/span&gt;), &lt;b&gt;가장 싼 '저해상도(C5, 20x20)' 맵&lt;/b&gt;에만 적용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;결과:&lt;/b&gt; '전체 맥락'을 빠르게 파악했습니다. (하지만 '작은 물체' 정보는 아직 모름)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;B. 싼 작업 (CCFM - CNN 융합):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;이제 '고해상도(C3)'와 '중해상도(C4)'의 '세부 정보'를 섞어야 하는데... 여기서 또 '회의'를 하면 느려지겠지?&quot;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;해결:&lt;/b&gt; '회의(트랜스포머)' 대신, 엄청나게 빠르고 가벼운 'CNN(컨볼루션)'을 사용합니다.&lt;/li&gt;
&lt;li&gt;A에서 얻은 '전체 맥락' + C4의 '세부 정보' ➡️ &lt;b&gt;CNN으로 융합!&lt;/b&gt; ➡️ &quot;업그레이드된 C4&quot;&lt;/li&gt;
&lt;li&gt;&quot;업그레이드된 C4&quot; + C3의 '세부 정보' ➡️ &lt;b&gt;CNN으로 융합!&lt;/b&gt; ➡️ &quot;업그레이드된 C3&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;기존 DETR은 모든 픽셀을 전체 맥락과 한꺼번에 비교해서 너무 느렸습니다. RT-DETR은 &lt;b&gt;다양한 해상도의 특징&lt;/b&gt;들을 효율적으로 융합합니다. &lt;b&gt;Self-Attention&lt;/b&gt;으로 CT의 모든 부분을 동시에 비교하며 관계를 파악합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[3단계] 디코더와 '스마트' 쿼리 (Decoder &amp;amp; Query Selection):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;쿼리 선택:&lt;/b&gt; 기존 DETR처럼 '빈 카드(탐정)' 100개를 쓰지 않습니다. 2단계에서 풍부해진 정보(주로 C5)를 보고 &quot;여기 뭔가 있을 것 같아!&quot;라고 &lt;b&gt;의심되는 중요한 위치 300개&lt;/b&gt;를 '똑똑한 탐정(스마트 쿼리)'으로 선발합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;탐지:&lt;/b&gt; 300명의 '스마트 탐정'들이 디코더에 들어가, &lt;b&gt;3개의 맵(C3, C4, C5)을 모두 참조&lt;/b&gt;합니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;추론:&lt;/b&gt; &quot;C5에서 '전체 맥락'을 보니 차고, C3에서 '세부 정보'를 보니 바퀴네... 이건 '자동차'가 확실해!&quot;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Cross-Attention&lt;/b&gt;으로 인코더가 파악한 정보를 참조하며 답을 찾습니다. 각 질문(쿼리)이 하나씩 담당해서 중복 없이 출혈을 찾습니다.&lt;/li&gt;
&lt;li&gt;모델이 &lt;b&gt;300개의 질문&lt;/b&gt;을 던집니다: &quot;여기 출혈 있나요? 1번 위치에? 2번 위치에?...&quot;&lt;b&gt;Cross-Attention&lt;/b&gt;으로 인코더가 파악한 정보를 참조하며 답을 찾습니다. 각 질문(쿼리)이 하나씩 담당해서 중복 없이 출혈을 찾습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[4단계] 탐지 과정 (결과):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;300명의 탐정이 각자 1:1로 물체를 할당받아(헝가리안 매칭) 답을 내놓습니다. 실제 출혈이 5개라면, 300개 질문 중 5개만 정답과 짝지어집니다. 나머지 295개는 &quot;여기 없음&quot;이라고 배웁니다. 이 방식 덕분에 &lt;b&gt;NMS(중복 제거) 불필요&lt;/b&gt; &amp;rarr; End-to-end 학습 가능!&lt;/li&gt;
&lt;li&gt;&lt;b&gt;최종 결과:&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;NMS-Free:&lt;/b&gt; NMS(청소부)가 필요 없습니다. (DETR의 장점)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Real-Time:&lt;/b&gt; '하이브리드 인코더' 덕분에 &lt;b&gt;속도가 매우 빠릅니다.&lt;/b&gt; (YOLO와 경쟁 가능)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;High Accuracy:&lt;/b&gt; '다중 해상도 맵(C3)'을 사용해 &lt;b&gt;작은 물체도 잘 찾습니다.&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;YOLOv10과 RT-DETR은 둘 다 'NMS(후처리)'가 필요 없는 빠르고 효율적인 &lt;b&gt;End-to-End 모델&lt;/b&gt;이라는 공통점이 있지만, 그 방식은 완전히 다릅니다.&lt;br /&gt;&lt;b&gt;YOLOv10&lt;/b&gt;은 전통적인 CNN(그리드) 방식을 극한까지 최적화했습니다. '앵커 프리(Anchor-Free)'를 채택해 K-means 같은 복잡한 '앵커 박스' 준비 과정을 없앴습니다. NMS 문제는 훈련 시 '이중 헤드(Dual Head)'*를 사용해 해결했습니다. '느슨한 헤드(One-to-Many)'가 풍부한 특징 학습을 돕고, '엄격한 헤드(One-to-One)'가 &quot;물체 하나당=담당자 하나&quot;를 강제로 할당합니다. 예측 시에는 이 '엄격한 헤드'만 사용하여 하나의 물체에 대해 여러 번 중복해서 Bounding box를 그리지 않도록 했습니다.&lt;br /&gt;&lt;b&gt;RT-DETR&lt;/b&gt;은 '트랜스포머' 방식을 '실시간'에 맞게 개선했습니다. 기존 DETR은 '저해상도 맵' 1장만 사용해 '전체 회의(셀프 어텐션)'를 하느라 느리고 작은 물체를 놓쳤습니다. 반면 RT-DETR은 HGNetv2 백본으로 '다중 해상도 맵(C3-C5)'을 추출합니다.&amp;nbsp; '하이브리드 인코더'를 사용해, 비싼 '셀프 어텐션'은 저해상도(C5) 맵에만 적용하고, 고해상도(C3, C4) 정보는 빠른 CNN으로 융합하고, 이후 헝가리안 매칭으로 NMS 없이 결과를 도출합니다.&lt;/p&gt;</description>
      <category>AI</category>
      <category>yolo #detr #yolov10 #rt-detr</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/85</guid>
      <comments>https://onethingflow.tistory.com/entry/yolov10-rtdetr-A-Z%EA%B9%8C%EC%A7%80-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90#entry85comment</comments>
      <pubDate>Tue, 11 Nov 2025 13:54:16 +0900</pubDate>
    </item>
    <item>
      <title>Yolo 모델? (feat. 객체 탐지 모델)</title>
      <link>https://onethingflow.tistory.com/entry/Yolo-%EB%AA%A8%EB%8D%B8-feat-%EA%B0%9D%EC%B2%B4-%ED%83%90%EC%A7%80-%EB%AA%A8%EB%8D%B8</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 서론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인간이 눈을 뜨고 세상을 즉각적으로 인식하는 것처럼, 인공지능이 세상을 '보는' 핵심 기술을 '객체 탐지(Object Detection)'라고 부른다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체 탐지(Object Detection)란 무엇인가?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 기본 개념부터 짚고 가겠습니다. &lt;b&gt;Object Detection (객체 탐지)&lt;/b&gt;은 이미지 또는 비디오에서 특정 개체(예: 사람, 자동차, 사물)를 식별하고 그 위치를 찾아내는 컴퓨터 비전 작업입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 모델이 이 작업을 수행한다는 것은 구체적으로 다음을 의미합니다.&lt;br /&gt;한 이미지 내에서 여러 객체를 찾아내고, 각 객체의 윤곽을 그리는 &lt;b&gt;경계 상자(bounding box)&lt;/b&gt;를 탐지합니다.&lt;br /&gt;알고리즘은 이미지를 입력으로 받아, 이 경계 상자와 &lt;b&gt;객체 클래스(이름)&lt;/b&gt;의 목록을 출력합니다.&lt;br /&gt;각 경계 상자에 대해 &quot;이것은 95% 확률로 '사람'이다&quot;와 같이 예측된 클래스와 그 &lt;b&gt;신뢰도(confidence)&lt;/b&gt;를 함께 반환합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국, 이 기술은 AI가 두 가지 핵심 질문에 동시에 답하는 것과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;이것은 무엇인가?&quot; (객체 식별)&lt;br /&gt;&quot;어디에 위치해 있는가?&quot; (정확한 위치 파악)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오랫동안 AI 분야는 이 두 가지 질문에 동시에, 그리고 '빠르게' 답하는 데 어려움을 겪었습니다. 기존의 인식 방법들은 여러 단계를 거쳐야 했기 때문에, 단일 알고리즘 실행만으로는 객체를 실시간으로 감지하기 어려웠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 이 '속도'와 '정확도'의 딜레마를 해결하며 등장한 것이 오늘 우리가 자세히 알아볼 YOLO입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. YOLO의 탄생: 왜 &quot;You Only Look Once&quot;인가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YOLO가 왜 인공지능 비전 분야에서 '혁신'으로 불리는지 이해하기 위해서는 그 이전의 방식을 먼저 살펴볼 필요가 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;YOLO 이전: 2단계 탐지기 (2-Stage Detectors)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;R-CNN 계열로 대표되는 초기 객체 탐지 모델들은 이미지를 '두 번' 봐야 했다.&lt;br /&gt;후보 영역 탐색: 먼저 이미지 전체를 훑으며 '여기 뭔가 있을 것 같다'라고 판단되는 수천 개의 후보 영역(Region Proposal)을 찾는다.&lt;br /&gt;분류: 그 수천 개의 영역들을 하나씩 다시 정밀하게 살펴보며 '이것은 사람이네', '저것은 고양이네'라고 분류한다.&lt;br /&gt;이는 마치 돋보기를 들고 방 안 구석구석을 샅샅이 뒤지는 탐정의 방식과 같다. 정확도는 높을 수 있으나, 하나의 이미지를 처리하는 데 상당한 시간이 소요되었다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;YOLO의 혁신: 1단계 탐지기 (1-Stage Detectors)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YOLO(You Only Look Once)는 이름 그대로, 이 모든 과정을 '단 한 번에' 끝내는 혁신적인 접근법을 제시했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YOLO는 이미지 전체를 단 한 번(Look Once) 훑어보는 것만으로 '어디에(위치)' '무엇이(종류)' 있는지를 동시에 예측한다. 이는 마치 방문을 한 번 쓱 쳐다보고도 방 안의 모든 사람과 사물의 위치를 즉각 파악하는 인간의 시각 능력과 유사하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 '실시간(Real-Time) 처리 속도'가 바로 YOLO가 자율주행, CCTV 보안, 그리고 로보틱스 연구에 필수적인 기술로 자리 잡은 이유이다. 1초에도 수십 번씩 변하는 현실 세계에 즉각 반응해야 하는 로봇에게, YOLO의 속도는 선택이 아닌 필수였다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. YOLO의 구조: 3단계 '공장 조립 라인'&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YOLO 모델의 내부 구조는 크게 세 부분으로 나눌 수 있습니다. 거대한 '공장 조립 라인'을 상상해 보세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 백본 (Backbone): '눈' (특징 추출기)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역할: 이미지의 원본 데이터를 받아 핵심 특징(feature)을 추출합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작동: 이미지가 이 '백본'이라 불리는 깊은 컨볼루션 신경망(CNN)을 통과합니다. 초기 레이어에서는 간단한 선이나 질감을, 깊은 레이어로 갈수록 더 복잡한 형태(바퀴, 눈, 코 등)를 인식합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비유: 공장의 첫 단계. 원재료(이미지)에서 쓸만한 부품(특징)들을 모조리 뽑아내는 라인입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 넥 (Neck): '신경망' (특징 융합기)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역할: 백본에서 추출된 다양한 크기의 특징들을 융합(combine)합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작동: 백본은 이미지의 '큰 특징(예: 사람의 전신)'과 '작은 특징(예: 사람의 얼굴)'을 서로 다른 층에서 추출합니다. '넥'은 이 정보들을 위아래로 섞어주며, &quot;큰 그림&quot;과 &quot;세부 사항&quot;을 모두 고려한 풍부한 특징 맵을 만듭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비유: 여러 부품 라인(백본)에서 온 크고 작은 부품들(특징)을 한데 모아 조립하기 좋게 정리하고 결합하는 중간 라인입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 헤드 (Head): '뇌' (최종 예측기)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역할: '넥'에서 잘 정리된 특징 정보를 받아, 최종적인 예측 결과를 출력합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작동: 이 '헤드' 부분이 이미지의 여러 스케일(크기)에서 동시에 작동합니다. &quot;작은 물체는 여기서 찾고, 큰 물체는 저기서 찾자&quot;라고 정해진 각자의 영역에서 최종 답안지를 작성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비유: 공장의 마지막 단계. 잘 조립된 부품(특징)을 보고, &quot;이건 '자동차'다&quot;, &quot;위치는 여기(Bounding Box)다&quot;, &quot;98% 확신한다(Confidence)&quot;라는 세 가지 정보를 담은 '제품 태그'를 찍어냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요약: 백본이 이미지를 보고 특징을 뽑아내면, 넥이 이 특징들을 다양한 크기로 조합하고, 헤드가 이 조합된 특징을 보고 최종 예측을 수행합니다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;버전&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;백본 (Backbone)&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;넥 (Neck)&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;헤드 (Head)&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;핵심 특징&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;YOLOv1&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;GoogLeNet 기반&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;없음&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;FC Layers&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;1-Stage, Real-Time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;YOLOv3&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;Darknet-53&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;FPN&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;앵커 기반 (3 스케일)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;다중 스케일 탐지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;YOLOv4&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;CSPDarknet53&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;SPP + PANet&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;앵커 기반 (v3와 동일)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;'Bag of Freebies/Specials' 최적화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;YOLOv5&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;CSPDarknet&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;PANet&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;앵커 기반 (v3/v4와 동일)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;PyTorch, 모델 스케일링 (s/m/l/x)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;YOLOv7&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;E-ELAN&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;E-ELAN (통합됨)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;RepConv 헤드&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;구조적 효율성 극대화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;YOLOv8&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;C2f (CSP 기반)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;PANet&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;앵커 프리 &amp;amp; 분리형&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;앵커 제거, 정확도 향상&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;YOLOv9&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;GELAN&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;PANet (GELAN 기반)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;앵커 프리 &amp;amp; 분리형&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;정보 손실 최소화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;YOLOv10&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;CSPNet (최적화)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;PANet (최적화)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;NMS-Free (이중 헤드)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;End-to-End, NMS 제거&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. YOLO의 탐지 과정: '바둑판' 전략&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;511&quot; data-origin-height=&quot;287&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VPBvv/dJMcacVJmKr/ACVD58LATxYXYD6jwwwbEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VPBvv/dJMcacVJmKr/ACVD58LATxYXYD6jwwwbEK/img.png&quot; data-alt=&quot;YOLO SYSTEM&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VPBvv/dJMcacVJmKr/ACVD58LATxYXYD6jwwwbEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVPBvv%2FdJMcacVJmKr%2FACVD58LATxYXYD6jwwwbEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;511&quot; height=&quot;287&quot; data-origin-width=&quot;511&quot; data-origin-height=&quot;287&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;YOLO SYSTEM&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YOLO가 이미지를 &quot;한 번만 본다&quot;는 것은 구체적으로 어떻게 작동하는 걸까요? 그 비밀은 바로 '바둑판' 전략에 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;954&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/big9Yg/dJMcaeeWvla/LDK1NUFsktMDabehVl30QK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/big9Yg/dJMcaeeWvla/LDK1NUFsktMDabehVl30QK/img.png&quot; data-alt=&quot;Grid 분할&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/big9Yg/dJMcaeeWvla/LDK1NUFsktMDabehVl30QK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbig9Yg%2FdJMcaeeWvla%2FLDK1NUFsktMDabehVl30QK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;954&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;954&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Grid 분할&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1단계: 이미지를 '바둑판'으로 나누기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YOLO는 이미지를 받으면, 일단 이미지 전체를 일정한 크기의 '바둑판(Grid)'으로 나눕니다. (예: 13x13, 19x19 등)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2단계: 각 칸에 '책임' 할당하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 바둑판의 각 칸(Grid Cell)은 &lt;b&gt;&quot;만약 어떤 객체의 중심점이 내 칸 안에 들어오면, 그 객체를 탐지하는 건 내 책임이다&quot;&lt;/b&gt;라는 규칙을 갖습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 고양이의 정확한 중심점이 'C-5' 칸에 있다면, 오직 'C-5' 칸만이 그 고양이를 탐지할 책임을 집니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3단계: 모든 칸이 '동시에' 예측하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 모든 바둑판 칸들이 동시에 &quot;내 책임 구역에 뭔가가 있을지도 몰라!&quot;라고 외치며 예측을 쏟아냅니다. 각 칸은 여러 개의 '예측 세트'를 만들어내며, 각 세트에는 다음 3가지 정보가 포함됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경계 상자 (Bounding Box): &quot;객체가 있다면, &lt;b&gt;여기(x, y, w, h)&lt;/b&gt;에 있을 거야&quot; (위치와 크기 정보)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신뢰도 (Confidence Score): &quot;내 상자 안에 진짜 객체가 있을 확률이 이 정도(예: 80%)야&quot; (배경이 아니라 객체라는 확신)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스 확률 (Class Probability): &quot;그게 만약 객체라면, '고양이'일 확률 95%, '강아지'일 확률 3%, '자동차'일 확률 0%...&quot; (객체의 종류)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4단계: '정리'하기 (NMS - 비최대 억제)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3단계를 거치면, 수백 수천 개의 무분별한 예측 상자들이 만들어집니다. (예: 고양이 한 마리를 두고 10개의 칸이 전부 &quot;고양이다!&quot;라고 외친 상황)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 지저분한 예측들을 정리하는 마지막 단계가 바로 &lt;b&gt;'비최대 억제(NMS, Non-Maximum Suppression)'&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작동:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 예측 상자 중 신뢰도가 가장 높은 상자(예: 98% '고양이')를 일단 선택합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 상자와 너무 많이 겹치는(즉, 같은 고양이를 가리키는) 다른 상자들(예: 80% '고양이', 75% '고양이')은 모두 '억제'시켜 지워버립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;남아있는 상자들 중 다시 신뢰도가 가장 높은 상자를 선택하고, 이 과정을 반복합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과: 최종적으로 각 객체당 가장 점수가 높은 '최고의 상자' 하나씩만 남게 됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.YOLO는 실제로 어떻게 '학습'하는가?: 3가지 핵심 성적표 (Loss Function) 파헤치기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YOLO가 똑똑해지는 과정은 '시험공부'에 비유할 수 있다. 모델이 예측(답안지)을 내면, '정답지(Ground Truth)'와 비교하여 '틀린 만큼' 벌점(Loss)을 부여한다. YOLO 모델은 이 총 벌점(Total Loss)을 최소화하는 방향으로 스스로의 가중치(Weight)를 업데이트하며 학습한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YOLO의 시험지는 크게 3과목으로 나뉘며, 실제에서도 이 3가지 손실(Loss)을 중심으로 논의가 이루어진다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Bounding Box Loss (위치 과목): &quot;이것은 '어디에' 있는가?&quot;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개념: '바운딩 박스(Bounding Box)'는 모델이 예측한 사물의 위치(네모 상자)를 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;손실 함수 (IoU): 이 과목의 채점 기준은 'IoU(Intersection over Union)'이다. 이는 모델이 예측한 상자와 정답 상자(Ground Truth Box)가 얼마나 정확하게 겹치는지를 0과 1 사이의 값으로 나타낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비유: 두 상자가 100% 똑같이 겹치면 IoU=1 (0점 감점), 전혀 겹치지 않으면 IoU=0 (높은 감점)이다. YOLO는 학습을 통해 이 겹치는 면적을 최대화(즉, Bbox Loss를 최소화)하려 노력한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Classification Loss (종류 과목): &quot;이것은 '무엇'인가?&quot;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개념: 찾은 상자 안의 물체가 '사람'인지, '컵'인지, '개'인지 정확히 맞히는 과목이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;손실 함수 (Class Loss): 이는 객관식 문제를 푸는 것과 같다. 정답은 '사람'인데 모델이 '개'라고 예측하면 높은 벌점을 받는다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. DFL (정밀도 과목): &quot;얼마나 '정확하게' 맞췄는가?&quot;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개념: Distribution Focal Loss(DFL)는 YOLO의 최신 버전에서 사용되는 고급 기술이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해설: 기존 모델이 '경계선은 100번 픽셀에 있다'라고 단정적으로 예측했다면, DFL은 '경계선은 100번 픽셀에 있을 확률이 90%, 99번 픽셀에 5%, 101번 픽셀에 5%'처럼 확률 분포로 예측한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비유: 이는 마치 흐릿한 저화질 사진을 선명한 고화질 사진으로 바꾸는 것처럼, 박스의 경계선을 훨씬 더 정밀하고 날카롭게 다듬어주는 역할을 수행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YOLO의 전체 학습은 이 3가지 손실(Bbox, Class, DFL)을 동시에 최소화하려는 '줄다리기' 과정이다. 실제 R&amp;amp;D 환경에서는 이 손실들의 '가중치(Weight)'(W1, W2, W3)를 어떻게 조절하는지가 중요한 연구 주제가 된다. 예를 들어, '위치'보다 '종류'를 맞히는 것이 더 중요한 작업(task)일 수 있기 때문이다. (실제로 'classification loss is always big'이라는 관찰은 가중치 조절의 필요성을 뒷받침한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 나아가, 이 3가지 손실 함수는 YOLO의 '성적표'일 뿐만 아니라, 나중에 다룰 강화학습(RL) 에이전트에게 줄 '보상(Reward)의 원천'이 된다. 즉, 이 3가지 기본 개념을 이해하는 것이 AI 로보틱스 핵심 연구를 이해하는 첫걸음이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 결론: YOLO는 왜 강력할까요?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YOLO의 구조와 탐지 과정을 요약하면 이렇습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구조: 이미지를 백본(특징 추출) -&amp;gt; 넥(특징 융합) -&amp;gt; 헤드(예측) 3단계를 거쳐 처리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과정: 이미지를 &lt;b&gt;'바둑판'&lt;/b&gt;으로 나누고, 각 칸이 동시에 &lt;b&gt;'상자+신뢰도+클래스'&lt;/b&gt;를 예측한 뒤, &lt;b&gt;'NMS'&lt;/b&gt;로 깔끔하게 정리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 모든 과정이 단 하나의 거대한 신경망 파이프라인 안에서 '한 번에' 일어나기 때문에, YOLO는 다른 어떤 모델보다 빠르고 효율적인 실시간 객체 탐지가 가능한 것입니다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/84</guid>
      <comments>https://onethingflow.tistory.com/entry/Yolo-%EB%AA%A8%EB%8D%B8-feat-%EA%B0%9D%EC%B2%B4-%ED%83%90%EC%A7%80-%EB%AA%A8%EB%8D%B8#entry84comment</comments>
      <pubDate>Sat, 8 Nov 2025 13:41:55 +0900</pubDate>
    </item>
    <item>
      <title>DETR 모델? (feat. 초보자용 설명)</title>
      <link>https://onethingflow.tistory.com/entry/DETR-%EB%AA%A8%EB%8D%B8-feat-%EC%B4%88%EB%B3%B4%EC%9E%90%EC%9A%A9-%EC%84%A4%EB%AA%85</link>
      <description>&lt;h2&gt;1. 프롤로그: &amp;quot;틀린 그림 찾기&amp;quot;와 AI&lt;/h2&gt;
&lt;p&gt;&amp;quot;사진 속에 고양이, 자동차, 사람이 어디 있나요?&amp;quot;&lt;/p&gt;
&lt;p&gt;우리에게 이 질문은 매우 간단한 &amp;#39;틀린 그림 찾기&amp;#39; 놀이처럼 들릴 수 있습니다. 하지만 컴퓨터에게 이 질문은 수십 년간 이어진 거대한 난제였습니다. 컴퓨터가 이미지 속 특정 객체의 위치와 종류를 알아맞히는 이 기술을 &amp;#39;객체 탐지(Object Detection)&amp;#39;라고 부릅니다.&lt;/p&gt;
&lt;p&gt;이 기술은 자율주행 자동차가 보행자를 인식하고, CCTV가 이상 행동을 감지하며, 의료 AI가 엑스레이 사진에서 병변을 찾아내는 모든 현대 AI 서비스의 시작점입니다.&lt;/p&gt;
&lt;p&gt;하지만 오랫동안 컴퓨터는 이 문제를 매우 &amp;#39;무식하고&amp;#39; 복잡한 방식으로 풀어왔습니다. 바로 &amp;#39;앵커 박스(Anchor Box)&amp;#39;라는 수천 개의 &amp;#39;추측&amp;#39;에 의존하는 방식이었죠. 오늘 소개할 &lt;strong&gt;DETR&lt;/strong&gt;은 이 낡은 방식을 완전히 뒤엎은 혁신적인 모델입니다.&lt;/p&gt;
&lt;h2&gt;2. DETR 이전의 시대: 수천 개의 &amp;#39;추측&amp;#39; 상자 (앵커 박스의 한계)&lt;/h2&gt;
&lt;p&gt;DETR의 혁신성을 이해하려면, 먼저 기존 방식(YOLO, Faster R-CNN 등 유명한 모델들)이 가졌던 근본적인 한계를 알아야 합니다.&lt;/p&gt;
&lt;h3&gt;앵커 박스란?&lt;/h3&gt;
&lt;p&gt;(비유) AI에게 이미지 속 고양이를 찾으라고 시키면, 기존 모델들은 일단 이미지 위에 수천, 수만 개의 &amp;#39;미리 만들어진 추측 상자(앵커 박스)&amp;#39;를 격자무늬로 빽빽하게 겹쳐 놓습니다. 그리고 이 수만 개의 상자 하나하나에 대해 &amp;quot;이 안에 물체가 있나? 있다면 얼마나 수정해야 하나?&amp;quot;를 판단합니다.&lt;/p&gt;
&lt;h3&gt;문제점: 너무 많은 &amp;#39;중복&amp;#39;과 &amp;#39;후처리&amp;#39;&lt;/h3&gt;
&lt;p&gt;이 방식의 가장 큰 문제는, 하나의 객체(예: 고양이 한 마리)에 수십 개의 긍정적인 &amp;#39;추측&amp;#39; 상자가 동시에 겹치게 된다는 것입니다. AI가 &amp;quot;이것도 고양이 같고, 저것도 고양이 같다&amp;quot;며 수십 개의 상자를 쏟아내는 것이죠.&lt;/p&gt;
&lt;p&gt;이 지저분한 중복 상자들을 정리하기 위해 **NMS (Non-Maximum Suppression, 비최대 억제)**라는 &amp;#39;후처리&amp;#39; 과정이 필수적이었습니다. &amp;quot;가장 점수가 높은 상자만 남기고 나머지는 지워!&amp;quot;라는 별도의 정리 단계가 필요했던 것입니다.&lt;/p&gt;
&lt;p&gt;결국, AI 모델 하나로 탐지가 끝나는 것이 아니라, 복잡한 사전/사후 처리 과정이 덕지덕지 붙어있는 복잡한 파이프라인이었습니다.&lt;/p&gt;
&lt;h2&gt;3. DETR의 등장: &amp;quot;탐지&amp;quot;를 &amp;quot;번역&amp;quot; 문제로 바꾸다&lt;/h2&gt;
&lt;p&gt;2020년, Facebook AI(현 Meta AI) 연구팀은 이 문제를 완전히 다른 시각으로 접근했습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;&amp;quot;왜 굳이 수만 개를 추측하고 지워야 하지? 그냥 필요한 만큼만 &amp;#39;질문&amp;#39;하고 &amp;#39;답변&amp;#39;을 얻으면 안 될까?&amp;quot;&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;여기서 **DETR (DEtection TRansformer)**이 탄생합니다. DETR은 이 기발한 아이디어를 구현하기 위해 &amp;#39;트랜스포머(Transformer)&amp;#39; 모델을 도입했습니다.&lt;/p&gt;
&lt;h3&gt;객체 탐지를 &amp;#39;번역&amp;#39; 문제로!&lt;/h3&gt;
&lt;p&gt;트랜스포머는 원래 &amp;quot;I love you&amp;quot;라는 영어 문장을 &amp;quot;사랑해&amp;quot;라는 한국어 문장으로 번역하는 기계 번역 모델이었습니다. DETR은 이 원리를 차용해, &lt;strong&gt;&amp;#39;이미지&amp;#39;를 &amp;#39;객체 목록(List of objects)&amp;#39;으로 번역&lt;/strong&gt;하는 모델을 만들었습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;(입력) [이미지 한 장]&lt;/li&gt;
&lt;li&gt;(번역/출력) [고양이, (x: 50, y: 30, w: 20, h: 40)], [자동차, (x: 120, y: 80, w: 50, h: 30)], [사람,...],...&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;핵심 용어: &amp;#39;End-to-End&amp;#39;&lt;/h3&gt;
&lt;p&gt;이 방식의 가장 큰 혁신은 &amp;#39;앵커 박스&amp;#39;도, &amp;#39;NMS 후처리&amp;#39;도 전혀 필요 없다는 것입니다. 모델에 이미지를 넣으면, 마치 번역 결과처럼 깔끔하게 정제된 객체 목록이 &amp;#39;한 번에&amp;#39; 나옵니다.&lt;/p&gt;
&lt;p&gt;이처럼 중간의 복잡한 과정 없이 입력에서 출력까지 한 번에 이어진다고 해서 &lt;strong&gt;&amp;#39;End-to-End&amp;#39;&lt;/strong&gt; 모델이라고 부릅니다. DETR은 객체 탐지 분야를 최초로 &amp;#39;End-to-End&amp;#39;로 풀어낸 모델입니다.&lt;/p&gt;
&lt;h2&gt;4. DETR, 어떻게 작동하나요?&lt;/h2&gt;
&lt;p&gt;DETR (DEtection TRansformer): ① 이분 매칭 손실 함수 + ② Transformer&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1971&quot; data-origin-height=&quot;513&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QtoL6/dJMcaf5ZmTJ/w8ENxL5JLn74A8y8h6Nfkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QtoL6/dJMcaf5ZmTJ/w8ENxL5JLn74A8y8h6Nfkk/img.png&quot; data-alt=&quot;detr 전체 모델 개요도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QtoL6/dJMcaf5ZmTJ/w8ENxL5JLn74A8y8h6Nfkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQtoL6%2FdJMcaf5ZmTJ%2Fw8ENxL5JLn74A8y8h6Nfkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1971&quot; height=&quot;513&quot; data-origin-width=&quot;1971&quot; data-origin-height=&quot;513&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;detr 전체 모델 개요도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;1. DETR에서는 먼저 CNN통해 이미지 features을 추출&lt;/p&gt;
&lt;p&gt;2. 해당 features을 transformer encoder에 입력으로 사용하여 global 정보 추출&lt;br&gt;3. (그림에는 없지만) Query와 global 정보를 tansformer decoder의 입력으로 사용, hidden feature 추출&lt;br&gt;4. 추출된 query들 중 이분 매칭을 사용하여 GT와 예측들을 유니크하게 매칭, 남은 예측은 객체 없음(no object, ∅)로 할당하여 일대일 매칭 진행.&lt;/p&gt;
&lt;h3&gt;&amp;#39;100개의 지정 좌석&amp;#39;과 &amp;#39;3명의 정답 손님&amp;#39; 비유&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;예측 (파티 주최자의 100개 추측)&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;모델(파티 주최자)은 이미지를 보고, 파티장에 **100개의 빈 좌석(Object Queries)**을 미리 배치합니다.&lt;/li&gt;
&lt;li&gt;주최자는 100개의 각 좌석에 대해 &amp;quot;이 자리는 &amp;#39;고양이&amp;#39; 자리일 거야&amp;quot;, &amp;quot;이 자리는 &amp;#39;강아지&amp;#39; 자리일 거야&amp;quot;,..., &amp;quot;이 자리는 &amp;#39;자동차&amp;#39; 자리일 거야&amp;quot;라고 &lt;strong&gt;미리 예측&lt;/strong&gt;을 해둡니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;정답 (실제 손님 3명)&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;하지만 실제 이미지에는 &lt;strong&gt;단 3명의 진짜 손님(Ground Truth)&lt;/strong&gt;, 즉 [고양이, 강아지, 자동차]만 존재합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;이분 매칭 (최적의 1:1 좌석 배정)&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;이제 주최자(모델)는 3명의 진짜 손님을 100개의 예측 좌석 중 &lt;strong&gt;가장 알맞은 자리&lt;/strong&gt;에 1:1로 앉혀야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;#39;최적의 짝&amp;#39; 찾기:&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;주최자는 모든 가능한 조합(3명 손님 x 100개 좌석)을 두고 &amp;quot;매칭 비용(Cost)&amp;quot;을 계산합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;비용 기준 1 (클래스):&lt;/strong&gt; &amp;quot;1번 좌석은 &amp;#39;고양이&amp;#39;라고 예측했는데, 마침 &amp;#39;고양이&amp;#39; 손님이 왔네! (비용 낮음)&amp;quot; / &amp;quot;2번 좌석은 &amp;#39;사람&amp;#39;이라고 예측했는데, &amp;#39;강아지&amp;#39; 손님이 왔네? (비용 높음)&amp;quot;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;비용 기준 2 (위치):&lt;/strong&gt; &amp;quot;1번 좌석이 예측한 위치가 실제 고양이 손님의 위치와 정확히 일치하네! (비용 낮음)&amp;quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;헝가리안 알고리즘:&lt;/strong&gt; 이 수많은 조합 중, &lt;strong&gt;전체 비용이 가장 낮은(가장 완벽한) 1:1 짝짓기&lt;/strong&gt;를 찾아내는 방법이 바로 &amp;#39;헝가리안 알고리즘&amp;#39;입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;#39;객체 없음(no object)&amp;#39; 할당 (남은 97개 좌석 처리)&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;자, 3명의 진짜 손님(고양이, 강아지, 자동차)이 100개의 좌석 중 자신과 가장 잘 맞는 3개의 좌석(예: 1번, 5번, 20번 좌석)에 앉았습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;그럼 남은 97개의 빈 좌석은 어떻게 될까요?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;이것이 바로 DETR의 핵심입니다. 모델은 이 남은 97개의 좌석 모두에 **&amp;#39;객체 없음(no object, ∅)&amp;#39;**이라는 특별한 정답을 강제로 할당합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;5. DETR, 어떻게 작동하나요? (비유로 이해하는 3단계)&lt;/h2&gt;
&lt;p&gt;그렇다면 DETR은 어떻게 이미지를 객체 목록으로 &amp;#39;번역&amp;#39;할까요? 그 구조는 크게 3단계로 나눌 수 있습니다.1&lt;/p&gt;
&lt;h3&gt;1단계: 백본 (Backbone) - 이미지 &amp;#39;읽기&amp;#39;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;(비유) AI가 돋보기를 들고 이미지의 모든 픽셀을 훑어보며 중요한 시각적 특징(선, 모서리, 질감, 색상 등)을 추출합니다.&lt;/li&gt;
&lt;li&gt;(기술) 이 단계는 전통적인 CNN(예: ResNet)을 사용해 이미지의 핵심 특징을 뽑아내는 &amp;#39;특징 맵(Feature Map)&amp;#39;을 생성합니다.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2단계: 트랜스포머 인코더 (Encoder) - 맥락 &amp;#39;이해하기&amp;#39;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;(비유) 1단계에서 찾은 특징 조각들을 서로 연결해 봅니다. &amp;quot;여기 &amp;#39;바퀴&amp;#39; 특징이 있고, 저기 &amp;#39;손잡이&amp;#39; 특징이 있네. 둘은 멀리 떨어져 있지만 &amp;#39;자동차&amp;#39;라는 하나의 맥락으로 연결되겠구나.&amp;quot; 이처럼 이미지 전체의 &amp;#39;관계&amp;#39;와 &amp;#39;맥락&amp;#39;을 이해합니다.&lt;/li&gt;
&lt;li&gt;(기술) 트랜스포머의 핵심인 &amp;#39;셀프 어텐션(Self-Attention)&amp;#39;을 통해 이미지 전역의 특징들 간의 관계를 학습합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3단계: 트랜스포머 디코더 (Decoder) &amp;amp; 객체 쿼리 (Object Queries) - &amp;#39;질문하고 답하기&amp;#39;&lt;/h3&gt;
&lt;p&gt;이 부분이 DETR의 가장 빛나는 아이디어입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;객체 쿼리(Object Queries)란?&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;(비유) DETR은 $N$개(보통 100개)의 &amp;#39;질문 카드&amp;#39;를 미리 들고 있습니다.1&lt;/li&gt;
&lt;li&gt;이 카드들은 &amp;quot;이 이미지에 있는 1번 객체는 뭐고 어디 있니?&amp;quot;, &amp;quot;2번 객체는 뭐고 어디 있니?&amp;quot;,..., &amp;quot;100번 객체는 뭐고 어디 있니?&amp;quot;라고 묻는 &amp;#39;빈칸&amp;#39;과 같습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;디코더의 역할:&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;이 100개의 질문 카드(쿼리)가 2단계에서 이해한 &amp;#39;이미지 맥락(인코더 출력)&amp;#39;을 참조하여 스스로 &amp;#39;답변&amp;#39;을 채워 넣습니다.&lt;/li&gt;
&lt;li&gt;&amp;quot;1번 객체는 &amp;#39;고양이&amp;#39;, 위치는 (x, y, w, h)&amp;quot;.&lt;/li&gt;
&lt;li&gt;&amp;quot;2번 객체는 &amp;#39;자동차&amp;#39;, 위치는 (x, y, w, h)&amp;quot;.&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;&amp;quot;99번 객체는 &amp;#39;없음(No Object)&amp;#39;&amp;quot;.&lt;/li&gt;
&lt;li&gt;&amp;quot;100번 객체는 &amp;#39;없음(No Object)&amp;#39;&amp;quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;(기술) 디코더는 $N$개의 학습 가능한 &amp;#39;객체 쿼리&amp;#39;를 입력받아, 인코더-디코더 어텐션을 통해 각 쿼리에 해당하는 객체의 클래스(분류)와 바운딩 박스(좌표)를 6개의 레이어를 거치며 정교하게 예측합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;결국 DETR은 이미지에 100개의 질문을 동시에 던지고, 이미지의 맥락을 바탕으로 100개의 답변을 얻어내는 시스템입니다.&lt;/p&gt;
&lt;h2&gt;5. DETR은 어떻게 &amp;#39;정답&amp;#39;을 배우나요? (손실 함수의 비밀)&lt;/h2&gt;
&lt;p&gt;AI는 &amp;#39;정답&amp;#39;과 &amp;#39;자신의 예측&amp;#39;을 비교하며 &amp;#39;틀린 정도(Loss, 손실)&amp;#39;를 계산하고, 이 손실을 줄이는 방향으로 스스로를 업데이트(학습)합니다.&lt;/p&gt;
&lt;p&gt;DETR은 100개의 예측과 실제 정답(예: 5개)을 비교할 때, &amp;#39;헝가리안 알고리즘&amp;#39;이라는 기법을 사용해 &amp;quot;어떤 예측이 어떤 정답과 짝을 이뤄야 하는지&amp;quot; 1:1로 매칭시켜줍니다.&lt;/p&gt;
&lt;p&gt;짝을 찾은 후에는, 3가지 &amp;#39;채점 기준(손실 함수)&amp;#39;을 동시에 만족시키도록 학습합니다. 이 3가지 기준은 실제 연구실에서도 모델의 성능을 좌우하는 핵심 요소로 논의됩니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;분류 손실 (Classification Loss): &amp;quot;이름을 맞혔나?&amp;quot;&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;(비유) &amp;quot;정답은 &amp;#39;고양이&amp;#39;인데, &amp;#39;개&amp;#39;라고 예측하면 큰 감점!&amp;quot;&lt;/li&gt;
&lt;li&gt;(연구 자료) 연구팀은 이 손실을 CLS (Classification Loss)라고 부르며, 모델이 객체의 종류를 정확히 분류했는지 평가합니다.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L1 손실 (L1 Loss): &amp;quot;좌표를 정확히 찍었나?&amp;quot;&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;(비유) &amp;quot;정답 박스 좌표 (x, y)와 예측 박스 좌표 (x&amp;#39;, y&amp;#39;) 사이의 &amp;#39;절대 거리&amp;#39;를 계산합니다. 1픽셀이라도 틀리면 감점.&amp;quot;&lt;/li&gt;
&lt;li&gt;(연구 자료) $L1$ Loss는 박스의 중심점과 크기(너비, 높이) 좌표값 자체의 차이를 직접적으로 줄이는 데 중점을 둡니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GIoU 손실 (GIoU Loss): &amp;quot;박스를 예쁘게 &amp;#39;포옹&amp;#39;했나?&amp;quot;&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;(비유) $L1$ 손실만으로는 한계가 있습니다. 박스의 중심 좌표는 같더라도($L1$ 손실 = 0), 박스 크기가 정답과 다르면 객체를 제대로 감싸지 못할 수 있습니다. GIoU는 &amp;quot;정답 박스와 예측 박스가 얼마나 잘 겹쳤는지(IoU)&amp;quot; 그 자체를 측정합니다.&lt;/li&gt;
&lt;li&gt;(연구 자료) 연구팀은 이 GIoU 손실을 매우 중요하게 다루며, 이는 박스의 &amp;#39;모양&amp;#39;과 &amp;#39;겹침&amp;#39;을 직접적으로 최적화합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;결국 DETR은 &amp;#39;이름표(분류)&amp;#39;, &amp;#39;절대 위치(L1)&amp;#39;, &amp;#39;겹치는 모양(GIoU)&amp;#39;이라는 3가지 기준을 동시에 만족시키도록 학습합니다.&lt;/p&gt;
&lt;h2&gt;RT-DETR이란?&lt;/h2&gt;
&lt;p&gt;RT-DETR의 풀네임은 Real-Time Detection Transformer이고, DETR의 성능과 단순한 파이프라인은 유지하면서 &lt;strong&gt;&amp;quot;실시간 속도&amp;quot;&lt;/strong&gt;까지 확보한 최신 트랜스포머 기반 객체 탐지 모델이다.&lt;/p&gt;
&lt;p&gt;주요 개선점:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;멀티스케일 특징(Multi-scale Feature) 효율적으로 처리: 백본과 하이브리드 인코더 구조로 다양한 크기의 객체를 더 빠르고 정확하게 탐지&lt;/li&gt;
&lt;li&gt;디코더 구조 단순화 및 최적화: 디코더 계층 수를 조정해 속도/정확도를 유연하게 조절 가능.&lt;/li&gt;
&lt;li&gt;속도와 정확도를 모두 잡은 구조: GPU 기준 SOTA급 실시간 처리 및 영향 없는 정확도 달성.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;YOLOv10과 차이&lt;/h3&gt;
&lt;p&gt;YOLOv10과 RT-DETR 둘 다 최신 객체 탐지 인공지능 모델이지만, 내부 동작 방식과 쓰임새에는 뚜렷한 차이가 있습니다. 특히, 둘 다 옛날 방식에서 자주 쓰던 &lt;strong&gt;NMS(Non-Maximum Suppression)&lt;/strong&gt;와 앵커박스(anchor box) 없이 동작하는 &amp;quot;End-to-End&amp;quot; 구조라는 점이 공통점입니다.&lt;/p&gt;
&lt;h4&gt;YOLOv10&lt;/h4&gt;
&lt;p&gt;기존의 방식(CNN)을 극한까지 최적화하고 불필요한 부품(NMS)을 제거하여 엄청나게 빠른 속도를 달성한 것이 특징입니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;YOLOv10: &amp;quot;수천 개의 &amp;#39;관할 구역&amp;#39; 담당자&amp;quot;  ️&lt;br&gt;시작: YOLO는 근본적으로 이미지를 &lt;strong&gt;바둑판처럼 잘게 쪼갠 그리드(Grid)&lt;/strong&gt;에서 시작합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#39;탐정&amp;#39;의 정체: YOLO의 &amp;#39;탐정&amp;#39;은 RT-DETR처럼 추상적인 요원이 아니라, 이 &lt;strong&gt;바둑판의 각 칸(및 앵커 박스)에서 대기하는 &amp;#39;수천 명의 지역 담당자&amp;#39;&lt;/strong&gt;입니다. 이들은 &amp;#39;정적&amp;#39;입니다.&lt;/p&gt;
&lt;p&gt;일하는 방식 (할당):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;예전 YOLO (v3~v8): 모든 &amp;#39;담당자&amp;#39;가 자기 구역에 물체가 보이면 일단 소리쳤습니다. (&amp;quot;내 구역에 고양이 중심!&amp;quot;) -&amp;gt; 그래서 중복된 박스가 수십 개씩 생겼고, &amp;#39;청소(NMS)&amp;#39;가 꼭 필요했습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;YOLOv10 (Smart Manager): 훈련(Training) 과정에서 &lt;strong&gt;&amp;#39;일대일 할당&amp;#39;&lt;/strong&gt;이라는 규칙을 도입했습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;quot;저기 고양이 1마리 보이지? 3행 5열 담당자! 너만 저 고양이에 대해 보고해. 나머지 담당자는 저 고양이에 대해선 조용히 해.&amp;quot;&lt;/p&gt;
&lt;p&gt;즉, &amp;#39;관리자(이중 헤드)&amp;#39;가 배정한다기보다, 훈련 시스템 자체가 &lt;strong&gt;&amp;#39;하나의 물체 = 오직 하나의 담당자&amp;#39;&lt;/strong&gt;라고 짝을 지어(Matching) 강제로 훈련시킵니다.&lt;/p&gt;
&lt;p&gt;핵심: 탐정(Grid Cell)들이 서로 협상하는 것이 아니라, 훈련을 통해 &lt;strong&gt;각자의 &amp;#39;책임 구역&amp;#39;이 명확하게 &amp;#39;할당&amp;#39;&lt;/strong&gt;됩니다. 애초에 한 물체에 대해 한 명만 대답하도록 &amp;#39;설계&amp;#39;된 것입니다.&lt;/p&gt;
&lt;h4&gt;RT-DETR&lt;/h4&gt;
&lt;p&gt;GPT나 BERT 같은 최신 AI 언어 모델에 사용되는 &amp;#39;트랜스포머&amp;#39; 기술을 객체 탐지에 적용한 모델입니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;RT-DETR: &amp;quot;100명의 엘리트 특수요원 (Query)&amp;quot;  &lt;br&gt;시작: RT-DETR은 100명(혹은 300명)의 &lt;strong&gt;&amp;#39;빈 슬롯&amp;#39; 혹은 &amp;#39;특수요원&amp;#39;&lt;/strong&gt;으로 시작합니다. 이들은 처음에는 아무것도 모릅니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;일하는 방식 (협상):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;이 100명의 요원들이 이미지 전체를 함께 훑어봅니다. (Cross-Attention)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;그다음, 요원들끼리 서로 &amp;#39;회의&amp;#39;(Self-Attention)를 시작합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;quot;내가 저기 큰 고양이를 맡을게.&amp;quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;quot;알았어, 그럼 난 그 옆의 작은 강아지를 맡을게.&amp;quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;quot;5번 요원, 넌 1번(고양이)이랑 겹치는 것 같으니 다른 걸 찾아봐.&amp;quot;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;핵심: 탐정(Query)들이 &lt;strong&gt;&amp;#39;서로 소통하고 협상&amp;#39;&lt;/strong&gt;하여 &amp;#39;동적으로&amp;#39; 역할을 분배합니다. 100개의 슬롯이 100개의 물체를 알아서 나눠 맡습니다.&lt;/p&gt;
&lt;h2&gt;  결론&lt;/h2&gt;
&lt;p&gt;DETR은 &amp;#39;앵커 박스&amp;#39;와 &amp;#39;NMS&amp;#39;라는 낡은 관행을 깨고, 트랜스포머를 통해 객체 탐지를 &amp;#39;End-to-End&amp;#39; 문제로 재정의했습니다. &lt;/p&gt;
&lt;p&gt;RT-DETR: 100명의 추상적인 탐정이 실시간 협상을 통해 역할을 나눕니다.&lt;/p&gt;
&lt;p&gt;YOLOv10: 수천 개의 고정된 위치의 탐정이 훈련 규칙에 따라 1:1로 역할을 할당받습니다.&lt;/p&gt;
&lt;p&gt;RT-DETR은 &lt;strong&gt;&amp;#39;동적인 엘리트 요원&amp;#39;&lt;/strong&gt;이고, YOLOv10은 &lt;strong&gt;&amp;#39;정적인 지역 담당자&amp;#39;&lt;/strong&gt;라는 근본적인 차이가 있습니다.&lt;/p&gt;
&lt;p&gt;RT-DETR이 YOLOv8을 상대로 &amp;#39;정확도&amp;#39;의 기준을 높였고, YOLOv10이 그 RT-DETR을 &amp;#39;속도&amp;#39;와 &amp;#39;정확도&amp;#39; 모든 면에서 다시 뛰어넘었습니다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>거대웅 TitanBear</author>
      <guid isPermaLink="true">https://onethingflow.tistory.com/83</guid>
      <comments>https://onethingflow.tistory.com/entry/DETR-%EB%AA%A8%EB%8D%B8-feat-%EC%B4%88%EB%B3%B4%EC%9E%90%EC%9A%A9-%EC%84%A4%EB%AA%85#entry83comment</comments>
      <pubDate>Sat, 8 Nov 2025 02:09:14 +0900</pubDate>
    </item>
  </channel>
</rss>