<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>harchiving</title>
    <link>https://harchiving.tistory.com/</link>
    <description>Computer Science Engineering, undergraduate student</description>
    <language>ko</language>
    <pubDate>Sun, 19 Jul 2026 15:30:15 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>harchiving</managingEditor>
    <image>
      <title>harchiving</title>
      <url>https://tistory1.daumcdn.net/tistory/7757715/attach/9196d2eec13844818e9605aa38cde339</url>
      <link>https://harchiving.tistory.com</link>
    </image>
    <item>
      <title>[코드트리] 갭체크로 한 달간 약점 유형 돌아본 후기</title>
      <link>https://harchiving.tistory.com/31</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글은 &lt;b&gt;코드트리 청약챌린지 7회차 미션&lt;/b&gt;으로 작성하는 중간점검 후기다.&lt;br /&gt;이번 회차 미션은 다시 한 번 &lt;b&gt;갭체크&lt;/b&gt;를 응시하고, 지난 4주 동안의 학습이 어떤 변화를 만들었는지 돌아보는 것이었다. 처음 갭체크를 봤을 때는 내가 어떤 부분이 부족한지도 정확히 모르는 상태였다. 문제를 풀면서 막히는 부분은 있었지만, 그것이 단순한 실수인지 개념 부족인지 구분하기 어려웠다. 그래서 이번 두 번째 갭체크는 단순한 실력 확인이라기보다, 한 달 동안의 학습 방향이 잘 맞았는지 확인하는 의미가 컸다.&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;첫 번째 갭체크 때는 기본 문법이나 단순 구현 문제는 어느 정도 따라갈 수 있었지만, 문제 조건을 차분히 정리하고 코드로 옮기는 과정에서 자주 막혔다. 특히 반복문 범위, 조건 처리, 함수로 코드를 나누는 부분에서 실수가 있었다. 당시에는 문제를 맞혔는지 틀렸는지만 신경 썼는데, 갭체크 결과를 보고 나니 내가 반복적으로 흔들리는 지점이 있다는 것을 알게 되었다.&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-filename=&quot;스크린샷 2026-06-22 오후 10.27.04.png&quot; data-origin-width=&quot;1886&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3UnXN/dJMcagsqjGw/V9HthEptx19tKazDWlYoY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3UnXN/dJMcagsqjGw/V9HthEptx19tKazDWlYoY0/img.png&quot; data-alt=&quot;before&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3UnXN/dJMcagsqjGw/V9HthEptx19tKazDWlYoY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3UnXN%2FdJMcagsqjGw%2FV9HthEptx19tKazDWlYoY0%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;1886&quot; height=&quot;630&quot; data-filename=&quot;스크린샷 2026-06-22 오후 10.27.04.png&quot; data-origin-width=&quot;1886&quot; data-origin-height=&quot;630&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;before&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오후 10.27.30.png&quot; data-origin-width=&quot;1880&quot; data-origin-height=&quot;628&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Xoum3/dJMcacKnZve/7J1BjbCKFP48fThOI7w0Sk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Xoum3/dJMcacKnZve/7J1BjbCKFP48fThOI7w0Sk/img.png&quot; data-alt=&quot;after&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Xoum3/dJMcacKnZve/7J1BjbCKFP48fThOI7w0Sk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXoum3%2FdJMcacKnZve%2F7J1BjbCKFP48fThOI7w0Sk%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;1880&quot; height=&quot;628&quot; data-filename=&quot;스크린샷 2026-06-22 오후 10.27.30.png&quot; data-origin-width=&quot;1880&quot; data-origin-height=&quot;628&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;after&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;비포와 애프터를 비교해 보니, 아직 완벽하게 약점이 사라졌다고 말하기는 어렵지만 문제를 바라보는 방식은 분명 달라졌다고 느꼈다. 첫 갭체크에서는 결과를 보고 부족한 부분을 확인하는 데 그쳤다면, 이번에는 내가 어떤 부분을 보완했고 어떤 점이 아직 남아 있는지 조금 더 구체적으로 볼 수 있었다. 단순히 점수나 결과만 비교하는 것이 아니라, 지난 한 달 동안의 학습 습관이 어떻게 바뀌었는지를 확인할 수 있었다는 점에서 의미가 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;특히 기억에 남는 학습은 &lt;b&gt;Trail 2 프로그래밍 연습의 챕터 1 함수 중 레슨 1 값을 반환하지 않는 함수&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;&amp;nbsp;&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://www.codetree.ai/&quot;&gt;코드트리 바로가기&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1782135058478&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;Codetree: Master Coding Interviews - Data Structures &amp;amp; Algorithms&quot; data-og-description=&quot;Master algorithms, ace tech interviews, and elevate your coding skills with Codetree's systematic curriculum and expert-crafted problem sets.&quot; data-og-host=&quot;www.codetree.ai&quot; data-og-source-url=&quot;https://www.codetree.ai/&quot; data-og-url=&quot;https://www.codetree.ai/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bS7IqZ/dJMb8XkpdmL/gfd3SCRqmJLQUOFb8mEREk/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400,https://scrap.kakaocdn.net/dn/chEkPS/dJMb8UHYZmb/2hxBkkcgrJXrCy0nrpfJuk/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400&quot;&gt;&lt;a href=&quot;https://www.codetree.ai/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.codetree.ai/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bS7IqZ/dJMb8XkpdmL/gfd3SCRqmJLQUOFb8mEREk/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400,https://scrap.kakaocdn.net/dn/chEkPS/dJMb8UHYZmb/2hxBkkcgrJXrCy0nrpfJuk/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400');&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;Codetree: Master Coding Interviews - Data Structures &amp;amp; Algorithms&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Master algorithms, ace tech interviews, and elevate your coding skills with Codetree's systematic curriculum and expert-crafted problem sets.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.codetree.ai&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;물론 아직 아쉬운 점도 있다. 두 번째 갭체크를 봤다고 해서 모든 약점이 바로 해결된 것은 아니다. 여전히 조건이 복잡한 문제에서는 시간이 걸리고, 구현 과정에서 작은 실수가 생기기도 한다. 하지만 이번 중간점검을 통해 중요한 것은 한 번에 완벽해지는 것이 아니라, 내가 어떤 부분에서 나아지고 있는지 확인하며 꾸준히 이어가는 것이라는 생각이 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;이번 7회차 미션은 지난 한 달을 돌아볼 수 있는 좋은 중간점검이었다. 처음에는 막막했던 약점들이 아직 완전히 사라진 것은 아니지만, 적어도 어떻게 공부해야 할지는 조금씩 보이기 시작했다. 앞으로도 코드트리와 함께 꾸준히 학습하면서 부족한 부분을 하나씩 채워가고 싶다. 다음 갭체크에서는 지금보다 더 성장한 결과를 확인할 수 있도록 계속 루틴을 이어가야겠다  &lt;/p&gt;</description>
      <category>개발자취업</category>
      <category>갭체크</category>
      <category>코드트리</category>
      <category>코딩테스트</category>
      <category>코딩테스트준비</category>
      <category>코테공부</category>
      <author>harchiving</author>
      <guid isPermaLink="true">https://harchiving.tistory.com/31</guid>
      <comments>https://harchiving.tistory.com/31#entry31comment</comments>
      <pubDate>Mon, 22 Jun 2026 22:31:27 +0900</pubDate>
    </item>
    <item>
      <title>[코드트리 후기] 북마크로 나만의 복습 루틴 만들기</title>
      <link>https://harchiving.tistory.com/30</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글은 &lt;b&gt;코드트리 청약챌린지 6회차 미션&lt;/b&gt;으로 작성하는 후기다.&lt;br /&gt;이번 회차 미션의 주제는 코드트리의 &lt;b&gt;북마크 기능&lt;/b&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;2866&quot; data-origin-height=&quot;804&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPzc8b/dJMcaaZWNsb/b7RkDZgtTXt8rtMpsFKOXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPzc8b/dJMcaaZWNsb/b7RkDZgtTXt8rtMpsFKOXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPzc8b/dJMcaaZWNsb/b7RkDZgtTXt8rtMpsFKOXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPzc8b%2FdJMcaaZWNsb%2Fb7RkDZgtTXt8rtMpsFKOXK%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;2866&quot; height=&quot;804&quot; data-origin-width=&quot;2866&quot; data-origin-height=&quot;804&quot;/&gt;&lt;/span&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;이번에 북마크해 둔 문제를 다시 풀면서 가장 크게 깨달은 점은, 처음 풀 때 막혔던 부분이 시간이 지난 뒤에도 비슷하게 다시 막힌다는 것이었다. 처음에는 단순한 실수라고 생각했던 부분도 다시 보니 반복되는 약점이었다. 예를 들어 조건을 꼼꼼히 읽지 않거나, 반복문의 범위를 정확히 잡지 못하는 경우가 있었다. 한 번 틀리고 넘어갔다면 그냥 잊혔을 문제였지만, 북마크해 두고 다시 풀어보니 내가 어떤 유형에서 실수를 반복하는지 확인할 수 있었다.&lt;/p&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;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;br /&gt;  &lt;a href=&quot;https://www.codetree.ai/&quot;&gt;코드트리 바로가기&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1781505660673&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;Codetree: Master Coding Interviews - Data Structures &amp;amp; Algorithms&quot; data-og-description=&quot;Master algorithms, ace tech interviews, and elevate your coding skills with Codetree's systematic curriculum and expert-crafted problem sets.&quot; data-og-host=&quot;www.codetree.ai&quot; data-og-source-url=&quot;https://www.codetree.ai/&quot; data-og-url=&quot;https://www.codetree.ai/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/MSZn9/dJMb88GdKMr/zfTkAz2grLazAQyi4SKSi0/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400,https://scrap.kakaocdn.net/dn/oFXHS/dJMb84X7t8I/KWjasfkDdhinKTOnN5nqOK/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400&quot;&gt;&lt;a href=&quot;https://www.codetree.ai/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.codetree.ai/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/MSZn9/dJMb88GdKMr/zfTkAz2grLazAQyi4SKSi0/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400,https://scrap.kakaocdn.net/dn/oFXHS/dJMb84X7t8I/KWjasfkDdhinKTOnN5nqOK/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400');&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;Codetree: Master Coding Interviews - Data Structures &amp;amp; Algorithms&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Master algorithms, ace tech interviews, and elevate your coding skills with Codetree's systematic curriculum and expert-crafted problem sets.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.codetree.ai&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;다른 학습 서비스와 비교했을 때 코드트리의 장점은 커리큘럼 학습과 복습 기능을 함께 활용하기 좋다는 점이었다. 다른 곳에서도 즐겨찾기 기능은 있을 수 있지만, 코드트리는 학습 흐름 안에서 바로 북마크하고 다시 돌아볼 수 있어서 복습 루틴을 만들기 편했다. 특히 코딩테스트 공부처럼 누적 학습이 중요한 분야에서는 내가 틀렸던 문제를 다시 확인하는 과정이 꼭 필요하다고 생각한다.&lt;/p&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;p data-ke-size=&quot;size16&quot;&gt;이번 6회차 미션을 통해 복습은 단순히 틀린 문제를 다시 보는 것이 아니라, 내가 어떤 방식으로 사고했고 어디에서 실수했는지 확인하는 과정이라는 것을 느꼈다. 북마크 기능은 그 과정을 더 쉽게 만들어주는 도구였다. 앞으로도 새로운 문제를 풀다가 헷갈리거나 다시 풀어볼 필요가 있는 문제는 바로 북마크에 저장하고, 일정 시간이 지난 뒤 다시 풀어보는 루틴을 이어가고 싶다.&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;코딩테스트 공부에서 중요한 것은 많이 푸는 것만이 아니라, 틀린 문제를 확실히 내 것으로 만드는 일이라고 생각한다. 이번 북마크 기능 활용을 통해 나만의 오답노트와 복습 루틴을 조금씩 만들어갈 수 있었다. 앞으로도 코드트리 커리큘럼을 따라가면서 북마크를 적극적으로 활용해, 놓친 개념과 실수를 하나씩 줄여가야겠다  &lt;/p&gt;</description>
      <category>공부습관</category>
      <category>오답노트</category>
      <category>코드트리</category>
      <category>코딩테스트</category>
      <category>코테공부</category>
      <author>harchiving</author>
      <guid isPermaLink="true">https://harchiving.tistory.com/30</guid>
      <comments>https://harchiving.tistory.com/30#entry30comment</comments>
      <pubDate>Mon, 15 Jun 2026 15:42:29 +0900</pubDate>
    </item>
    <item>
      <title>[코딩테스트] 코드트리 알림톡으로 매일 학습 루틴 만들기</title>
      <link>https://harchiving.tistory.com/29</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글은 &lt;b&gt;코드트리 청약챌린지 5회차 미션&lt;/b&gt;으로 작성하는 후기다.&lt;br /&gt;이번 회차 미션의 주제는 다양한 동기부여 방식을 활용해 꾸준히 학습한 경험을 공유하는 것이었다. 코딩테스트 공부는 한 번에 몰아서 하는 것보다 매일 조금씩 이어가는 것이 중요하다고 생각하지만, 실제로 꾸준히 실천하는 일은 생각보다 쉽지 않았다. 그래서 이번에는 코드트리의 &lt;b&gt;학습 리마인더 알림톡&lt;/b&gt;을 활용해 학습 루틴을 만들어보았다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1179&quot; data-origin-height=&quot;1499&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/enbNTc/dJMcaiXP4Ri/2XwZixbJzgIfy4DWOerH90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/enbNTc/dJMcaiXP4Ri/2XwZixbJzgIfy4DWOerH90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/enbNTc/dJMcaiXP4Ri/2XwZixbJzgIfy4DWOerH90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FenbNTc%2FdJMcaiXP4Ri%2F2XwZixbJzgIfy4DWOerH90%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;329&quot; height=&quot;418&quot; data-origin-width=&quot;1179&quot; data-origin-height=&quot;1499&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&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;nbsp;&lt;/p&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;코드트리 학습을 하면서 느낀 점은 커리큘럼이 정리되어 있어 알림을 받은 뒤 바로 이어서 공부하기 좋다는 점이었다. 다른 학습 서비스에서는 문제를 고르는 데 시간이 걸리거나, 내가 어디까지 공부했는지 다시 확인해야 하는 경우가 있었다. 반면 코드트리는 내가 학습하던 흐름을 이어가기 쉬워서 알림을 받은 뒤 바로 접속해 다음 내용을 확인하기 좋았다. 알림이 단순히 접속을 유도하는 데서 끝나는 것이 아니라, 실제 학습으로 이어지기 쉬운 구조라는 점이 좋았다.&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;ldquo;하루에 아주 조금이라도 코드트리에 들어가 보기&amp;rdquo;, &amp;ldquo;문제 하나라도 읽어보기&amp;rdquo;, &amp;ldquo;어제 풀던 레슨을 이어서 확인하기&amp;rdquo;처럼 낮은 기준으로 시작하려고 했다. 이 방식이 오히려 꾸준함을 유지하는 데 더 현실적이라고 느꼈다.&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;알림톡의 체감 효과는 생각보다 분명했다. 평소 같으면 그냥 지나쳤을 시간에도 알림을 보고 학습을 떠올릴 수 있었고, 공부를 완전히 잊어버리는 날이 줄었다. 물론 알림이 온다고 해서 자동으로 실력이 늘어나는 것은 아니다. 결국 직접 문제를 풀고, 틀린 부분을 다시 확인하고, 풀이 과정을 정리하는 것은 내가 해야 할 일이다. 하지만 그 시작점을 만들어준다는 점에서 알림톡은 좋은 동기부여 도구라고 생각했다.&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://www.codetree.ai/&quot;&gt;코드트리 바로가기&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1780888949175&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;Codetree: Master Coding Interviews - Data Structures &amp;amp; Algorithms&quot; data-og-description=&quot;Master algorithms, ace tech interviews, and elevate your coding skills with Codetree's systematic curriculum and expert-crafted problem sets.&quot; data-og-host=&quot;www.codetree.ai&quot; data-og-source-url=&quot;https://www.codetree.ai/&quot; data-og-url=&quot;https://www.codetree.ai/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dunTim/dJMb88GcSUU/8OTEwjOQeoxNaCnb2PRZwk/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400,https://scrap.kakaocdn.net/dn/bYAEfn/dJMb82eUSIj/Tq0vplddx4QXOD9ugnJOQK/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400&quot;&gt;&lt;a href=&quot;https://www.codetree.ai/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.codetree.ai/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dunTim/dJMb88GcSUU/8OTEwjOQeoxNaCnb2PRZwk/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400,https://scrap.kakaocdn.net/dn/bYAEfn/dJMb82eUSIj/Tq0vplddx4QXOD9ugnJOQK/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400');&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;Codetree: Master Coding Interviews - Data Structures &amp;amp; Algorithms&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Master algorithms, ace tech interviews, and elevate your coding skills with Codetree's systematic curriculum and expert-crafted problem sets.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.codetree.ai&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;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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 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;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘기초</category>
      <category>알림톡</category>
      <category>코드트리</category>
      <category>코딩테스트</category>
      <category>코테공부</category>
      <category>학습리마인더</category>
      <author>harchiving</author>
      <guid isPermaLink="true">https://harchiving.tistory.com/29</guid>
      <comments>https://harchiving.tistory.com/29#entry29comment</comments>
      <pubDate>Mon, 8 Jun 2026 12:23:13 +0900</pubDate>
    </item>
    <item>
      <title>[코드트리] 함수 알고리즘 기초 학습 후기</title>
      <link>https://harchiving.tistory.com/28</link>
      <description>&lt;p data-end=&quot;330&quot; data-start=&quot;140&quot; data-ke-size=&quot;size16&quot;&gt;이번 글은 &lt;b&gt;코드트리 청약챌린지 3주차 미션&lt;/b&gt;으로 작성하는 학습 후기다.&lt;br /&gt;2주차에는 갭체크를 통해 현재 내 실력을 점검했고, 3주차에는 그 결과를 바탕으로 실제 커리큘럼을 따라가며 부족한 부분을 채워보았다. 이번에 내가 학습한 내용은 Trail 2 프로그래밍 연습의 챕터 1 함수 중 레슨 1 &amp;lsquo;값을 반환하지 않는 함수&amp;rsquo;였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2874&quot; data-origin-height=&quot;1450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eHqYEb/dJMb997zH69/yrkFevq1SbSgeipI84eAWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eHqYEb/dJMb997zH69/yrkFevq1SbSgeipI84eAWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eHqYEb/dJMb997zH69/yrkFevq1SbSgeipI84eAWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeHqYEb%2FdJMb997zH69%2FyrkFevq1SbSgeipI84eAWk%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;2874&quot; height=&quot;1450&quot; data-origin-width=&quot;2874&quot; data-origin-height=&quot;1450&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;358&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;576&quot; data-start=&quot;360&quot; data-ke-size=&quot;size16&quot;&gt;코드트리의 커리큘럼은 큰 Trail 안에 챕터가 있고, 다시 그 안에서 레슨 단위로 학습이 이어지는 구조였다. 단순히 문제만 풀게 하는 방식이 아니라, 먼저 개념을 확인하고 그 내용을 바탕으로 연습 문제를 풀어보는 흐름이라 처음 학습하는 내용도 부담 없이 따라갈 수 있었다. 이번에 학습한 함수 레슨도 기본 개념을 이해한 뒤, 직접 코드를 작성하면서 익숙해지는 방식으로 구성되어 있었다.&lt;/p&gt;
&lt;p data-end=&quot;576&quot; data-start=&quot;360&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;774&quot; data-start=&quot;578&quot; data-ke-size=&quot;size16&quot;&gt;이번 레슨에서 다룬 &lt;b&gt;값을 반환하지 않는 함수&lt;/b&gt;는 말 그대로 특정 값을 돌려주는 것이 목적이 아니라, 함수 안에서 정해진 동작을 수행하는 형태였다. 처음에는 함수라고 하면 결과값을 return으로 돌려줘야 한다는 이미지가 강했는데, 이번 레슨을 통해 출력이나 반복되는 동작을 정리하는 데에도 함수를 사용할 수 있다는 점을 다시 이해하게 되었다.&lt;/p&gt;
&lt;p data-end=&quot;774&quot; data-start=&quot;578&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;981&quot; data-start=&quot;776&quot; data-ke-size=&quot;size16&quot;&gt;문제를 풀면서 가장 많이 신경 쓴 부분은 &amp;ldquo;어떤 코드를 함수로 분리해야 하는가&amp;rdquo;였다. 평소에는 짧은 문제를 풀 때 코드를 위에서부터 순서대로 작성하는 편이었는데, 함수 단원에서는 반복되거나 의미가 분명한 동작을 따로 묶는 연습이 필요했다. 처음에는 굳이 함수를 만들어야 하나 싶기도 했지만, 문제를 풀다 보니 함수로 나누면 코드의 역할이 더 잘 보인다는 점을 느꼈다.&lt;/p&gt;
&lt;p data-end=&quot;981&quot; data-start=&quot;776&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1168&quot; data-start=&quot;983&quot; 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;2880&quot; data-origin-height=&quot;1452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czCQgk/dJMcafNxJEO/mTc11xlPXWkZCy1CvdzzZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czCQgk/dJMcafNxJEO/mTc11xlPXWkZCy1CvdzzZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czCQgk/dJMcafNxJEO/mTc11xlPXWkZCy1CvdzzZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczCQgk%2FdJMcafNxJEO%2FmTc11xlPXWkZCy1CvdzzZk%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;2880&quot; height=&quot;1452&quot; data-origin-width=&quot;2880&quot; data-origin-height=&quot;1452&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;1201&quot; data-start=&quot;1170&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1407&quot; data-start=&quot;1203&quot; data-ke-size=&quot;size16&quot;&gt;레슨을 끝까지 풀고 나니, 함수에 대한 감각이 조금 더 선명해졌다. 이전에는 문제를 풀 때 필요한 코드를 한 번에 작성하는 데 집중했다면, 이번에는 &amp;ldquo;이 부분은 함수로 따로 빼면 더 보기 좋을까?&amp;rdquo;, &amp;ldquo;이 함수는 어떤 동작을 담당해야 할까?&amp;rdquo;를 생각하게 되었다. 기본 문제부터 연습 문제까지 따라가면서 같은 개념을 여러 번 적용해 볼 수 있었던 점도 도움이 되었다.&lt;/p&gt;
&lt;p data-end=&quot;1407&quot; data-start=&quot;1203&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1594&quot; data-start=&quot;1409&quot; data-ke-size=&quot;size16&quot;&gt;코드트리의 장점은 학습 흐름이 단계적으로 이어진다는 점이었다. 다른 학습 서비스에서는 문제를 고르는 것부터 고민해야 하는 경우가 있었는데, 코드트리는 정해진 커리큘럼을 따라가면 자연스럽게 개념 학습과 문제 풀이가 이어졌다. 특히 함수처럼 기초 개념이지만 앞으로 계속 사용하게 될 내용을 레슨 단위로 나누어 학습할 수 있어서 좋았다.&lt;/p&gt;
&lt;p data-end=&quot;1594&quot; data-start=&quot;1409&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1786&quot; data-start=&quot;1596&quot; data-ke-size=&quot;size16&quot;&gt;해설과 모범코드도 복습할 때 도움이 되었다. 내가 작성한 코드와 비교하면서 함수 이름을 어떻게 정리했는지, 함수 안에 어떤 동작을 넣었는지 확인할 수 있었다. 내가 푼 코드가 정답이더라도 모범코드를 보면 더 간결하게 작성할 수 있는 부분이 보였다. 이 과정에서 단순히 답을 맞히는 것보다 코드를 더 깔끔하게 만드는 연습도 중요하다고 느꼈다.&lt;/p&gt;
&lt;p data-end=&quot;1786&quot; data-start=&quot;1596&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1944&quot; data-start=&quot;1788&quot; data-ke-size=&quot;size16&quot;&gt;아쉬운 점을 하나 꼽자면, 함수가 실제 코딩테스트 문제에서 어떻게 활용되는지 예시가 조금 더 많으면 좋겠다고 생각했다. 기초 레슨에서는 개념을 익히는 것이 우선이지만, 나중에 구현이나 시뮬레이션 문제에서 함수를 어떻게 나누면 좋은지까지 연결해서 보여주면 더 도움이 될 것 같았다.&lt;/p&gt;
&lt;p data-end=&quot;1944&quot; data-start=&quot;1788&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2012&quot; data-start=&quot;1946&quot; data-ke-size=&quot;size16&quot;&gt;코드트리는 아래 링크에서 확인할 수 있다.&lt;br /&gt;  &lt;a href=&quot;https://www.codetree.ai/&quot; data-end=&quot;2012&quot; data-start=&quot;1975&quot;&gt;코드트리 바로가기&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1779694615960&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;Codetree: Master Coding Interviews - Data Structures &amp;amp; Algorithms&quot; data-og-description=&quot;Master algorithms, ace tech interviews, and elevate your coding skills with Codetree's systematic curriculum and expert-crafted problem sets.&quot; data-og-host=&quot;www.codetree.ai&quot; data-og-source-url=&quot;https://www.codetree.ai/&quot; data-og-url=&quot;https://www.codetree.ai/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b67OqL/dJMb83kzevE/hLvdzt9rDtZZ5a7u0goVF1/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400,https://scrap.kakaocdn.net/dn/bJyLDf/dJMb9jOs6Rd/KmRHndGCbdPa1TJwodTQz0/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400&quot;&gt;&lt;a href=&quot;https://www.codetree.ai/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.codetree.ai/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b67OqL/dJMb83kzevE/hLvdzt9rDtZZ5a7u0goVF1/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400,https://scrap.kakaocdn.net/dn/bJyLDf/dJMb9jOs6Rd/KmRHndGCbdPa1TJwodTQz0/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400');&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;Codetree: Master Coding Interviews - Data Structures &amp;amp; Algorithms&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Master algorithms, ace tech interviews, and elevate your coding skills with Codetree's systematic curriculum and expert-crafted problem sets.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.codetree.ai&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-end=&quot;2161&quot; data-start=&quot;2014&quot; data-ke-size=&quot;size16&quot;&gt;이번 3주차 학습을 통해 함수는 단순히 문법을 배우는 단원이 아니라, 코드를 더 구조적으로 작성하기 위한 기본 도구라는 것을 느꼈다. 특히 값을 반환하지 않는 함수는 반복되는 출력이나 특정 동작을 정리할 때 유용했고, 문제를 더 깔끔하게 풀 수 있도록 도와주었다.&lt;/p&gt;
&lt;p data-end=&quot;2161&quot; data-start=&quot;2014&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2360&quot; data-start=&quot;2163&quot; data-ke-size=&quot;size16&quot;&gt;아직은 간단한 함수부터 연습하는 단계지만, 이번 레슨을 통해 코드를 역할별로 나누는 습관을 조금씩 들일 수 있었다. 앞으로 더 복잡한 문제를 풀 때도 무작정 코드를 길게 작성하기보다, 필요한 기능을 함수로 분리하면서 풀이 과정을 정리해 보고 싶다. 이번 3주차는 함수 기초를 다시 다지고, 앞으로의 코딩테스트 공부 방향을 잡는 의미 있는 시간이었다  &lt;/p&gt;</description>
      <category>알고리즘 기초</category>
      <category>코드트리</category>
      <category>코딩테스트</category>
      <category>코테공부</category>
      <category>함수</category>
      <author>harchiving</author>
      <guid isPermaLink="true">https://harchiving.tistory.com/28</guid>
      <comments>https://harchiving.tistory.com/28#entry28comment</comments>
      <pubDate>Mon, 25 May 2026 16:37:11 +0900</pubDate>
    </item>
    <item>
      <title>코드트리 코딩테스트 갭체크 후기: 2주차부터 시작한 첫 미션 기록  </title>
      <link>https://harchiving.tistory.com/27</link>
      <description>&lt;p data-end=&quot;246&quot; data-start=&quot;101&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;246&quot; data-start=&quot;101&quot; data-ke-size=&quot;size16&quot;&gt;이번 글은 &lt;b&gt;코드트리 청약챌린지 2주차 미션&lt;/b&gt;으로 작성하는 후기다.&lt;br /&gt;1주차에는 아직 통장 개설 전이라 참여하지 못했고, 이번 2주차가 사실상 나의 첫 미션이었다. 그래서 이번 미션은 본격적으로 문제를 많이 풀기보다, 먼저 내 현재 실력을 점검해 보는 의미가 컸다. 그 과정에서 응시한 것이 바로 &lt;b&gt;갭체크&lt;/b&gt;였다.&lt;/p&gt;
&lt;p data-end=&quot;246&quot; data-start=&quot;101&quot; 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;2322&quot; data-origin-height=&quot;1406&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yKk8b/dJMb990LWNS/wH5nrKsKLQHUN5OKKTzJu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yKk8b/dJMb990LWNS/wH5nrKsKLQHUN5OKKTzJu1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yKk8b/dJMb990LWNS/wH5nrKsKLQHUN5OKKTzJu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyKk8b%2FdJMb990LWNS%2FwH5nrKsKLQHUN5OKKTzJu1%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;702&quot; height=&quot;425&quot; data-origin-width=&quot;2322&quot; data-origin-height=&quot;1406&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;418&quot; data-start=&quot;255&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;418&quot; data-start=&quot;255&quot; data-ke-size=&quot;size16&quot;&gt;갭체크 안내 화면을 처음 확인했을 때는 생각보다 긴장됐다.&lt;br /&gt;평소에도 코딩테스트 공부를 해야 한다는 생각은 하고 있었지만, 막상 내 실력을 진단한다고 하니 실제 시험을 앞둔 것 같은 느낌이 들었다. 그래도 지금 내가 어느 정도 수준인지 알아야 앞으로의 학습 방향도 정할 수 있다고 생각했다.&lt;/p&gt;
&lt;p data-end=&quot;545&quot; data-start=&quot;420&quot; data-ke-size=&quot;size16&quot;&gt;무작정 문제를 많이 푸는 것도 중요하지만, 그보다 먼저 내가 어떤 유형에 강하고 어떤 부분에서 자주 막히는지 파악하는 과정이 필요하다고 느꼈다. 그런 점에서 갭체크는 챌린지를 시작하는 첫 단계로 적당한 미션이었다고 생각했다.&lt;/p&gt;
&lt;p data-end=&quot;545&quot; data-start=&quot;420&quot; 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;2880&quot; data-origin-height=&quot;1450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfG0Xk/dJMcaaZDj8e/FPuSEUuZKdRJFQZQPwtbJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfG0Xk/dJMcaaZDj8e/FPuSEUuZKdRJFQZQPwtbJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfG0Xk/dJMcaaZDj8e/FPuSEUuZKdRJFQZQPwtbJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfG0Xk%2FdJMcaaZDj8e%2FFPuSEUuZKdRJFQZQPwtbJ0%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;761&quot; height=&quot;383&quot; data-origin-width=&quot;2880&quot; data-origin-height=&quot;1450&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;747&quot; data-start=&quot;583&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;747&quot; data-start=&quot;583&quot; data-ke-size=&quot;size16&quot;&gt;갭체크 문제를 풀면서 느낀 점은, 문제 난이도가 단순히 어렵다기보다는 기본기를 정확히 확인하는 방식에 가깝다는 것이었다.&lt;br /&gt;처음에는 익숙한 유형도 있었기 때문에 비교적 차분하게 풀 수 있었다. 하지만 조건을 꼼꼼하게 읽어야 하거나 구현 과정에서 예외를 생각해야 하는 문제에서는 시간이 걸렸다.&lt;/p&gt;
&lt;p data-end=&quot;949&quot; data-start=&quot;749&quot; data-ke-size=&quot;size16&quot;&gt;특히 문제를 읽고 바로 코드를 작성하는 습관이 아직 남아 있다는 점을 느꼈다. 입력 조건, 반복 범위, 예외 상황을 먼저 정리하고 풀이 방향을 잡은 뒤 코드를 작성해야 하는데, 급하게 접근하면 중간에 다시 수정하는 일이 생겼다. 코딩테스트에서는 풀이 아이디어도 중요하지만, 그 아이디어를 실수 없이 코드로 옮기는 능력이 정말 중요하다는 것을 다시 느꼈다  &lt;/p&gt;
&lt;p data-end=&quot;1138&quot; data-start=&quot;951&quot; data-ke-size=&quot;size16&quot;&gt;내가 비교적 안정적으로 풀 수 있었던 부분은 조건문, 반복문, 배열을 활용하는 기본 구현 문제였다. 반대로 조건이 조금 복잡해지거나 여러 경우를 나누어 생각해야 하는 문제에서는 풀이 방향을 정리하는 데 시간이 더 필요했다. 이번 갭체크를 통해 단순히 &amp;ldquo;문제를 맞혔다, 틀렸다&amp;rdquo;가 아니라 내가 어떤 과정에서 막히는지를 확인할 수 있었다.&lt;/p&gt;
&lt;p data-end=&quot;1138&quot; data-start=&quot;951&quot; 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;2094&quot; data-origin-height=&quot;1184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzNrYD/dJMcagleRcT/ASPcrCwbqOmHIEjKHrCvXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzNrYD/dJMcagleRcT/ASPcrCwbqOmHIEjKHrCvXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzNrYD/dJMcagleRcT/ASPcrCwbqOmHIEjKHrCvXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzNrYD%2FdJMcagleRcT%2FASPcrCwbqOmHIEjKHrCvXK%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;637&quot; height=&quot;360&quot; data-origin-width=&quot;2094&quot; data-origin-height=&quot;1184&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;1297&quot; data-start=&quot;1171&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1297&quot; data-start=&quot;1171&quot; data-ke-size=&quot;size16&quot;&gt;결과를 확인하면서 내 강점과 약점을 조금 더 분명하게 알 수 있었다.&lt;br /&gt;강점은 기본 문법과 단순 구현 문제에서는 크게 흔들리지 않는다는 점이었다. 반면 약점은 문제를 차분히 분석하고, 구현 과정에서 실수를 줄이는 부분이었다.&lt;/p&gt;
&lt;p data-end=&quot;1461&quot; data-start=&quot;1299&quot; data-ke-size=&quot;size16&quot;&gt;평소에는 틀린 문제를 보면 단순히 실수라고 생각하고 넘어간 적도 많았다. 하지만 이번 갭체크를 통해 그런 실수도 반복되면 결국 보완해야 할 약점이라는 생각이 들었다. 특히 인덱스 범위, 조건 처리, 예외 케이스처럼 사소해 보이는 부분이 실제 정답 여부를 크게 좌우한다는 점을 다시 확인했다.&lt;/p&gt;
&lt;p data-end=&quot;1646&quot; data-start=&quot;1463&quot; data-ke-size=&quot;size16&quot;&gt;갭체크 이후 추천 학습 경로가 제시된 점도 도움이 됐다. 단순히 결과만 보여주는 것이 아니라, 부족한 부분을 보완하기 위해 어떤 순서로 학습하면 좋을지 안내해 주는 점이 좋았다. 코딩테스트 공부를 하다 보면 어떤 문제부터 풀어야 할지 막막할 때가 있는데, 코드트리는 현재 상태를 기준으로 학습 방향을 잡아준다는 점에서 유용했다.&lt;/p&gt;
&lt;p data-end=&quot;1714&quot; data-start=&quot;1648&quot; data-ke-size=&quot;size16&quot;&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;&lt;a title=&quot;코드트리&quot; href=&quot;https://www.codetree.ai/ko/trail-info&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.codetree.ai/ko/trail-info&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1779114907875&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;코딩 테스트 학습 안내 | 코드트리&quot; data-og-description=&quot;막막한 코딩테스트 준비, 혼자 헤매지 말고 체계적인 코딩 학습과 단계별 가이드로 빠르게 실력을 쌓아 취업에 성공하세요.&quot; data-og-host=&quot;www.codetree.ai&quot; data-og-source-url=&quot;https://www.codetree.ai/ko/trail-info&quot; data-og-url=&quot;https://www.codetree.ai/ko/trail-info&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/uEiUF/dJMb9jOsh0b/tTFUDsYbeRhdk5EK6Ppri1/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400&quot;&gt;&lt;a href=&quot;https://www.codetree.ai/ko/trail-info&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.codetree.ai/ko/trail-info&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/uEiUF/dJMb9jOsh0b/tTFUDsYbeRhdk5EK6Ppri1/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400');&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;코딩 테스트 학습 안내 | 코드트리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;막막한 코딩테스트 준비, 혼자 헤매지 말고 체계적인 코딩 학습과 단계별 가이드로 빠르게 실력을 쌓아 취업에 성공하세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.codetree.ai&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-end=&quot;1995&quot; data-start=&quot;1716&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1995&quot; data-start=&quot;1716&quot; data-ke-size=&quot;size16&quot;&gt;다른 학습 서비스와 비교했을 때 코드트리의 장점은 진단과 학습이 자연스럽게 이어진다는 점이었다. 단순히 문제를 많이 제공하는 데서 끝나는 것이 아니라, 현재 내 실력을 확인하고 그에 맞는 학습 경로를 추천해 주는 흐름이 좋았다. 다만 아쉬운 점도 있었다. 약점 분석이 조금 더 구체적으로 제공되면 더 도움이 될 것 같았다. 예를 들어 개념 이해가 부족한 것인지, 구현 실수가 많은 것인지, 문제 해석에서 시간이 오래 걸리는 것인지까지 나뉘어 보이면 이후 학습 계획을 세우는 데 더 유용할 것 같았다.&lt;/p&gt;
&lt;p data-end=&quot;2142&quot; data-start=&quot;1997&quot; data-ke-size=&quot;size16&quot;&gt;이번 2주차 미션은 나에게 코드트리 청약챌린지를 시작하는 첫 기록이었다. 1주차를 놓친 점은 아쉬웠지만, 오히려 갭체크를 통해 현재 위치를 먼저 확인하고 시작할 수 있었다는 점은 좋았다. 앞으로는 추천 학습 경로를 따라가며 부족한 부분을 하나씩 채워가고 싶다.&lt;/p&gt;
&lt;p data-end=&quot;2308&quot; data-start=&quot;2144&quot; data-ke-size=&quot;size16&quot;&gt;이번 갭체크를 통해 내가 무엇을 잘하고, 무엇을 더 연습해야 하는지 알 수 있었다. 아직 부족한 부분이 많지만, 그만큼 앞으로 채워갈 부분도 분명해졌다고 생각한다. 다음 미션부터는 문제를 푸는 양뿐만 아니라 풀이 과정과 실수한 부분까지 함께 기록하면서 코딩테스트 실력을 조금씩 키워가야겠다  &lt;/p&gt;</description>
      <category>갭체크</category>
      <category>알고리즘공부</category>
      <category>코드트리</category>
      <category>코딩테스트</category>
      <category>코테공부</category>
      <category>코테준비</category>
      <author>harchiving</author>
      <guid isPermaLink="true">https://harchiving.tistory.com/27</guid>
      <comments>https://harchiving.tistory.com/27#entry27comment</comments>
      <pubDate>Mon, 18 May 2026 23:36:26 +0900</pubDate>
    </item>
    <item>
      <title>오픈소스 프로젝트에 첫 기여해보기</title>
      <link>https://harchiving.tistory.com/26</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오픈소스에 기여한다고 하면 상당히 거창하고 어려운 일처럼 보인다. 나도 그렇게 생각했기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에 좋은 기회로 관심 있던 오픈소스 컨트리뷰션 아카데미(OSSCA)에 멘티로 참여하게 되면서 처음으로 오픈소스 문화에 입문하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나처럼 무엇을 기여할지 고민하기 이전에, 어떻게 기여를 시도할 수 있는지조차 어려움을 겪는, &lt;b&gt;정말 아무것도 모르는(!)&lt;/b&gt; 비기너들을 위해 &lt;u&gt;오픈소스 기여 방법&lt;/u&gt;을 소개해보고자 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기여할 프로젝트 고르기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Github에서 기여하고 싶은 오픈소스 프로젝트를 골라야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;오픈소스 기여는 무엇보다 &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;/p&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;blockquote data-ke-style=&quot;style3&quot;&gt;참고할만한 사이트들&lt;br /&gt;&lt;a href=&quot;https://github.com/explore&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/explore&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://github.com/topics/open-source&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/topics/open-source&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://www.codetriage.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.codetriage.com/&lt;/a&gt;&lt;/blockquote&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;b&gt;익숙한 언어나 프레임워크를 사용하고 있는 프로젝트&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;&amp;nbsp;&lt;/p&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;이슈나 PR이 활발하게 일어나는지, 기여를 위한 커뮤니티가 잘 조성되어 있는지&lt;/b&gt; 확인해보길 바란다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예컨대 내가 참여 중인 Yorkie 프로젝트에는 소통창구로 Discord 링크가 README에 적혀져 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;피드백이 빠르고, 잘 관리되며, 새로운 기여자들에게 우호적인 프로젝트를 선택한다면 기여에 보람을 느끼기 좋기 때문이다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;IDE에서 레포지토리를 열어보는 오픈소스 기여 환경을 세팅하기 위해서는 몇가지 절차가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 이 글을 포스팅하게 된 이유이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;fork&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 원본 레포지토리를 fork한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;114&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XaCSW/btsPE22KeGy/tFRrvsTYF2OlVhVdFzekb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XaCSW/btsPE22KeGy/tFRrvsTYF2OlVhVdFzekb0/img.png&quot; data-alt=&quot;fork 버튼은 레포지토리의 우측 상단에서 찾아볼 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XaCSW/btsPE22KeGy/tFRrvsTYF2OlVhVdFzekb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXaCSW%2FbtsPE22KeGy%2FtFRrvsTYF2OlVhVdFzekb0%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;1254&quot; height=&quot;114&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;114&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;fork 버튼은 레포지토리의 우측 상단에서 찾아볼 수 있다.&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;&lt;b&gt;fork는 해당 레포지토리를 자신의 Github에 복제하는 것&lt;/b&gt;이라고 보면 된다. &lt;s&gt;말 그대로 포크로 떠온다고 한다&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 내 깃허브에 있는 레포지토리는 내가 fork한 레포지토리의 복사본이 되고, &lt;b&gt;원본 레포지토리와의 커넥션&lt;/b&gt;을 갖는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 fork를 어떤 레포지토리 안에서 작업할 브랜치를 만드는 것처럼, 레포지토리 자체를 브랜치로 생성하는 것이라고 이해했다.&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;&lt;b&gt;fork를 하는 이유는 무엇일까?&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;내가 열심히 개발한 프로젝트의 레포지토리를 누가 클론해서 코드를 삭제하고 push한 게 반영된다면? 끔찍할 것이다.&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;이를 위해 fork를 하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원본 레포지토리는 권한에 제한을 두어 함부로 망가지지 않게 하고, &lt;b&gt;기여자들은 fork를 통해 자신의 레포지토리에서 작업 후 원본 레포지토리로 PR&lt;/b&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;이것이 fork의 장점이다. 내가 복사한 레포지토리는 원본 레포지토리와 연결되어 있어, 내 레포지토리에서 수정하게 되면 이 변경사항을 원본 레포지토리에 반영해달라고 요청할 수 있고, 원본 레포지토리의 변경사항도 내 레포지토리로 계속 받아올 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;또한, 내 fork한 레포지토리에서 작업을 한다면 아무리 코드를 망가뜨리고 바꿔놓아도 원본 레포지토리에 피해가 가지 않게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;그러니 너무 부담갖지 말고 마음 편하게 작업하자!&lt;/span&gt;&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;758&quot; data-origin-height=&quot;588&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baMd1t/btsPHhEb7F1/khGAXJjLhRM0BgTujvIYf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baMd1t/btsPHhEb7F1/khGAXJjLhRM0BgTujvIYf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baMd1t/btsPHhEb7F1/khGAXJjLhRM0BgTujvIYf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaMd1t%2FbtsPHhEb7F1%2FkhGAXJjLhRM0BgTujvIYf0%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;758&quot; height=&quot;588&quot; data-origin-width=&quot;758&quot; data-origin-height=&quot;588&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fork 버튼을 누르면 위와 같은 화면이 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원본 레포지토리에서 작업 중인 브랜치에서 이어서 작업할 이슈가 있지 않은 이상, 보통은 main 브랜치만 가져오면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Create fork 버튼을 누르면 내 깃허브에 해당 레포지토리가 복사된다.&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;1256&quot; data-origin-height=&quot;484&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgUGJJ/btsPF8gRMIo/dNI0qqLXK0cxEOa94LS8h0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgUGJJ/btsPF8gRMIo/dNI0qqLXK0cxEOa94LS8h0/img.png&quot; data-alt=&quot;내 깃허브에 있는 복사본. Update branch가 필요하다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgUGJJ/btsPF8gRMIo/dNI0qqLXK0cxEOa94LS8h0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgUGJJ%2FbtsPF8gRMIo%2FdNI0qqLXK0cxEOa94LS8h0%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;1256&quot; height=&quot;484&quot; data-origin-width=&quot;1256&quot; data-origin-height=&quot;484&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;내 깃허브에 있는 복사본. Update branch가 필요하다.&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;'codepair'라는 레포지토리를 fork한 뒤, fork한 레포지토리를 내 깃허브에서 본 화면이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 레포지토리를 fork했는지 링크가 걸려 있는 것을 확인할 수 있다.&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;&lt;b&gt;이때 나만 쓰는 이 복사본을 origin이라 하고, 원본 레포지토리를 upstream이라고 한다.&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;예를 들면 위 이미지에 있는 알림 문구에서는 이 브랜치가 upstream보다 2개의 커밋이 뒤처져있다고 알려주고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 Sync fork - Update branch를 통해 origin &lt;b&gt;레포지토리를 계속 갱신(최신화)해주어야 한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;clone&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 fork한 origin 레포지토리를 내 로컬 환경에 깔아주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;clone을 통해 내 컴퓨터의 원하는 곳에 레포지토리를 복제해주면, 자신이 사용하는 IDE 환경에서 코드를 읽고 수정할 수 있게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 fork와 달리, 내 origin 레포지토리를 정말 그대로 사용할 수 있게 가져오는 것이다.&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;내 레포지토리의 우측 상단에 있는 Code 버튼을 누르면 클론을 위한 URL이 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 URL을 복사하여 터미널에 실행해 원하는 곳에 레포지토리를 깔아주면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1754332925761&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git clone https://github.com/내 ID/레포지토리명.git&lt;/code&gt;&lt;/pre&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;/p&gt;
&lt;pre id=&quot;code_1754333395686&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git remote -v&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;를 실행해보면, origin 태그와 함께 방금 clone한 URL이 보일 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1754333558005&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git remote add upstream https://github.com/원본 레포지토리.git&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원본 레포지토리의 URL을 가져와 위 명령어를 실행하여 원본 레포지토리를 추가로 연결하고, 다시 git remote -v를 확인해보면, 아래 사진처럼 보이게 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1106&quot; data-origin-height=&quot;178&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d8vaN6/btsPESMooas/Cn76eygqeHwdCrgeEG8K00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d8vaN6/btsPESMooas/Cn76eygqeHwdCrgeEG8K00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d8vaN6/btsPESMooas/Cn76eygqeHwdCrgeEG8K00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd8vaN6%2FbtsPESMooas%2FCn76eygqeHwdCrgeEG8K00%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;586&quot; height=&quot;94&quot; data-origin-width=&quot;1106&quot; data-origin-height=&quot;178&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 git status 명령을 통해 내가 어디에 있고 어떤 상태인지 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 로컬의 origin 레포지토리에서 브랜치를 생성해 작업하면 된다.&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;이렇게 모든 세팅을 로컬 환경에 완료하면, 다양한 git 명령어를 통해 작업을 진행할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 결국 원격의 원본 레포지토리(upstream), 이를 내 깃허브에 포크한 원격의 복사본 레포지토리(origin), 이를 클론한 로컬 레포지토리로 총 3개의 레포지토리를 다루게 된다고 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 깃허브에서 원본 레포지토리와 포크한 내 레포지토리 간 Sync fork를 해주었듯이, 원격 origin 레포지토리와 이를 클론한 로컬과의 동기화도 마찬가지로 진행해주어야 한다. (git pull origin main)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;README.md와 CONTRIBUTING.md를 읽는 것&lt;/b&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;README.md에는 보통 해당 프로젝트의 간략한 개요와 &lt;b&gt;개발 환경을 구축하는 가이드라인&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CONTRIBUTING.md에는 &lt;b&gt;기여자들을 위한 가이드라인&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음으로는 로컬 환경에서 해당 프로젝트의 코드들을 읽어보면 되는데, 대부분 방대한 파일과 코드 양을 자랑할 것이다(...).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나같은 경우에는 적당한 규모의 프로젝트의 frontend 폴더만 열어서 읽었기 때문에 일단 주요 파일들을 다 읽고 시작했지만(물론 그래도 정말 많다), &lt;u&gt;어렵다면 이슈를 먼저 고르고 그와 관련된 코드들을 찾아가도 된다.&lt;/u&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;사실 &lt;b&gt;오픈소스 기여는 코드 읽기가 7할&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;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트엔드를 예로 들어보면, 가장 먼저 route 파일을 확인해 어떤 라우트들이 있는지 보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 pages 폴더에 있는 페이지 파일명들을 적어두고, 한 파일씩 읽으며 이 페이지가 어떤 페이지인지 이해하고, components 폴더에 있는 컴포넌트 이름들을 적어두고 해당 컴포넌트가 어떤 컴포넌트인지 이해하면서 점점 구조화해나갔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지 내에서 컴포넌트들이 어떻게 쓰이는지 확인하면서 자연스럽게 UI/UX와 관련해 개선할 이슈들을 찾게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나처럼 코드를 먼저 읽어도 되고, 원본 레포지토리의 Issues 탭에 가서 기여가 필요한 목록들을 먼저 살펴보아도 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1902&quot; data-origin-height=&quot;894&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ci6cqe/btsPFg7vLyS/IwM8OvqHnNZYII8nU1j8cK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ci6cqe/btsPFg7vLyS/IwM8OvqHnNZYII8nU1j8cK/img.png&quot; data-alt=&quot;이슈 목록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ci6cqe/btsPFg7vLyS/IwM8OvqHnNZYII8nU1j8cK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fci6cqe%2FbtsPFg7vLyS%2FIwM8OvqHnNZYII8nU1j8cK%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;1902&quot; height=&quot;894&quot; data-origin-width=&quot;1902&quot; data-origin-height=&quot;894&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;Issues 탭에서는 사람들이 해당 프로젝트에 대해 개선이 필요한 점들을 찾아 적어둔 내용들을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bug일 수도 있고, 새로운 기능을 구현하는 것일 수도 있고, 단순한 번역이나 오탈자 수정같은 문서 작업이 필요한 것일 수도 있다.&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;첫 기여는 언제나 떨린다! &lt;s&gt;나만 그런걸까&lt;/s&gt;&lt;/p&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;u&gt;사소하다고 기여를 망설이지 않았으면 좋겠다.&lt;/u&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;이슈마다 달려 있는 라벨을 통해 이슈를 목적에 따라 분류할 수 있으며, 대부분의 오픈소스 프로젝트에 들어가 보면 위에 내가 올려둔 화면처럼 &lt;b&gt;'good first issue'&lt;/b&gt; 라벨을 따로 분류해둔 것을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 오픈소스 기여 비기너들의 기여 독려를 위해 &lt;u&gt;처음 기여해보기 좋은 쉽고 간단한 이슈들을 마련해 둔 라벨&lt;/u&gt;이다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;얼마나 따뜻하고 아름다운 세상인가&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 코드를 읽으며 import한 라이브러리에서 더 이상 지원하지 않는 컴포넌트를 사용하여 코드 취소선이 그어져 있는 것을 보고, 이를 업데이트하는 것을 첫 기여 대상으로 삼았다.&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;내가 찾은 이슈는 Issues 탭을 검토했을 때 존재하지 않는 이슈였기 때문에, 새로운 이슈로 작성해 등록하였다.&lt;/p&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;u&gt;새로운 이슈를 찾는 것도 일종의 기여 활동&lt;/u&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;누군가 올린 이슈를 해결하고 싶다면, 오른쪽 상단의 &lt;b&gt;Assignees를 먼저 확인&lt;/b&gt;해보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이슈 목록에서도 이슈마다 오른쪽 끝에서 Assignees의 프로필을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1296&quot; data-origin-height=&quot;566&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u4jrn/btsPF5YGFlg/RlsiFFKbds1y4NQLYlZzN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u4jrn/btsPF5YGFlg/RlsiFFKbds1y4NQLYlZzN0/img.png&quot; data-alt=&quot;내가 등록한 이슈. 이슈를 등록할 때 생성된 양식에 맞추어 내용을 작성하였다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u4jrn/btsPF5YGFlg/RlsiFFKbds1y4NQLYlZzN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu4jrn%2FbtsPF5YGFlg%2FRlsiFFKbds1y4NQLYlZzN0%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;1296&quot; height=&quot;566&quot; data-origin-width=&quot;1296&quot; data-origin-height=&quot;566&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;Assignees에 누군가 할당되어 있다면, 그 사람이 해당 이슈를 해결하고 있는 &lt;b&gt;담당자&lt;/b&gt;라고 보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 할당된 사람이 없는 이슈에 기여하고 싶다면 &lt;b&gt;해당 이슈에 기여하고 싶다고 comment를 남기면 된다.&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;그럼 기여 활동을 시작하면 된다!&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;그밖에도 만약 이미 할당된 사람이 있는데 오랫동안 작업이 이루어지지 않는 것 같아 이슈를 할당받고 싶거나, 작업하다가 논의할 사항이 생겨도 이 이슈의 comment를 이용하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;로컬 환경의 내 origin 레포지토리에 브랜치를 생성하고, 브랜치에서 작업을 한 뒤 작업 내용을 커밋하고 원격의 origin 레포지토리에 push한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 자동으로 원본 레포지토리인 upstream에 PR이 가능하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;PR&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1238&quot; data-origin-height=&quot;142&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rTmq8/btsPGuDQUmx/XquAKmQtJg4wW6ITN0u6Dk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rTmq8/btsPGuDQUmx/XquAKmQtJg4wW6ITN0u6Dk/img.png&quot; data-alt=&quot;PR 작성하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rTmq8/btsPGuDQUmx/XquAKmQtJg4wW6ITN0u6Dk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrTmq8%2FbtsPGuDQUmx%2FXquAKmQtJg4wW6ITN0u6Dk%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;1238&quot; height=&quot;142&quot; data-origin-width=&quot;1238&quot; data-origin-height=&quot;142&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;PR 작성하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 깃허브로 돌아와 Pull Request을 작성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사진과 같이, 내가 fork해서 만든 나의 origin 레포지토리의 한 브랜치(지금은 main이라 적혀 있지만, 특정 브랜치에서 작업한 경우 해당 브랜치의 이름이 오게 된다)에서 원본 레포지토리의 main으로 pull 요청을 보내게 된다.&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;1270&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QznJl/btsPGmFLpqv/8EUqYyvFPnzvRicFmAPZjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QznJl/btsPGmFLpqv/8EUqYyvFPnzvRicFmAPZjk/img.png&quot; data-alt=&quot;내가 한 첫 기여의 PR&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QznJl/btsPGmFLpqv/8EUqYyvFPnzvRicFmAPZjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQznJl%2FbtsPGmFLpqv%2F8EUqYyvFPnzvRicFmAPZjk%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;1270&quot; height=&quot;768&quot; data-origin-width=&quot;1270&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;내가 한 첫 기여의 PR&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 작성했던 PR이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이슈와 마찬가지로 생성된 작성 양식에 따라 내용을 채워 PR을 올렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이슈나 PR을 작성할 때 포맷이 정해져 있지 않다면 메인테이너와 커미터가 이를 이해할 수 있게끔 자세하게 작성하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이슈 목록에 있는 이슈를 해결하는 PR이라면 &lt;b&gt;자신이 해결한 이슈 번호를 반드시 태깅&lt;/b&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;PR을 올리고 나면 해당 프로젝트에 걸려 있는 CI 파이프라인에 따라 1차 검토가 수행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로는 &lt;u&gt;린트 오류나 빌드 오류가 없는지&lt;/u&gt; 기본적인 코드 품질 검사를 거치게 되는데, 이때 오류가 발생한다면 반드시 다시 커밋을 통해 고쳐야 한다.&lt;/p&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;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 처음 기여하는 프로젝트라면 &lt;b&gt;CLA 사인&lt;/b&gt;을 요청받게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 &lt;u&gt;Contributor License Agreement&lt;/u&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CLA에 서명하고 코드 품질 검사도 통과하면 이제 &lt;b&gt;관리자의 리뷰&lt;/b&gt;만 기다리면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관리자가 우리의 PR을 읽어보고 수정 사항이나 의견을 리뷰로 달아주면, 이를 반영하는 커밋을 거듭한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실수가 많으면 검토 과정에서 리뷰어도, 계속 수정하는 나도 고통받을 수 있다(...). 나의 능력이 허용하는 선에서 &lt;u&gt;최대한 리뷰하기 쉽도록 가독성 좋고, 실수가 없는지 확인한 뒤 신중하게 PR을 올리도록 하자.&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;나도 컨트리뷰터!&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1082&quot; data-origin-height=&quot;730&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eexoB0/btsPIyrIGaw/KoTHKCsHP5VOqVKZYbh4s1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eexoB0/btsPIyrIGaw/KoTHKCsHP5VOqVKZYbh4s1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eexoB0/btsPIyrIGaw/KoTHKCsHP5VOqVKZYbh4s1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeexoB0%2FbtsPIyrIGaw%2FKoTHKCsHP5VOqVKZYbh4s1%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;1082&quot; height=&quot;730&quot; data-origin-width=&quot;1082&quot; data-origin-height=&quot;730&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 검토 작업이 성공적으로 끝나면, 관리자가 이를 &lt;b&gt;approve&lt;/b&gt;하여 원본 레포지토리에 &lt;b&gt;병합&lt;/b&gt;하고 자동으로 PR이 &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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;merge가 완료되었으면 작업이 끝난 내 브랜치는 삭제해도 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PR에 이슈가 연결되어 있었다면, PR과 함께 이슈도 자동으로 함께 닫힌다.&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;&lt;b&gt;메인테이너의 감사 인사와, 오픈소스에 내 코드가 적혀 있는 것, 컨트리뷰터로 내 프로필이 올라가 있는 것&lt;/b&gt;을 보면 오픈소스 기여의 보람과 재미를 비로소 느끼게 될 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;12등.png&quot; data-origin-width=&quot;454&quot; data-origin-height=&quot;228&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVaxri/btsPHI9se0g/2EPDbnE3WfPg6kj7eXfKv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVaxri/btsPHI9se0g/2EPDbnE3WfPg6kj7eXfKv0/img.png&quot; data-alt=&quot;2개의 커밋으로 12등에 랭크된 나...&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVaxri/btsPHI9se0g/2EPDbnE3WfPg6kj7eXfKv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVaxri%2FbtsPHI9se0g%2F2EPDbnE3WfPg6kj7eXfKv0%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;454&quot; height=&quot;228&quot; data-filename=&quot;12등.png&quot; data-origin-width=&quot;454&quot; data-origin-height=&quot;228&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2개의 커밋으로 12등에 랭크된 나...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;컨트리뷰터.png&quot; data-origin-width=&quot;1934&quot; data-origin-height=&quot;734&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cN8wgp/btsPLfAQFE9/oxmyT6jNsKLI7oYZEgrIV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cN8wgp/btsPLfAQFE9/oxmyT6jNsKLI7oYZEgrIV1/img.png&quot; data-alt=&quot;README의 컨트리뷰터 명단에 올라간 내 프로필&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cN8wgp/btsPLfAQFE9/oxmyT6jNsKLI7oYZEgrIV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcN8wgp%2FbtsPLfAQFE9%2FoxmyT6jNsKLI7oYZEgrIV1%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;1934&quot; height=&quot;734&quot; data-filename=&quot;컨트리뷰터.png&quot; data-origin-width=&quot;1934&quot; data-origin-height=&quot;734&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;README의 컨트리뷰터 명단에 올라간 내 프로필&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;오픈소스에 기여해보기 전에는 '내가 감히 어떻게 그런 걸'이라는 생각에 도전하기를 주저했다.&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;&amp;nbsp;&lt;/p&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;p data-ke-size=&quot;size16&quot;&gt;즉 기여하는 루트만 알면 허들이 높지는 않다는 의미이다. &lt;span style=&quot;color: #666666;&quot;&gt;이 글로 이제 루트도 알지 않았는가&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오픈소스에 기여하고자 하는 마음만 있다면,&lt;/b&gt; 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;/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;</description>
      <category>OSS</category>
      <category>contribute</category>
      <category>github</category>
      <category>opensourcesoftware</category>
      <category>oss</category>
      <category>OSSCA</category>
      <category>yorkie</category>
      <category>오픈소스</category>
      <category>오픈소스기여</category>
      <author>harchiving</author>
      <guid isPermaLink="true">https://harchiving.tistory.com/26</guid>
      <comments>https://harchiving.tistory.com/26#entry26comment</comments>
      <pubDate>Tue, 5 Aug 2025 06:37:57 +0900</pubDate>
    </item>
    <item>
      <title>SQLD 제57회 벼락치기 합격 후기와 팁</title>
      <link>https://harchiving.tistory.com/24</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;지난 5월 31일에 있었던 제57회 SQLD, SQL 개발자 자격증을 취득했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개정 이후 가장 어려웠다는 제57회 SQLD를 SQL 활용 파트를 버리고 간단하게 합격한 과정과 몇 가지 팁을 적어보고자 한다.&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-filename=&quot;blob&quot; data-origin-width=&quot;1124&quot; data-origin-height=&quot;671&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yRWUA/btsOSl9IUKA/vFwMF0kPV5m8z9PTahrbNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yRWUA/btsOSl9IUKA/vFwMF0kPV5m8z9PTahrbNk/img.png&quot; data-alt=&quot;턱걸이 합격&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yRWUA/btsOSl9IUKA/vFwMF0kPV5m8z9PTahrbNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyRWUA%2FbtsOSl9IUKA%2FvFwMF0kPV5m8z9PTahrbNk%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; alt=&quot;SQLD 시험결과 확인&quot; loading=&quot;lazy&quot; width=&quot;634&quot; height=&quot;378&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1124&quot; data-origin-height=&quot;671&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;턱걸이 합격&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&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;올해 5월 처음&lt;/b&gt; 공부하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 학기에 데이터베이스 이론 과목을 수강하면서 중간고사와 기말고사 사이에 있는 SQLD 시험 응시를 병행해서 효율을 높이자는 생각이었고, 5월 초 중간고사에서 시험 범위였던 &lt;u&gt;SQLD 1과목 일부를 학습&lt;/u&gt;해둔 뒤, 많은 내용을 잊어버리고(?) 벼락치기로 SQLD를 응시한 뒤에 6월에 있는 기말고사를 응시하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SQLD 1과목 일부라 함은, &lt;u&gt;데이터 모델링의 개념이나 데이터베이스 연산이 뭐가 있는지, 대충 어떤 원리의 연산인지&lt;/u&gt; 정도였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 데이터베이스 수업을 듣는 전공 학부생이라면, 나와 같은 일정으로 SQLD를 따는 것도 추천한다.&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;SQLD는 3일 정도 준비를 하긴 했지만, &lt;s&gt;극효율을 위해 자료 조사한 시간이 훨씬 많았고&lt;/s&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;하지만 찾아보니 SQLD는 &lt;b&gt;요령껏 따는 응시자들이 대부분&lt;/b&gt;이기에(...) 자신의 &lt;u&gt;실력을 보고 판단&lt;/u&gt;하면 될 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시험 개요&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SQLD는 SQL 개발자라는 &lt;u&gt;국가 공인 자격증&lt;/u&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SQL과 관련된 자격증으로 SQLD보다 따기 어려운 SQLP, SQL 전문가 자격증도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SQLD는 이에 비해선 기초 자격증이라고 보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 &lt;b&gt;SQLD의 합격률은 약 50% 내외&lt;/b&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;&lt;b&gt;SQLD 시험은 2024년, 제52회부터 출제 범위와 방식이 바뀌었다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;662&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cubPGH/btsORUKYmmL/2xdatDTDMyKlgLq7XDkkl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cubPGH/btsORUKYmmL/2xdatDTDMyKlgLq7XDkkl1/img.png&quot; data-alt=&quot;출처: 홍쌤의 데이터랩&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cubPGH/btsORUKYmmL/2xdatDTDMyKlgLq7XDkkl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcubPGH%2FbtsORUKYmmL%2F2xdatDTDMyKlgLq7XDkkl1%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; alt=&quot;SQLD 출제 범위&quot; loading=&quot;lazy&quot; width=&quot;647&quot; height=&quot;662&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;662&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;h3 data-ke-size=&quot;size23&quot;&gt;출제 방식&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시험 응시는 &lt;b&gt;90분&lt;/b&gt;이며, &lt;b&gt;개정이 되면서 주관식이 사라지고 50문제 모두 4지선다 객관식&lt;/b&gt;으로 바뀌었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1과목 10문제(20점), 2과목 40문제(80점)로 문항 당 차등 없이 2점씩으로 &lt;u&gt;2과목 배점이 훨씬 크다.&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 &lt;b&gt;1과목 4문제(8점), 2과목 16문제(32점) 이상&lt;/b&gt; 맞히지 못하면 &lt;b&gt;과락으로 탈락&lt;/b&gt;하니 전략을 잘 세워야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과락을 주의하며 100점 만점 중 &lt;b&gt;총점 60점&lt;/b&gt;을 넘기면 합격이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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과목에서 Top N&amp;nbsp; 쿼리나 PIVOT절이 추가되었으며, SQL 최적화 기본 원리 파트가 빠졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;문제는 &lt;b&gt;최근 개정되었다 보니, 최신 자료가 부족했다&lt;/b&gt;는 점인데, 이를 대비한 방법은 아래에서 소개하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;분기별로 1년에 총 4번&lt;/b&gt; 있으며, &lt;b&gt;주말 오전&lt;/b&gt;에 치뤄진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 토요일 오전 10시에 응시하였고, 9시 30분까지 입실하여야 했다.&lt;/p&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;p data-ke-size=&quot;size16&quot;&gt;응시료는 &lt;b&gt;50,000원&lt;/b&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;지참할 것은 &lt;b&gt;컴퓨터용 사인펜과 신분증&lt;/b&gt;, 문제를 풀 때 쓸 펜(샤프)이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시험은 컴퓨터가 아닌 지필로 이루어져 종이 시험지를 보고 별도 OMR 답안지에 마킹하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수험표의 경우 확인하지 않았고 고사실을 찾을 때와 답안지에 적을 때를 위한 &lt;u&gt;내 수험번호만 알면 된다.&lt;/u&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특이사항은 &lt;b&gt;수정액과 수정테이프를 쓸 수 없다.&lt;/b&gt; &lt;s&gt;이런 시험은 처음 봤다&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘못 마킹한 경우 답안지를 교체해야 하며, &lt;b&gt;시험 종료 5분 전에는 교체도 불가&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;시험 도중 화장실을 갈 수 없고, 퇴실은 시험 종료 30분 전부터 가능했던 것 같으나 확실하진 않다.&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;별도 연습지는 제공되지 않아 시험지 여백에 풀면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시험지는 유명한 노랭이 책과 같은 양식으로 출력되어 있었다. (페이지 당 1~2문제)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간이 없던 나의 전략은, 2과목에서 주로 킬러로 많은 문제가 나오는 &lt;b&gt;SQL 활용 파트를 통째로 버리고(!)&lt;/b&gt;, 1과목과 2과목의 쉬운 문제들을 최대한 많이 맞혀서 60점을 넘기자는 것이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 생각하면 말도 안 되는 과감하고 리스크가 큰 전략이긴 하지만... 돌아가도 그럴 것 같다...ㅎ &lt;s&gt;성공했기 때문에&lt;/s&gt;&lt;/p&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. 1과목 이론 공부&amp;amp;자료&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어려운 2과목을 공부할 시간에 먼저 1과목을 제대로 익히고 외워 &lt;u&gt;기본 점수를 얻고 갈 전략&lt;/u&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그 수단으로 유튜브 @홍쌤의 데이터랩에 올라와 있는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://youtu.be/xmkaOqbTQRE?si=gqfkzlNc1rmMHDBW&quot;&gt;[2025 개정] SQLD 1과목 완벽 정리&lt;/a&gt;를&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;쭉 들었다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;개정 전 자료들이 훨씬 많아, 개정 후 이론만 찾아보기 어려웠는데 개정 후 정리 영상이 있어 편하게 자료를 영상으로 보면서 익혔다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자료로는 다양한 자료를 찾았지만, 가장 좋았던 자료는 블로그에 올라온 &lt;b&gt;&lt;a href=&quot;https://bruders.tistory.com/173&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;개정판 개념정리 pdf&lt;/a&gt;&lt;/b&gt; 였다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개정이 된 지 얼마 되지 않았고, 개념서를 따로 구입하지 않았다 보니 개념을 눈으로 보고 익힐 만한 최신 요약본이 필요했는데 이 블로그에 올라온 pdf가 정말 많이 도움이 되었다. 너무 너무 정리를 잘 해주셨다 !&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 pdf를 굿노트에 옮겨서 위의 유튜브 정리 영상을 보며 같이 읽었다.&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;다만, 영상을 보면 아시다시피 짚어주고 넘어가는 식이기 때문에 &lt;b&gt;이론을 아예 모르고 들으면 어려울 수 있을 것&lt;/b&gt; 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;요약본으로도 머리에 잘 들어오지 않는 &lt;/span&gt;경우엔 시간을 더 두고 개념을 공부해야 하는데, 나는 개념을 전공 서적(데이터베이스개론)으로 공부했었으나, 오로지 자격증 취득 목적이라면 차라리 SQLD를 위한 유료 인강 패키지같은 것을 끊어 수강하거나 개념서를 구매해 보는 게 더 효율적일 것 같기는 하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 블로그의 &lt;a href=&quot;https://harchiving.tistory.com/category/Study/DateBase&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;데이터베이스 카테고리&lt;/a&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;대충 영상으로 내용을 훑은 뒤엔 유명한 일명 &lt;b&gt;노랭이&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;기출 문제는 아니고, 예시 문제라고 생각하면 된다.&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;400&quot; data-origin-height=&quot;542&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8Nfth/btsOS8amxBV/VXnKkw0gzgj8m2sGtWzM61/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8Nfth/btsOS8amxBV/VXnKkw0gzgj8m2sGtWzM61/img.jpg&quot; data-alt=&quot;노랭이 개정판&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8Nfth/btsOS8amxBV/VXnKkw0gzgj8m2sGtWzM61/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8Nfth%2FbtsOS8amxBV%2FVXnKkw0gzgj8m2sGtWzM61%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; alt=&quot;SQLD 자격검정 실전문제&quot; loading=&quot;lazy&quot; width=&quot;276&quot; height=&quot;374&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;542&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;확실히 모르는 경우엔 답을 적지 않았고, 빠르게 푼 뒤에 &lt;u&gt;틀린 문제의 해설지를 읽으며&lt;/u&gt; 개념을 읽혔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 요약본 pdf에서 해당 개념 부분을 찾아 읽거나 표시했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 2과목 공부&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 말했다시피 2과목의 핵심인 &lt;u&gt;SQL 활용 부분을 버렸다.&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 먼저 SQL 기본 부분을 요약본과 해당 파트를 설명하는 유튜브 영상 몇 개를 무작위로 보며 익히고, 노랭이를 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;충분히 어려웠고 엄청 많이 틀렸다. (ㅋㅋ) 하지만 노랭이를 풀며 어떤 식으로 풀어야 하는지 감이 왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들면 선지가 엄청 긴 SQL 문제들을 자세히 보면 &lt;u&gt;긴 SQL문에서 딱 하나의 절만 바꾸어 써두었기에&lt;/u&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;b&gt;SQLD 문제는 4지선다이기 때문에 소거법으로 풀어도 된다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SQL 기본 파트를 공부하고 나서는 SQL 활용 파트를 건너뛰고, &lt;b&gt;관리 구문 파트&lt;/b&gt;를 공부했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SQL 기본 파트에서 나오는 데이터베이스 이론과, 관리 구문 파트는 그냥 암기이기 때문에 &lt;u&gt;점수를 주는 문제&lt;/u&gt;다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 이 부분과, 1과목에서 최대한 점수를 따려고 했다.&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;노랭이를 풀다 보면 해설을 봐도 이해가 잘 안 되는 부분들이 있는데, 그 부분들은 네이버 카페인 &lt;b&gt;&lt;a href=&quot;https://cafe.naver.com/sqlpd&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;데이터 전문가 포럼&lt;/a&gt;&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;물론 해소되지 않을 때도 있었지만, 시간이 없었기 때문에 어려우면 굳이 붙잡고 있지 않았다...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 카페는 이 용도 말고도 굉장히 많은 응시자가 활동하기 때문에 기타 정보들을 얻기 유용했으므로 &lt;u&gt;가입을 추천&lt;/u&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;또, 노랭이가 실제 시험 난이도보다 어렵다고 하길래, 너무 어렵거나 어려워 보인다(...) 싶은 몇 문제는 &lt;b&gt;풀지 않고 출제 내용이 무엇인지만 해설지로 확인&lt;/b&gt;했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로, 시험장에서 풀어 보니 &lt;u&gt;시험 문제가 훨씬 쉽게 느껴졌다.&lt;/u&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;시험 개정이 되면서 노랭이도 개정이 되어 문제 번호가 다르거나 바뀐 것들이 있었는데, 그건 카페의 &lt;a href=&quot;https://cafe.naver.com/sqlpd?iframe_url_utf8=%2FArticleRead.nhn%253Fclubid%3D21771779%2526articleid%3D70063&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이 글&lt;/a&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요약본과 노랭이를 대충 훑은 뒤엔, 공부하지 않은 &lt;u&gt;SQL 활용 부분의 요약본을 읽었다.&lt;/u&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;&amp;nbsp;&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;여기까지 한 뒤에는 기출 문제들을 검색해 살펴보았다.&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;a href=&quot;https://yunamom.tistory.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이 사이트&lt;/a&gt;의 52회 이후 복원 글과 아까 말한 카페의 SQLD 관련 카테고리에서 지난 응시자들이 머리를 맞대고 적어둔 복원 글을 참고해 문제와 정답을 시험 날 아침에 벼락치기로 읽다가 시험을 쳤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 도움이 꽤 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&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;p data-ke-size=&quot;size16&quot;&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;1과목은 확실하게 외우지 않으면 풀지 못하기 때문에 헷갈리는 문제들이 많아 고민하다가 시간을 꽤 썼는데, 2과목은 오히려 쉬운 문제를 빠르게 쳐낼 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선지가 보통 4개 중에 2개는 확실히 답이 아니고, &lt;u&gt;2개 중에 헷갈리게 출제&lt;/u&gt;된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 자신의 감(...)을 믿고 &lt;u&gt;한번 끝까지 완주한 뒤에&lt;/u&gt; 못 풀었던 문제를 풀기를 바란다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1과목 같은 경우는 헷갈려도 더 끌리는 선지에 찍고 넘어갔고, 2과목 같은 경우는 어려워 보이거나 복잡한 문제는 그냥 넘기고 풀었다. 어차피 그 문제 못 풀어도, &lt;b&gt;50문제 중에 20문제 틀려도 합격이라는 점을 잊으면 안 된다!&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;p data-ke-size=&quot;size16&quot;&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;1과목과 2과목 기본 문제를 맞히고, 나머지는 잘 찍어서 합격하자는 내 전략은 &lt;b&gt;아무튼 성공&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;확실히 다른 문제는 평이하게 나오고, 1과목의 어려운 문제와 SQL 활용 문제 중 어려운 문제들이 있는데, 이 문제들까지 맞히려면 열심히 공부해야 할 듯 하다.&lt;/p&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 응시자들의 공부 전략을 보면 노랭이를 3회독 이상 하던데, 시간이 된다면 좋은 것 같다.&lt;/p&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;개정 이후 출제 방향&lt;/u&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;개정 이후에 새로 추가된 범위(PIVOT절 등)에 대해 신유형들이 매회차 나오고 있다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공부하지 않아서 모르겠지만... 몇 문제 되지 않아도 2과목 중 반 이상은 맞혀야 합격 선을 넘기기 때문에 전략을 잘 세우는 게 좋겠다. 불합격자들도 한두 문제 차이로 불합격하는 사람들이 많다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;체감상으로는 1과목이 생각보다 어려웠고, 2과목 기본 문제는 상당수의 문제가 생각보다 더 쉽게 나왔다.&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;&lt;b&gt;SQLD 시험이 점점 어려워지고 있다&lt;/b&gt;고 한다. 제57회가 지금까지 중에 가장 어려웠다는 반응들을 보았다.&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주~한 달 공부하면 합격할 듯 하다.&lt;/p&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;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자료의 경우에는 이것저것 모두 찾아보긴 했으나, 도움이 되고 결정적으로 공부할 때 사용한 것은 위에 적은 블로그 pdf와 네이버 카페, 홍쌤 유튜브 영상이 전부였다.&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;덧붙여, &lt;b&gt;서울시에 거주하는 청년&lt;/b&gt;이라면 미취업청년 응시료지원 사업을 통해&lt;u&gt;&lt;b&gt; SQLD 응시료를 환급&lt;/b&gt;&lt;/u&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;</description>
      <category>Review</category>
      <category>DB</category>
      <category>SQL</category>
      <category>SQLD</category>
      <category>SQLD시험</category>
      <category>SQLD합격후기</category>
      <category>데이터베이스</category>
      <author>harchiving</author>
      <guid isPermaLink="true">https://harchiving.tistory.com/24</guid>
      <comments>https://harchiving.tistory.com/24#entry24comment</comments>
      <pubDate>Mon, 21 Jul 2025 17:54:32 +0900</pubDate>
    </item>
    <item>
      <title>[운영체제] 8. 메모리 관리</title>
      <link>https://harchiving.tistory.com/23</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;해당 내용은 공룡책(Operating System Concepts 10th Ed: Abraham Silberschatz, Peter Baer Galvin, Greg Gagne)과 대학 강의를 기반으로 재구성하여 정리한 공부 내용입니다.&lt;br /&gt;+) 6장부터는 사자책(명품 운영체제: 황기태)에 더 중점을 두고 전개됩니다.&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 메모리 계층 구조와 메모리 관리 핵심&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1203&quot; data-origin-height=&quot;778&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NHBiH/btsOrx968xf/X8dkl3OTytgPmWivGEvWH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NHBiH/btsOrx968xf/X8dkl3OTytgPmWivGEvWH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NHBiH/btsOrx968xf/X8dkl3OTytgPmWivGEvWH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNHBiH%2FbtsOrx968xf%2FX8dkl3OTytgPmWivGEvWH0%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;548&quot; height=&quot;354&quot; data-origin-width=&quot;1203&quot; data-origin-height=&quot;778&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리 계층 구조: CPU 레지스터 - 캐시 메모리 - 메인 메모리 - 보조 기억 장치 ...&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인 메모리(RAM): 휘발성, 하드 디스크: 비휘발성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;CPU의 빠른 명령 처리 속도와 메모리 응답 속도의 차이 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; CPU가 명령과 데이터를 가져오는 &lt;b&gt;&lt;u&gt;메모리 액세스 시간을 단축&lt;/u&gt;&lt;/b&gt;시켜야 하는 문제 &lt;u&gt;(메모리 계층 구조의 목적!)&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 메인 메모리보다 빠른 캐시 메모리를 CPU와 메인 메모리 사이에 설치해 사용&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;캐시 메모리: CPU가 현재 실행하는 프로세스 코드와 데이터 중 당장 실행할 일부를 메인 메모리에서 가져다 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일부만 두는 데도 효과적인 이유 &amp;rarr; &lt;b&gt;참조의 지역성 때문&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;1) &lt;b&gt;시간적 지역성(Temporal Locality)&lt;/b&gt;: 한 번 참조된 데이터는 가까운 미래에 다시 참조될 가능성이 높음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) &lt;b&gt;공간적 지역성(Spatial Locality)&lt;/b&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;하드 디스크나 SSD 같이 대용량이면서 값이 싼 보조 기억 장치를 메인 메모리의 연장된 저장 공간으로 활용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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. CPU 레지스터&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU가 현재 실행할 코드와 데이터, 다음에 실행할 몇 개의 코드와 데이터를 미리 저장할 목적&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 8~30개&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레지스터 1개 크기 32비트&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;2. 캐시 메모리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주기억장치로 사용하고 있는 메인 메모리보다 더 빠른 메모리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU의 빠른 처리 속도를 맞추기 위해 도입됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가격이 비싸 소량만 사용됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응답 속도와 위치에 따라 여러 레벨로 나누어 사용 - 현대의 멀티 코어 CPU의 경우 코어별로 L1/L2, 공유하는 L3 캐시를 두는 식&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;3. 메인 메모리&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 보조기억장치&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;&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;1418&quot; data-origin-height=&quot;950&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dFvRD2/btsOsnr4PfM/M1mgOSsirIPyyOs1FuDudK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dFvRD2/btsOsnr4PfM/M1mgOSsirIPyyOs1FuDudK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dFvRD2/btsOsnr4PfM/M1mgOSsirIPyyOs1FuDudK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdFvRD2%2FbtsOsnr4PfM%2FM1mgOSsirIPyyOs1FuDudK%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;688&quot; height=&quot;461&quot; data-origin-width=&quot;1418&quot; data-origin-height=&quot;950&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로그램 실행과 메모리 계층 구조&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1424&quot; data-origin-height=&quot;928&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btg7n0/btsOqLabISw/LqOK3bdRv9kbeLgTGz6DK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btg7n0/btsOqLabISw/LqOK3bdRv9kbeLgTGz6DK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btg7n0/btsOqLabISw/LqOK3bdRv9kbeLgTGz6DK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbtg7n0%2FbtsOqLabISw%2FLqOK3bdRv9kbeLgTGz6DK0%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;642&quot; height=&quot;418&quot; data-origin-width=&quot;1424&quot; data-origin-height=&quot;928&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 운영체제가 보조기억장치에 저장된 실행 파일을 메인 메모리에 적재&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 메인 메모리에 적재된 코드와 데이터 중 실행할 일부 코드와 실행에 필요한 데이터가 L3 캐시로 복사&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. L3 캐시에서 당장 실행할 코드와 데이터 일부가 L1/L2 캐시로 복사&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. CPU 코어가 L1/L2 캐시에서 현재 실행할 명령과 데이터를 레지스터로 읽어 들인 후 연산 실행&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;L1, L2, L3 캐시 모두 컴퓨터 시스템에 따라 존재 유무 다를 수 O&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 캐시 없는 경우 CPU가 메인 메모리로부터 코드와 데이터를 액세스해 명령 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 캐시 있는 경우 CPU가 캐시로부터만 코드와 데이터를 읽고 실행 &amp;rarr; 반드시 실행에 필요한 내용 캐시로 복사되어야 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;메인 메모리 &amp;harr; 캐시&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU가 현재 프로세스나 스레드 실행을 중단하고 다른 프로세스나 스레드 실행 시 L1/L2 캐시에는 새로 실행하고자 하는 프로세스나 스레드의 명령과 데이터를 찾을 수 없는 &lt;u&gt;캐시 미스(cache miss)&lt;/u&gt; 발생 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;rarr;&lt;span&gt; 연쇄적으로 메인 메모리로부터 L3 캐시, L1/L2 캐시로 새 프로세스 코드와 데이터 이동. 그전에 현재 캐시에 들어 있는 데이터 중 수정된 데이터는 L3 캐시나 메인 메모리에 기록돼야 함&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;rarr;&lt;span&gt; 캐시로 인해 프로세스나 스레드의 컨텍스트 스위칭이 코드와 데이터를 이동시키는 보이지 않는 오버헤드 초래&lt;/span&gt;&lt;/span&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;캐시 미스는 프로그램 실행 중에도 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;메인 메모리&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;harr; 보조기억장치&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인 메모리 전체가 사용 중이거나 빈 영역이 일정 이하로 줄어들면 메인 메모리에 적재된 코드나 데이터 일부를 하드디스크나 SSD에 저장해 공간을 확보하는 기법 &amp;rarr; 가상 메모리&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;메모리 계층화가 효율적인 이유: 참조의 지역성(locality of reference)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 코드나 데이터, 자원 등이 아주 짧은 시간 내에 다시 사용되는 프로그램의 특성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 빠른 캐시를 사용해 얻는 이득 &amp;gt; 캐시를 다시 채우기 위해 CPU가 대기하는 실&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;base 레지스터와 limit 레지스터를 사용하여 보호 기법 제공&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;base 레지스터는 가장 작은 물리 메모리 주소 값을 저장하고, limit 레지스터는 주어진 영역의 크기를 저장한다.&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;CPU는 사용자 모드에서 만들어진 모든 주소와 레지스터를 비교하여 다른 사용자 프로그램 또는 운영체제의 메모리 공간에 접근하면 트랩을 발생시킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주소가 base보다 크거나 같은지, base+limit보다 작은지 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;1. 여러 프로세스에 의해 사용되는 공유 자원으로, 프로세스가 임의의 메모리 영역을 사용하게 할 수 없기 때문 - 메모리 할당 관리 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 메모리를 &lt;b&gt;보호&lt;/b&gt;하기 위함. - 사용 중인 메모리에 대해 프로세스 접근 제어 및 사용자 모드에서 커널 공간 접근 제어 위한 보호 기능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 메모리의 &lt;b&gt;용량 한계를 극복&lt;/b&gt;하기 위함. - 메모리의 물리적 크기 한계를 극복하는 가상 메모리 같은 메모리 관리 정책 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 메모리 사용 &lt;b&gt;효율&lt;/b&gt;을 높이기 위함. - 다중프로그래밍정도(DOM);운영체제가 메모리에 동시 적재하여 실행시키는 프로세스 개수 = 운영체제 메모리 관리 효율성을 나타내는 지표. 메모리 용량 대비 많은 프로세스를 실행시켜 시스템 처리율을 높여야 함&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; 기본적인 메모리 관리 기능: 할당과 보호 - 프로세스에 메모리 배분, 자신 영역 외 침범하거나 훼손하지 못하게 제어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;1. 물리 주소: 실제 메모리 주소(하드웨어 주소); address bus에 연결됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 논리/가상 주소: 프로그램 내에서 사용되는 주소; 코드나 데이터(변수나 동적 할당 메모리)의 주소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU가 프로세스 실행 동안 다루는 모든 주소는 논리 주소이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커널도 논리 주소로 이루어져 커널 코드가 실행될 때에도 논리 주소가 물리 주소로 바뀌어야 한다.&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;1280&quot; data-origin-height=&quot;809&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1NeEC/btsOtsfypsw/ZmVsvDrpM5YMRdkkJwcRi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1NeEC/btsOtsfypsw/ZmVsvDrpM5YMRdkkJwcRi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1NeEC/btsOtsfypsw/ZmVsvDrpM5YMRdkkJwcRi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1NeEC%2FbtsOtsfypsw%2FZmVsvDrpM5YMRdkkJwcRi0%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;610&quot; height=&quot;386&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;809&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;(위 그림처럼) CPU가 논리 주소를 사용해 물리 메모리에 데이터를 저장하고자 하면, 이 명령을 실행하기 위해 논리 주소 4번지를 발생 &amp;rarr; 주소 변환 하드웨어(MMU)에 의해 물리 주소로 변환 &amp;rarr; 주소가 CPU 패키지 바깥으로 빠져 나가 물리 메모리에 전달&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;주소 변환 하드웨어 &lt;b&gt;MMU&lt;/b&gt;(Memory Management Unit): 프로세스의 논리 주소와 물리 주소의 매핑 정보를 담은 &lt;u&gt;매핑 테이블&lt;/u&gt;을 참고하여 논리 주소를 물리 주소로 변환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리 관리 방식에 따라 다르게 구현되며, CPU 패키지 내에 구성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매핑 테이블과 MMU 덕분에 컴파일러는 프로그램을 논리 주소로 컴파일하는 데 부담이 없고, 운영체제도 프로세스의 코드와 데이터를 물리 메모리 빈 곳 아무데나 할당하고 적재해도 되며, 프로그램 개발자도 응용프로그램이 어디에 적재될지 몰라도 된다.(알 수도 없다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;각 루틴(함수)이 실제 호출되기 전까지는 메모리에 올라오지 않고 재배치 가능한 상태로 디스크에 대기&lt;/b&gt;하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리에 있는 루틴이 다른 루틴을 호출하면 호출된 루틴이 메모리에 적재되어 있는지 조사하고, 안 되어 있다면 relocatable linking loader가 불려 요구된 루틴을 메모리에 가져온 뒤 변화를 테이블에 기록한다.&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; 오류 처리 루틴처럼 빈도가 낮은데 &lt;b&gt;실행할 코드가 많은 경우에 유용&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;&amp;nbsp;&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;Static linking의 경우: 시스템 라이브러리와 사용자 코드가 로더에 의해 실행 파일 이미지 내에 통합&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dynamic linking의 경우: 코드와 라이브러리가 분리되어 있어 필요 시 로드됨&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;동적 링킹은 주로 시스템 라이브러리에 사용되어 메모리 낭비를 줄인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 공유된 시스템 라이브러리를 참조, 즉 이러한 라이브러리를 여러 프로세스 간에 공유할 수 있게 하여 패치나 보안 업데이트 적용도 용이하다. &amp;rarr; 버전 관리 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;&lt;b&gt;스텁(stub)&lt;/b&gt;: 프로그램이 실행될 때 동적 라이브러리에 있는 함수 호출을 처리하기 위해 사용되는 코드 조각&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주로 &lt;b&gt;PLT(Procedure Linkage Table)&lt;/b&gt;에 위치&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PLT는 각 외부 함수 호출을 위한 stub 코드들의 집합이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;함수의 첫번째 호출 시 동적 링커에 의해 실제 함수 주소를 찾아 GOT(Global Offset Table)에 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 호출 시에는 GOT에 저장된 실제 주소로 점프&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;동적 링커는 실행 파일이 로드될 때 NEEDED 정보를 참고해 필요한 라이브러리들을 메모리에 로드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로드 과정에서 라이브러리 내의 함수와 변수 심볼을 실행 파일의 심볼 테이블과 매칭함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;MMU(memory management unit)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;논리 주소를 물리 주소로 바꾸어 주는 하드웨어 장치&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;base 레지스터 = relocation 레지스터&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동적으로 논리 주소에 재배치 레지스터 값을 더해 주소를 변환&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1602&quot; data-origin-height=&quot;838&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m0UP6/btsOtFlqwdK/kLUbJCdd45yyLWMXOxD7k0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m0UP6/btsOtFlqwdK/kLUbJCdd45yyLWMXOxD7k0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m0UP6/btsOtFlqwdK/kLUbJCdd45yyLWMXOxD7k0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm0UP6%2FbtsOtFlqwdK%2FkLUbJCdd45yyLWMXOxD7k0%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;570&quot; height=&quot;298&quot; data-origin-width=&quot;1602&quot; data-origin-height=&quot;838&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&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;span style=&quot;color: #333333; text-align: start;&quot;&gt;1) 프로세스의 코드와 데이터를 적재하기 위한 공간 할당 2) 프로세스 실행 중 동적으로 스택이나 힙을 사용할 때 필요한 공간 할당&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;rarr;&lt;span&gt; 전적으로 운영체제 커널에 의해 수행됨&lt;/span&gt;&lt;/span&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;&lt;b&gt;명령어와 데이터를 메모리 주소로 주소 바인딩하는 것은 3개의 다른 단계에 발생할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Compile time: absoute code 생성 (메모리 위치가 바뀌면 재컴파일되어야 한다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Load time: relocatable code 생성&lt;span&gt;&amp;nbsp;&lt;/span&gt;(프로그램이 메모리에 적재될 때 실제 메모리 주소가 할당된다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Execution time: 실행 시간까지 바인딩을 지연. 주소 맵을 위한 하드웨어 지원이 필요하다.&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; 컴파일러와 링커에 의해 매겨진 주소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행 타임 바인딩 &amp;rarr; 가상 메모리 시스템으로, 운영체제가 메모리 보호 및 접근 제어를 담당&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;논리 주소와 물리 주소 분리 효과&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 논리 주소 공간을 물리 주소 공간보다 크게 설정 가능:&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;2. 동적 메모리 할당 시 효율성:&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;3. 프로그램의 독립성:&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;운영체제의 메모리 할당 기법&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1322&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bA3ELc/btsOrUSamHc/l61mT3LsMK0XQWRqbHC4q1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bA3ELc/btsOrUSamHc/l61mT3LsMK0XQWRqbHC4q1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bA3ELc/btsOrUSamHc/l61mT3LsMK0XQWRqbHC4q1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbA3ELc%2FbtsOrUSamHc%2Fl61mT3LsMK0XQWRqbHC4q1%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;690&quot; height=&quot;235&quot; data-origin-width=&quot;1322&quot; data-origin-height=&quot;450&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;연속 메모리 할당&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1902&quot; data-origin-height=&quot;1162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Tl4AS/btsOtpXstP7/FUYBQpdv0ih6kEkRSDVP7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Tl4AS/btsOtpXstP7/FUYBQpdv0ih6kEkRSDVP7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Tl4AS/btsOtpXstP7/FUYBQpdv0ih6kEkRSDVP7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTl4AS%2FbtsOtpXstP7%2FFUYBQpdv0ih6kEkRSDVP7k%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;740&quot; height=&quot;452&quot; data-origin-width=&quot;1902&quot; data-origin-height=&quot;1162&quot;/&gt;&lt;/span&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;연속 메모리 할당(contiguous memory allocation): 각 프로세스에게 메모리 한 덩어리씩 할당하는 기법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 프로세스가 할당받은 메모리가 한 덩어리로 연속된 공간임을 의미함&lt;/p&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) 고정 크기 할당(fixed size partition allocation)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 메모리 전체를 &lt;b&gt;파티션&lt;/b&gt;으로 불리는 고정 크기로 나누고, 프로세스마다 1개의 파티션을 할당하는 기법&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1436&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vYKel/btsOrt8rmZV/yLLOnIFUdz2mHUTUM4RzxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vYKel/btsOrt8rmZV/yLLOnIFUdz2mHUTUM4RzxK/img.png&quot; data-alt=&quot;고정 크기 할당을 사용한 대표 사례: IBM OS/360 MFT 운영체제&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vYKel/btsOrt8rmZV/yLLOnIFUdz2mHUTUM4RzxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvYKel%2FbtsOrt8rmZV%2FyLLOnIFUdz2mHUTUM4RzxK%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;687&quot; height=&quot;111&quot; data-origin-width=&quot;1436&quot; data-origin-height=&quot;232&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;고정 크기 할당을 사용한 대표 사례: IBM OS/360 MFT 운영체제&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;메모리 전체를 n개의 동일한 크기의 파티션으로 분할해두고, 프로세스를 실행시킬 때 각 프로세스에게 1개의 파티션을 할당함&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;동시에 실행시킬 수 있는 프로세스 개수는 n개로 제한, 새로운 프로세스가 도착하면 작업 큐에서 대기해야 한다.&lt;/span&gt;&lt;/span&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;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;프로세스가 파티션 크기보다 작은 경우 메모리 일부가 낭비되는 문제(=&lt;b&gt;내부 단편화&lt;/b&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;파티션 크기보다 큰 프로세스는 처음부터 실행될 수 없는 문제&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;rarr;&lt;span&gt; 시스템 운영자가 실행시킬 전체 응용프로그램들의 크기를 사전에 계산하여 파티션 크기를 정하는 방식으로 해결&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;(당시에 실행시킬 응용프로그램이 정해져 있었기에 가능한 방법이다.)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2) 가변 크기 할당(variable size partition allocation)&lt;/h3&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;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;1454&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pVVuI/btsOsnfc8Nd/NzKK7xUVdOjJ6HDbNGCGb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pVVuI/btsOsnfc8Nd/NzKK7xUVdOjJ6HDbNGCGb1/img.png&quot; data-alt=&quot;가변 크기 할당을 사용한 대표 사례: IBM OS/360 MVT 운영체제&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pVVuI/btsOsnfc8Nd/NzKK7xUVdOjJ6HDbNGCGb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpVVuI%2FbtsOsnfc8Nd%2FNzKK7xUVdOjJ6HDbNGCGb1%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;648&quot; height=&quot;98&quot; data-origin-width=&quot;1454&quot; data-origin-height=&quot;220&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가변 크기 할당을 사용한 대표 사례: IBM OS/360 MVT 운영체제&lt;/figcaption&gt;
&lt;/figure&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;프로세스가 도착했을 때 가용 메모리가 부족 &amp;rarr; 실행 중인 프로세스가 종료되어 필요한 만큼 가용 공간이 생길 때까지 작업 큐에서 대기한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단편화(fragmentation)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단편화: 프로세스에게 할당할 수 없는 작은 크기의 조각 메모리(hole)들이 생기는 현상&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위치에 따라 내부 단편화, 외부 단편화로 분류&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 메모리 정책을 사용해도 단편화는 발생 &amp;rarr; 단편화로 인한 메모리 낭비를 줄이는 메모리 할당 정책 강구&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;내부 단편화&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1550&quot; data-origin-height=&quot;296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c79lVj/btsOtJaiP5C/kKOHaSnLaGjughl7Mfpo11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c79lVj/btsOtJaiP5C/kKOHaSnLaGjughl7Mfpo11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c79lVj/btsOtJaiP5C/kKOHaSnLaGjughl7Mfpo11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc79lVj%2FbtsOtJaiP5C%2FkKOHaSnLaGjughl7Mfpo11%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;634&quot; height=&quot;121&quot; data-origin-width=&quot;1550&quot; data-origin-height=&quot;296&quot;/&gt;&lt;/span&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;고정 크기 파티션에서 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스 크기와 파티션 크기의 차이만큼 내부에 홀이 발생 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;rarr;&lt;span&gt; 다른 프로세스에게 할당할 수 없는 낭비 메모리임&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;외부 단편화&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1980&quot; data-origin-height=&quot;306&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpvPNr/btsOsD3bXbd/EoTnjKKoASTnJC1FmjDKPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpvPNr/btsOsD3bXbd/EoTnjKKoASTnJC1FmjDKPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpvPNr/btsOsD3bXbd/EoTnjKKoASTnJC1FmjDKPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpvPNr%2FbtsOsD3bXbd%2FEoTnjKKoASTnJC1FmjDKPk%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;647&quot; height=&quot;100&quot; data-origin-width=&quot;1980&quot; data-origin-height=&quot;306&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;할당된 메모리들 사이에 활용할 수 없는 홀이 생기는 경우&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;가변 크기 파티션에서 발생&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;외부 단편화로 인해 할당할 메모리가 부족해지면 파티션을 이동시켜 홀을 없애는 메모리 압축(memory compaction) 기법을 사용할 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;연속 메모리 할당 구현&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;하드웨어 지원&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;하드웨어적 구현이 필요한 부분:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;1) 프로세스 실행 중 논리 주소를 물리 주소로 변환하는 기능&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;2) 프로세스가 다른 프로세스의 메모리 액세스를 금지하는 기능&lt;/span&gt;&lt;/span&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;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;구현을 위해 필요한 CPU 레지스터 및 장치:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;- base 레지스터: 현재 실행 중인 프로세스에게 할당된 물리 메모리 시작 주소&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;- limit 레지스터: 현재 실행 중인 프로세스에게 할당된 메모리 크기&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;- 주소 레지스터: 현재 액세스하는 메모리의 논리 주소&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;- 주소 변환 하드웨어(MMU): CPU에서 나오는 논리 주소를 물리 주소로 변환하는 장치&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1526&quot; data-origin-height=&quot;668&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xQQaj/btsOsFs8oJx/E0LdFm0pR2KBTJkcnCkyhK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xQQaj/btsOsFs8oJx/E0LdFm0pR2KBTJkcnCkyhK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xQQaj/btsOsFs8oJx/E0LdFm0pR2KBTJkcnCkyhK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxQQaj%2FbtsOsFs8oJx%2FE0LdFm0pR2KBTJkcnCkyhK%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;762&quot; height=&quot;334&quot; data-origin-width=&quot;1526&quot; data-origin-height=&quot;668&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령 레지스터에 있는 명령을 실행하기 위해 논리 주소 300이 물리 주소로 변환되어야 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;rarr;&lt;span&gt;&lt;span&gt; CPU가 주소 레지스터에 담긴 논리 주소 300 출력&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;rarr;&lt;span&gt;&lt;span&gt; MMU가 &lt;u&gt;논리 주소를 limit 레지스터의 값과 비교&lt;/u&gt;해 할당된 메모리 범위 내인지 체크함(다른 프로세스 &lt;b&gt;메모리 보호&lt;/b&gt; 위함) &amp;rarr;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt; 범위를 넘어서면 &lt;u&gt;시스템 오류 신호를 발생&lt;/u&gt;시켜 CPU가 오류를 처리하는 커널 코드를 실행하고 현재 프로세스를 강제 중단 / 정상 범위이면 MMU가 &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;'base 레지스터에 저장된 물리 주소 1000 + 주소 레지스터에 담긴 논리 주소 300 = &lt;u&gt;물리 주소 1300 &lt;/u&gt;생성하여 CPU 패키지 바깥으로 내보냄 &amp;rarr;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt; 물리 주소 1300이 주소 버스를 타고 메모리에 전달 &amp;rarr;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt; 메모리는 1300번지에 저장된 데이터를 데이터 버스에 내놓음 &amp;rarr;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt; CPU가 이 값을 CPU 내부로 전달&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;운영체제 지원&lt;/h4&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;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt; 새 프로세스를 스케줄링하여 실행시킬 때마다 물리 메모리의 시작 주소와 크기 정보를 CPU 내부 base, limit 레지스터에 적재&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;홀 선택 알고리즘&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hole selection algorithm = 동적 메모리 할당(dynamic memory allocation); 운영체제가 프로세스를 처음 실행시키거나 프로세스의 실행 도중 메모리가 요구될 때 적당한 홀을 선택해서 할당해야 한다.&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;고정 크기 할당 시: 홀들을 가용 메모리 리스트로 만들어 관리하고, 이중 하나를 선택하면 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가변 크기 할당 시: 메모리 전체에 있는 홀마다 &lt;u&gt;시작 주소와 크기&lt;/u&gt; 정보를 구성하고, 이들을 홀 리스트(또는 가용 메모리 리스트)로 만들어 관리해야 함. 그리고 메모리 할당 요청이 발생하면 홀 리스트에서 적절한 홀을 선택해야 함. &amp;rarr;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;u&gt; 어떤 홀을 선택하느냐&lt;/u&gt;에 따라 성능이 상이하여 선택이 중요!&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&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;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;1. first-fit(최초 적합)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;홀 리스트를 검색하여 처음으로 만나는, 요청 크기보다 큰(수용 가능한) 홀 선택&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;good: 알고리즘 속도는 빠름&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;bad: 외부 단편화로 인한 메모리 낭비 큼&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&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;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;2. best-fit(최적 적합)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;홀 리스트를 검색하여 요청 크기를 수용하는 것 중 가장 작은 홀을 선택&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;good: 메모리 낭비 적음&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;bad: 홀 리스트가 크기별로 정렬되어 있지 않은 경우, 홀을 전부 검색해야 하는 부담이 존재&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&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;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;3. worst-fit(최악 적합)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;홀 리스트를 검색하여 요청 크기를 수용하는 것 중 가장 큰 홀을 선택&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;bad: 홀 리스트가 크기별로 정렬되어 있지 않은 경우, 홀을 전부 검색해야 하는 부담이 존재&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;잘 사용하지 않음!&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&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;1218&quot; data-origin-height=&quot;434&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xzuON/btsOtGzfqXv/4yHHWnhEeBmbpk7xFw1P60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xzuON/btsOtGzfqXv/4yHHWnhEeBmbpk7xFw1P60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xzuON/btsOtGzfqXv/4yHHWnhEeBmbpk7xFw1P60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxzuON%2FbtsOtGzfqXv%2F4yHHWnhEeBmbpk7xFw1P60%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;666&quot; height=&quot;237&quot; data-origin-width=&quot;1218&quot; data-origin-height=&quot;434&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;연속 메모리 할당의 장단점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;good:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리 할당 알고리즘이 단순하여 구현이 용이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;논리 주소를 물리 주소로 바꾸는 과정이 단순하여 CPU의 메모리 액세스 속도가 상대적으로 빠름(시작 위치, 크기 정보만 관리하면 됨)&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;bad:&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;프로세스에게 하나의 연속된 메모리를 할당하여 메모리 할당의 유연성이 부족하다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;메모리 전체에 비어 있는 작은 공간(홀)들을 합하면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;u&gt;충분한 공간이 있음&lt;/u&gt;에도 불구하고, 프로세스를 적재할 만큼은 연속된 메모리가 없어 프로세스를 적재할 수 없는 경우가 발생한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&amp;rarr; 분할 메모리 할당 기법으로 해결&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 홀들을 한쪽으로 모아 큰 빈 메모리 공간을 만드는 메모리 압축 과정이 필요&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;처음부터 프로세스에게 필요한 메모리를 예측하여 큰 메모리를 할당한다면 내부 단편화를 초래하는 메모리 낭비가 생길 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;분할 메모리 할당&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1736&quot; data-origin-height=&quot;1050&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czbx2I/btsOts0Xc7i/EWJeXezKAMUSwBPs16pYek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czbx2I/btsOts0Xc7i/EWJeXezKAMUSwBPs16pYek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czbx2I/btsOts0Xc7i/EWJeXezKAMUSwBPs16pYek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fczbx2I%2FbtsOts0Xc7i%2FEWJeXezKAMUSwBPs16pYek%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;711&quot; height=&quot;430&quot; data-origin-width=&quot;1736&quot; data-origin-height=&quot;1050&quot;/&gt;&lt;/span&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;분할 메모리 할당(non-contiguous memory allocation): 프로세스에게 필요한 메모리를 여러 덩어리로 나누어 분산 할당하는 기법&lt;/p&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) 가변 크기 할당 - 세그먼테이션(segmentation)&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 각 덩어리가 세그먼트(segment)이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;세그먼트: 프로세스 내에서 하나의 단위로 다룰 수 있는 의미 있는 블록(논리 블록) &lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;ex. 함수, 객체&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&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;프로세스를 구성하는 세그먼트들을 물리 메모리에 분산 할당(주로 코드, 데이터, 스택, 힙 4개 세그먼트로 분할)&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;p data-ke-size=&quot;size16&quot;&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;컴파일러와 링커, 로더의 도움이 필요&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;논리 세그먼트와 물리 세그먼트의 매핑&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1524&quot; data-origin-height=&quot;1226&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0wb38/btsOuDVH78S/SDbnZgAdNfhV7r8jtUMEKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0wb38/btsOuDVH78S/SDbnZgAdNfhV7r8jtUMEKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0wb38/btsOuDVH78S/SDbnZgAdNfhV7r8jtUMEKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0wb38%2FbtsOuDVH78S%2FSDbnZgAdNfhV7r8jtUMEKK%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;502&quot; height=&quot;404&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1524&quot; data-origin-height=&quot;1226&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;세그먼트 테이블은 &lt;b&gt;시스템 전체에 1개!&lt;/b&gt; 프로세스 당 세그먼트 개수가 작기 때문&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 적재한 모든 프로세스들의 세그먼트들을 관리 &amp;rarr; 논리 세그먼트 당 하나의 항목이 저장됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목은 논리 세그먼트가 적재된 세그먼트의 시작 물리 주소(base)와 세그먼트의 크기(limit)로 구성&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; 외부 단편화 초래&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 프로세스 실행 시 프로세스의 각 세그먼트를 적재할 빈 홀을 찾기 위해 홀 선택 알고리즘을 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;세그먼테이션의 구현&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&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;- CPU: CPU에 의해 발생되는 논리주소는 [세그먼트 번호, 옵셋] 형태. CPU에 세그먼트 테이블의 시작 주소를 가리키는 레지스터 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- MMU: 메모리 보호(논리 주소가 세그먼트 크기를 넘어서는지 판별)와 주소 변환(논리 주소를 물리 주소로 바꿈) 구현&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1172&quot; data-origin-height=&quot;856&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0rUwD/btsOs1w5XFB/mfeNORICxNE3nsHegnPvl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0rUwD/btsOs1w5XFB/mfeNORICxNE3nsHegnPvl1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0rUwD/btsOs1w5XFB/mfeNORICxNE3nsHegnPvl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0rUwD%2FbtsOs1w5XFB%2FmfeNORICxNE3nsHegnPvl1%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;570&quot; height=&quot;423&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1172&quot; data-origin-height=&quot;856&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU에서 논리 주소 발생 &amp;rarr; 메모리에 저장된 세그먼트 테이블에서 세그먼트 번호에 해당하는 항목이 일단 읽힘 &amp;rarr; 이 항목의 limit값과 논리 주소의 옵셋을 비교 &amp;rarr; offset이 limit보다 크면 논리 주소가 세그먼트의 영역을 벗어난 것이므로 시스템 오류 발생 / offset이 limit보다 작으면 세그먼트 테이블의 항목에 들어 있는 물리 세그먼트 시작 주소 + 옵셋 = 물리 주소 출력&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;- 세그먼트 테이블: 세그먼트 테이블을 메모리에 두면 CPU가 논리 주소를 발생시켜 메모리를 액세스할 때마다 현재 세그먼트(s)의 limit과 base 값을 알아내기 위해 메모리에 있는 세그먼트 테이블 항목을 읽어와야 해서 실행 속도에 큰 부담이 됨. &amp;rarr; 주소 변환 속도를 위해 세그먼트 테이블 일부를 MMU 내에 두기도 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;프로세스 생성마다 논리 세그먼트를 적재할 물리 세그먼트를 홀 리스트에서 찾아 할당하고, 프로세스가 종료할 때마다 할당된 물리 세그먼트를 반환하는 기능을 가져야 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;실행 파일에 만들어진 논리 세그먼트들을 인지하고, 이들을 물리 메모리의 빈 영역을 할당받아 적재하여 세그먼트 테이블을 갱신함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;단편화 문제&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스에 가변 크기로 물리 세그먼트들을 할당&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;논리 세그먼트와 동일한 크기의 물리 세그먼트를 할당 &amp;rarr; &lt;u&gt;내부 단편화는 없음&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;But 세그먼트마다 크기가 서로 달라, 세그먼트들 사이에 빈 공간이 있을 때 크기가 작아 새 프로세스에 할당하지 못하는 메모리 낭비가 발생할 수 있다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;rarr;&lt;b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;외부 단편화 문제&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;페이징 기법 도입&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2) 고정 크기 할당 - 페이징(paging)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 프로세스에게 동일한 크기의 덩어리를 여러 개 할당하는 기법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스를 논리적인 단위로 분할하지 않고, 논리 주소 0번지부터 &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;u&gt;프로세스의 각 페이지를 물리 메모리의 프레임에 하나씩&lt;/u&gt; 분산 할당한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;페이징 메모리 관리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 프로세스의 주소 공간을 0번지부터 페이지로 불리는 고정 크기로 나누고, 물리 메모리도 동일한 크기로 0번지부터 분할하여, 프로세스의 각 페이지를 물리 메모리의 임의의 페이지에 분산 할당하는 메모리 관리 기법&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;물리 메모리에서 페이지 크기의 메모리 블록을 프레임(=페이지 프레임, 물리 페이지)이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대부분 4KB로 설정&lt;/b&gt;된다.(8, 16KB도 존재)&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;- 페이지 테이블의 각 항목(PTE, Page Table Entry)에는&amp;nbsp; 페이지 프레임 번호(물리 메모리에서 해당 페이지의 위치) 기록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;u&gt;프로세스마다 페이지와 물리 프레임을 매핑하는 페이지 테이블 존재&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- MMU 장치가 페이지 테이블을 이용해 &lt;u&gt;논리 주소를 물리 주소로 변환&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;장점&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 구현이 쉽다. 고정 크기 페이지로 분할하여 이해도 더 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 이식성이 높다. CPU에 의존적이지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 융통성이 높다. 시스템에 따라 페이지 크기를 변경할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 세그먼테이션에서 발생하는 외부 단편화 존재X, 홀 선택 알고리즘 실행할 필요X &amp;rarr; 메모리 활용, 시간 오버헤드 면에서 우수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;내부 단편화가 발생하기는 함&lt;/u&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;세그먼테이션과 페이징 기법은 서로 장단점이 있어 현대 컴퓨터 시스템에서는 페이징을 기반으로 세그먼테이션을 혼합 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;페이지 테이블&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;char *p = (char*)malloc(200); 을 실행한 경우:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스 힙 영역에 페이지 5를 할당하고, 비어 있는 물리 프레임 2를 할당하여 프로세스 페이지 테이블 항목 5에 프레임 번호 2를 기록한다. 그리고 페이지 5의 앞 200바이트를 할당해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;malloc(200) 함수는 페이지 번호 5의 논리 주소인 20480을 리턴하여 포인터 변수 p에는 20480이 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지 5의 시작 주소는 5*4KB = 20KB = 20*1024 = 20480으로 계산된 주소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프레임 2의 물리 주소는 2*4KB = 8192번지이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 *p = 'a'; 실행 시 MMU에 의해 논리 주소 20480이 물리 주소 8192로 바뀌어 물리 메모리 8192번지에 'a'가 저장된다.&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;프로세스에서 시스템 호출을 실행하는 경우:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커널 공간에 있는 페이지 k의 커널 코드를 실행하는 경우 현재 프로세스의 페이지 테이블에서 물리 프레임 번호를 알아내어 이에 적재된 커널 코드를 실행하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 커널 코드도 논리 주소로 되어 있다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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페이지, 즉 2KB로 매우 작다.&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;페이지 크기가 커지면 단편화도 커지며, 프로세스를 구성하는 페이지 개수는 줄어들고, 페이지 테이블 크기도 작아진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;페이징 주소 체계&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;페이징의 논리 주소&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;논리 주소 = [페이지 번호(p), 옵셋(offset)]&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;페이지 크기가 4KB(=2^12)라면, 페이지 내 각 바이트 주소(옵셋 주소)를 12비트로 나타낼 수 있다. = 옵셋 크기는 12비트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;32비트의 논리 주소에서 하위 12비트는 페이지 내 옵셋 주소, 상위 20비트는 페이지 번호가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;논리 주소의 물리 주소 변환&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;p를 페이지 테이블의 인덱스로 하여 페이지 테이블 항목을 찾음 &amp;rarr; 페이지 p가 할당된 프레임 번호 f 획득 &amp;rarr; 프레임 번호 f에 대해 옵셋을 그대로 사용하면 물리 주소가 된다.&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;* 페이지 테이블은 물리 메모리에 저장된다는 것을 잊지 말 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;페이징의 구현&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU와 MMU, 운영체제의 지원이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;하드웨어 지원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU 칩 내에 현재 실행 중인 프로세스의 페이지 테이블이 적재된 물리 메모리 주소를 가진 레지스터, PTBR(Page Table Base Register)가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레지스터의 값은 PCB에 저장된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;논리 주소를 물리 주소로 변환하기 위한 MMU 장치가 CPU 칩에 패키징되며, CPU에 따라 페이징 테이블 일부를 MMU 장치 내에 저장하기도 한다.&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;Page-table base register(PTBR): 페이지 테이블을 가리키는 포인터&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Page-table length register(PTLR): 페이지 테이블의 사이즈를 표현&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 이 두 레지스터를 MMU가 관리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PCB가 테이블 관련 레지스터를 다른 레지스터드롸 함께 보관하다가, 문맥 전환 시 테이블 레지스터 값들을 MMU로 전달&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;각 프로세스마다 PCB에 주소 저장, 실행될 때마다 PTBR 레지스터에 옮기는 기능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;페이지 테이블의 문제점과 TLB&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) 페이지 테이블로 인한 성능 저하&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) 공간 낭비&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;1) 페이지 테이블은 크기 때문에 메모리에 두게 되어 CPU가 메모리를 액세스할 때마다 물리 메모리를 2번 액세스하여 실행 속도를 심각하게 저하시킨다.&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;2) 페이지 테이블의 크기는 프로세스의 최대 크기(주소 공간)에 맞추어 생성되지만 실제 프로세스 크기는 그에 못 미치므로 페이지 테이블이 많이 비어 있어 메모리 낭비를 가져온다.&lt;/p&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) 2번의 물리 메모리 액세스 문제 해결: TLB의 사용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리 액세스 = 페이지 테이블 항목 읽기 1번 + 데이터 액세스 1번&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 페이지 테이블을 읽어오는 과정을 없애면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;TLB&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Translation Look-aside Buffer&lt;/b&gt; (=주소 변환용 캐시)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU가 최근에 액세스한 페이지 번호가 페이지가 적재된 프레임 번호의 쌍을 저장하는 캐시 메모리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MMU 내에 둔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TLB의 항목 = [페이지 번호 p, 프레임 번호 f]&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;일반 메모리와 달리, 페이지 번호를 &lt;u&gt;모든 항목과 동시에 비교&lt;/u&gt;하여 프레임 번호를 출력한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 주소 번지를 사용하지 않고, 내용을 직접 비교하여 찾는 메모리라 하여 '내용-주소화 기억 장치(content addressable memory, CAM)', '연관 메모리(associative memory)'라고도 부른다.&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;상용 CPU 내 TLB의 경우 가격이 비싸고 공간 제약 때문에 64~1024개 정도로 작은 편이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 페이지 테이블 전체를 저장할 수 없고, 최근 액세스한 소수의 페이지와 프레임 번호를 저장하여 활용성을 높인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;TLB를 활용한 메모리 액세스&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TLB를 사용하는 경우 TLB 히트가 일어나면 바로 주소 변환 발생 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;rarr;&lt;span&gt; 1번만 물리 메모리를 액세스해 액세스 시간을 반으로 줄임&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동일한 페이지를 연속해서 액세스하는 동안 TLB 히트가 바로 발생하므로 실행 속도가 대폭 향상된다.&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;단, 모든 프로그램의 실행 속도가 개선되는 것은 아님!&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;b&gt;참조의 지역성&lt;/b&gt;을 띄는데, 이 경우 효과적이지만, 랜덤하게 메모리를 액세스할 경우 TLB 미스가 자주 발생할 것이다.&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;* 참조의 지역성(locality of reference): 프로그램이 실행되는 동안 짧은 시간 범위 내에 일정 구간의 메모리 영역을 반복 액세스하는 경향성&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;TLB 성능 = TLB 히트율 = TLB 히트 횟수 비율 / CPU 메모리 액세스 횟수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TLB의 항목 수와 페이지 크기에 비례 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;rarr;&lt;span&gt; 항목 수를 늘린다면 비용 상승, 페이지 크기를 늘리면 내부 단편화 증가로 메모리 낭비&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;rarr;&lt;span&gt; 적절한 선택이 필요&lt;/span&gt;&lt;/span&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;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;TLB 도달 범위(TLB reach): TLB 캐시의 항목 수 * 페이지 크기로 계산 (성능 지표가 된다.)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실질 메모리 접근 시간(effective memory access time, EAT): hit ratio*메인 메모리 접근 시간+(1-hit ratio)*데이터 접근 시간&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;메모리 보호&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보호 비트를 이용해 읽기 전용 페이지에 쓰기 작업이 이뤄지지 않도록 함 &amp;rarr; 무효 비트가 설정된 페이지에서 매핑 시도 시 트랩 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;page-table length register(PTLR)&lt;/b&gt;이 페이지 범위 넘어서는 접근을 방지하는 방법도 있음 &amp;rarr; 모든 논리 주소 값을 PTLR과 비교해 오류가 나면 트랩 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;2) 페이지 테이블의 낭비 문제 해결: 역페이지 테이블, 멀티레벨 페이지 테이블&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;페이지 테이블로 메모리가 낭비되는 2가지 요인&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;- 페이지 테이블의 일부 항목만 사용&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;- 프로세스마다 페이지 테이블 존재&lt;/span&gt;&lt;/span&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;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;32비트 주소 체계를 사용하는 경우 프로세스의 주소 공간은 4GB, 페이지가 4KB면 최대 페이지 개수는 100만개이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;페이지 테이블 항목이 4바이트이면 프로세스의 페이지 테이블 크기는 4MB이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;그러나 실제 크기가 10MB라면 프로세스를 위해 실제 활용되는 페이지 테이블 항목 수는 2560개이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;또한 100개의 프로세스가 실행 중이면 페이지 테이블로만 소모되는 메모리가 100*4MB=400MB이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;역 페이지 테이블&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;프레임을 중심으로 물리 메모리의 전체 프레임에 대해 각 프레임이 어떤 프로세스의 어떤 페이지에 할당되었는지 나타내는 테이블&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;시스템에 1개&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Study/OS</category>
      <category>OperatingSystem</category>
      <category>operatingsystemconcepts</category>
      <category>OS</category>
      <category>공룡책</category>
      <category>메모리관리</category>
      <category>명품운영체제</category>
      <category>사자책</category>
      <category>운영체제</category>
      <author>harchiving</author>
      <guid isPermaLink="true">https://harchiving.tistory.com/23</guid>
      <comments>https://harchiving.tistory.com/23#entry23comment</comments>
      <pubDate>Sat, 14 Jun 2025 22:09:35 +0900</pubDate>
    </item>
    <item>
      <title>데이터베이스 권한 관리</title>
      <link>https://harchiving.tistory.com/22</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;606&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pB6Tj/btsOuNkIF4Z/OyDtswn9YSDreWe4bW8H4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pB6Tj/btsOuNkIF4Z/OyDtswn9YSDreWe4bW8H4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pB6Tj/btsOuNkIF4Z/OyDtswn9YSDreWe4bW8H4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpB6Tj%2FbtsOuNkIF4Z%2FOyDtswn9YSDreWe4bW8H4K%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;601&quot; height=&quot;292&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;606&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;보안&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스 보안의 목표 &amp;rarr; 조직에서 허가한 사용자만 데이터베이스에 접근할 수 있도록 통제하여 보안을 유지하는 것&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1712&quot; data-origin-height=&quot;454&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcwOaL/btsOv0jAep5/EMdwBJYiRT3ia0dNOpha5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcwOaL/btsOv0jAep5/EMdwBJYiRT3ia0dNOpha5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcwOaL/btsOv0jAep5/EMdwBJYiRT3ia0dNOpha5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcwOaL%2FbtsOv0jAep5%2FEMdwBJYiRT3ia0dNOpha5K%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;604&quot; height=&quot;160&quot; data-origin-width=&quot;1712&quot; data-origin-height=&quot;454&quot;/&gt;&lt;/span&gt;&lt;/figure&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;u&gt;물리적 손실&lt;/u&gt;을 발생시키는 위험으로부터 데이터베이스 보호&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;u&gt;접근이 허락된 사용자만 권한 내에서 데이터베이스를 사용&lt;/u&gt;하도록 보호&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계정이 발급된 사용자만 데이터베이스에 접근할 수 있도록 통제하고, 사용자별로 &lt;u&gt;사용 범위와 수행 가능한 작업 내용&lt;/u&gt;을 제한&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;u&gt;제약조건을 정의&lt;/u&gt;하고 위반하지 않도록 통제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;권한 관리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접근 제어(access control): 계정이 발급된 사용자가 로그인에 성공했을 경우에만 데이터베이스에 접근 허용, DB 관리자가 사용자 계정을 관리&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;1466&quot; data-origin-height=&quot;772&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WmKbJ/btsOuulp4Dh/lLlXn6vM94unagNRlH1jp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WmKbJ/btsOuulp4Dh/lLlXn6vM94unagNRlH1jp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WmKbJ/btsOuulp4Dh/lLlXn6vM94unagNRlH1jp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWmKbJ%2FbtsOuulp4Dh%2FlLlXn6vM94unagNRlH1jp0%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;520&quot; height=&quot;274&quot; data-origin-width=&quot;1466&quot; data-origin-height=&quot;772&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 사용자는 허용된 권한 내에서만 DB를 사용하며, 로그인에 성공한 사용자도 DB 사용 범위와 수행 가능한 작업이 제한된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보안을 위한 데이터 단위는 DB 전체 ~ 특정 데이터 값까지 다양할 수 O&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;데이터베이스의 모든 객체는 &lt;u&gt;객체를 생성한 사용자만 사용 권한&lt;/u&gt;을 갖는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스 객체의 소유자는 필요에 따라 SQL문을 이용해 다른 사용자에게 사용 권한을 부여하거나 취소할 수 있다.&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;1682&quot; data-origin-height=&quot;724&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d1jyYr/btsOt75jN6G/rJRnxOnbKTnjzahkzZNLnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d1jyYr/btsOt75jN6G/rJRnxOnbKTnjzahkzZNLnK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d1jyYr/btsOt75jN6G/rJRnxOnbKTnjzahkzZNLnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd1jyYr%2FbtsOt75jN6G%2FrJRnxOnbKTnjzahkzZNLnK%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;704&quot; height=&quot;303&quot; data-origin-width=&quot;1682&quot; data-origin-height=&quot;724&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체 권한 부여: GRANT문&lt;/h3&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;1702&quot; data-origin-height=&quot;186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSAT2Z/btsOtsuBnUt/VYNBLDcGaFe8mDZmM6JaC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSAT2Z/btsOtsuBnUt/VYNBLDcGaFe8mDZmM6JaC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSAT2Z/btsOtsuBnUt/VYNBLDcGaFe8mDZmM6JaC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSAT2Z%2FbtsOtsuBnUt%2FVYNBLDcGaFe8mDZmM6JaC0%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;576&quot; height=&quot;63&quot; data-origin-width=&quot;1702&quot; data-origin-height=&quot;186&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;INSERT, DELETE, UPDATE, SELECT, REFERENCES 등&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REFERENCES: 외래키 제약조건을 정의할 수 있는 권한&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UPDATE나 SELECT같은 경우, 테이블 일부 속성에 대한 권한 부여도 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 권한을 한번에 부여도 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 기본적으로 GRANT문으로 부여받은 권한을 다른 사용자에게 부여할 수 X&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;PUBLIC: 모든 사용자에게 권한을 똑같이 부여하고 싶을 때 사용자 지정 대신 PUBLIC으로 작성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WITH GRANT OPTION: 사용자가 자신이 부여받은 권한을 다른 사용자에게 부여할 수 있도록 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시스템 권한 부여: GRANT문&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스 관리자가 부여&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템 권한: 데이터베이스 관리와 관련된 작업에 대한 권한 ex. CREATE TABLE 등 DDL 관련 권한&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 지정 없이 GRANT 권한 TO 사용자로 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체 권한 취소: REVOKE문&lt;/h3&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;1646&quot; data-origin-height=&quot;192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kHUGT/btsOu5rXLFx/KlixSIAEJ4LkrzYFe40Fek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kHUGT/btsOu5rXLFx/KlixSIAEJ4LkrzYFe40Fek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kHUGT/btsOu5rXLFx/KlixSIAEJ4LkrzYFe40Fek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkHUGT%2FbtsOu5rXLFx%2FKlixSIAEJ4LkrzYFe40Fek%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;576&quot; height=&quot;67&quot; data-origin-width=&quot;1646&quot; data-origin-height=&quot;192&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 A가 B에게 권한을 부여하여 B가 C에게 같은 권한을 부여한 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CASCADE 옵션: 권한 취소할 A가 B, C 모두 연쇄적으로 권한을 함께 취소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RESTRICT 옵션: 권한을 취소할 A가 C가 부여받은 권한까지 취소하지 X&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시스템 권한 취소: REVOKE문&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스 관리자가 다른 사용자에게 부여한 시스템 권한을 취소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 지정 X&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1434&quot; data-origin-height=&quot;700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCZtsN/btsOuIKvsYh/zFX24D3VFQ3sANLbBmYfG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCZtsN/btsOuIKvsYh/zFX24D3VFQ3sANLbBmYfG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCZtsN/btsOuIKvsYh/zFX24D3VFQ3sANLbBmYfG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCZtsN%2FbtsOuIKvsYh%2FzFX24D3VFQ3sANLbBmYfG1%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;559&quot; height=&quot;273&quot; data-origin-width=&quot;1434&quot; data-origin-height=&quot;700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;역할(role)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;rarr; 권한 관리가 쉬워짐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;역할 생성: CREATE ROLE문&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 역할 생성은 &lt;u&gt;DB 관리자&lt;/u&gt;가 담당&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1658&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Xpubk/btsOv7QgBfA/Fhd4kjCtYKvjeOQ7FyVeDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Xpubk/btsOv7QgBfA/Fhd4kjCtYKvjeOQ7FyVeDK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Xpubk/btsOv7QgBfA/Fhd4kjCtYKvjeOQ7FyVeDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXpubk%2FbtsOv7QgBfA%2FFhd4kjCtYKvjeOQ7FyVeDK%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;593&quot; height=&quot;60&quot; data-origin-width=&quot;1658&quot; data-origin-height=&quot;168&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;역할에 권한 추가: GRANT문&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;객체와 관련된 권한을 역할에 추가하는 작업은 &lt;u&gt;객체의 소유자&lt;/u&gt;가 담당&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1708&quot; data-origin-height=&quot;160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CLXqL/btsOurI2ici/ymP4DxAUhuHhRVfiE5kFv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CLXqL/btsOurI2ici/ymP4DxAUhuHhRVfiE5kFv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CLXqL/btsOurI2ici/ymP4DxAUhuHhRVfiE5kFv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCLXqL%2FbtsOurI2ici%2FymP4DxAUhuHhRVfiE5kFv1%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;626&quot; height=&quot;59&quot; data-origin-width=&quot;1708&quot; data-origin-height=&quot;160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;역할 부여: GRANT문&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역할을 사용자에게 부여하는 것은 &lt;u&gt;DB 관리자&lt;/u&gt;가 담당&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;180&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqQZNr/btsOuJJnDHG/xeTKnIp0yFfCrY6SqnImkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqQZNr/btsOuJJnDHG/xeTKnIp0yFfCrY6SqnImkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqQZNr/btsOuJJnDHG/xeTKnIp0yFfCrY6SqnImkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqQZNr%2FbtsOuJJnDHG%2FxeTKnIp0yFfCrY6SqnImkK%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;583&quot; height=&quot;63&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;180&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;역할 취소: REVOKE문&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자에게 부여한 역할 취소는&lt;u&gt; DB 관리자&lt;/u&gt;가 담당&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1650&quot; data-origin-height=&quot;200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zvHLh/btsOwHwKGEl/eKYkTKJ2g8yRyTwk8StXq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zvHLh/btsOwHwKGEl/eKYkTKJ2g8yRyTwk8StXq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zvHLh/btsOwHwKGEl/eKYkTKJ2g8yRyTwk8StXq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzvHLh%2FbtsOwHwKGEl%2FeKYkTKJ2g8yRyTwk8StXq0%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;521&quot; height=&quot;63&quot; data-origin-width=&quot;1650&quot; data-origin-height=&quot;200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;역할 제거: DROP ROLE문&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역할 제거는 &lt;u&gt;DB 관리자&lt;/u&gt;가 담당&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1612&quot; data-origin-height=&quot;192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/D5PFu/btsOweolRN9/o719JVQ9hLPcvAKdJTvKdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/D5PFu/btsOweolRN9/o719JVQ9hLPcvAKdJTvKdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/D5PFu/btsOweolRN9/o719JVQ9hLPcvAKdJTvKdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FD5PFu%2FbtsOweolRN9%2Fo719JVQ9hLPcvAKdJTvKdK%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;497&quot; height=&quot;59&quot; data-origin-width=&quot;1612&quot; data-origin-height=&quot;192&quot;/&gt;&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;출처: 데이터베이스 개론 2판 김연희 저, MySQL로 배우는 데이터베이스 개론과 실습 박우창 외2&lt;/blockquote&gt;</description>
      <category>Study/DateBase</category>
      <category>DATABASE</category>
      <category>DB</category>
      <category>SQL</category>
      <category>SQLD</category>
      <category>권한관리</category>
      <category>데이터베이스</category>
      <category>데이터베이스개론</category>
      <category>데이터베이스보안</category>
      <author>harchiving</author>
      <guid isPermaLink="true">https://harchiving.tistory.com/22</guid>
      <comments>https://harchiving.tistory.com/22#entry22comment</comments>
      <pubDate>Tue, 10 Jun 2025 20:23:16 +0900</pubDate>
    </item>
    <item>
      <title>데이터베이스 회복과 병행 제어</title>
      <link>https://harchiving.tistory.com/21</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;792&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AN2kL/btsOwg0tJFE/PC0W2g3SgKSrItoK0ps900/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AN2kL/btsOwg0tJFE/PC0W2g3SgKSrItoK0ps900/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AN2kL/btsOwg0tJFE/PC0W2g3SgKSrItoK0ps900/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAN2kL%2FbtsOwg0tJFE%2FPC0W2g3SgKSrItoK0ps900%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;532&quot; height=&quot;409&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;792&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;p data-ke-size=&quot;size16&quot;&gt;작업 수행에 필요한 SQL문들의 모임(특히 DB를 변경하는 INSERT, DELETE, UPDATE문 관리)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;장애 발생 시 복구 작업이나 병행 제어 작업을 위한 중요한 단위로 사용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스 무결성과 일관성을 보장하기 위해 작업 수행에 필요한 연산들을 하나의 트랜잭션으로 제대로 정의, 관리해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;특성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;= ACID 특성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원자성, 일관성, 격리성, 지속성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;원자성(atomicity)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션의 연산들이 &lt;b&gt;모두&lt;/b&gt; 정상적으로 실행되거나, &lt;b&gt;하나도&lt;/b&gt; 실행되지 않아야 하는 all-or-nothing 방식을 의미&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션 수행 도중 장애 발생 &amp;rarr; 지금까지 실행한 연산 처리를 모두 취소, 데이터베이스를 트랜잭션 작업 전 상태로 되돌려야 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 원자성 보장을 위해 장애 발생 시 회복 기능 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;일관성(consistency)&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;584&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEZIKm/btsOuE8jizY/8i0Snki9hTwRtVmPbOEjtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEZIKm/btsOuE8jizY/8i0Snki9hTwRtVmPbOEjtk/img.png&quot; data-alt=&quot;트랜잭션이 성공했는데 성공한 결과가 아님!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEZIKm/btsOuE8jizY/8i0Snki9hTwRtVmPbOEjtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEZIKm%2FbtsOuE8jizY%2F8i0Snki9hTwRtVmPbOEjtk%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;468&quot; height=&quot;229&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;584&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;트랜잭션이 성공적으로 수행된 후에도 데이터베이스가 일관된 상태를 유지해야 함을 의미&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;격리성(isolation)&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1288&quot; data-origin-height=&quot;830&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bx9vE9/btsOt7jPkDG/FKY2Ob1WyF3nF1Jbkob7A0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bx9vE9/btsOt7jPkDG/FKY2Ob1WyF3nF1Jbkob7A0/img.png&quot; data-alt=&quot;계좌이체 트랜잭션 중간 연산 결과에 계좌입금 트랜잭션이 접근해 은경 계좌 잔액이 1,000원과 5,000원이 됨&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bx9vE9/btsOt7jPkDG/FKY2Ob1WyF3nF1Jbkob7A0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbx9vE9%2FbtsOt7jPkDG%2FFKY2Ob1WyF3nF1Jbkob7A0%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;590&quot; height=&quot;380&quot; data-origin-width=&quot;1288&quot; data-origin-height=&quot;830&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;계좌이체 트랜잭션 중간 연산 결과에 계좌입금 트랜잭션이 접근해 은경 계좌 잔액이 1,000원과 5,000원이 됨&lt;/figcaption&gt;
&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;지속성(durability)&lt;/h4&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;트랜잭션의 4가지 특성을 보장하기 위해 필요한 기능&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1014&quot; data-origin-height=&quot;722&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JG4by/btsOwNDCfGV/bySpfhhpKvOKSOiLWFKim0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JG4by/btsOwNDCfGV/bySpfhhpKvOKSOiLWFKim0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JG4by/btsOwNDCfGV/bySpfhhpKvOKSOiLWFKim0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJG4by%2FbtsOwNDCfGV%2FbySpfhhpKvOKSOiLWFKim0%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;374&quot; height=&quot;266&quot; data-origin-width=&quot;1014&quot; data-origin-height=&quot;722&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;트랜잭션의 주요 연산&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;commit 연산&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션이 성공적으로 수행되었음을 선언(작업 완료)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;commit 연산이 실행되면 트랜잭션 수행 결과가 DB에 반영되고 일관된 상태를 지속적으로 유지하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;rollback 연산&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션을 수행하는 데 실패했음을 선언(작업 취소)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;rollback 연산이 실행되면 트랜잭션이 지금까지 실행한 연산의 결과가 취소되고 DB가 트랜잭션 수행 전의 일관된 상태로 되돌아간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;트랜잭션의 상태&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1006&quot; data-origin-height=&quot;976&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgpPJh/btsOwHKaS8B/jRUHGPo2q3pz4SP0uF6jp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgpPJh/btsOwHKaS8B/jRUHGPo2q3pz4SP0uF6jp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgpPJh/btsOwHKaS8B/jRUHGPo2q3pz4SP0uF6jp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgpPJh%2FbtsOwHKaS8B%2FjRUHGPo2q3pz4SP0uF6jp1%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;367&quot; height=&quot;356&quot; data-origin-width=&quot;1006&quot; data-origin-height=&quot;976&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;활동(active) 상태&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션이 수행되기 시작하여 현재 수행 중인 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;부분 완료(partially committed) 상태&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션의 마지막 연산이 실행을 끝낸 직후의 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;완료(committed) 상태&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션이 성공적으로 완료되어 commit 연산을 실행한 상태. 최종 결과를 DB에 반영함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;실패(failed) 상태&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장애가 발생하여 트랜잭션의 수행이 중단된 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;철회(aborted) 상태&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션 수행 실패로 rollback 연산을 실행한 상태. 철회 상태로 종료된 트랜잭션은 상황에 따라 다시 수행되거나 폐기됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;장애와 회복&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;장애(failure)&lt;/h3&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;1820&quot; data-origin-height=&quot;820&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgYqla/btsOwHi6oVO/oLe1Ez7Vn4nI9kKneexkRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgYqla/btsOwHi6oVO/oLe1Ez7Vn4nI9kKneexkRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgYqla/btsOwHi6oVO/oLe1Ez7Vn4nI9kKneexkRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgYqla%2FbtsOwHi6oVO%2FoLe1Ez7Vn4nI9kKneexkRk%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;663&quot; height=&quot;299&quot; data-origin-width=&quot;1820&quot; data-origin-height=&quot;820&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;데이터베이스를 저장하는 저장장치의 종류&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1796&quot; data-origin-height=&quot;836&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btUVjR/btsOt5F9SwH/sOAbN49JNWFcSmqJVzaQ6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btUVjR/btsOt5F9SwH/sOAbN49JNWFcSmqJVzaQ6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btUVjR/btsOt5F9SwH/sOAbN49JNWFcSmqJVzaQ6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtUVjR%2FbtsOt5F9SwH%2FsOAbN49JNWFcSmqJVzaQ6K%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;643&quot; height=&quot;299&quot; data-origin-width=&quot;1796&quot; data-origin-height=&quot;836&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;트랜잭션 수행을 위해 필요한 데이터 연산&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1660&quot; data-origin-height=&quot;582&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XM2Gj/btsOuhGy57T/8nmmh6Uupmm0Ru3AQpNT6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XM2Gj/btsOuhGy57T/8nmmh6Uupmm0Ru3AQpNT6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XM2Gj/btsOuhGy57T/8nmmh6Uupmm0Ru3AQpNT6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXM2Gj%2FbtsOuhGy57T%2F8nmmh6Uupmm0Ru3AQpNT6K%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;572&quot; height=&quot;201&quot; data-origin-width=&quot;1660&quot; data-origin-height=&quot;582&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;디스크 &amp;harr; 메인 메모리 데이터 이동 연산: input/output&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 DB는 비휘발성 저장 장치인 디스크에 상주하므로, 트랜잭션이 DB의 데이터를 처리하기 위해서는 데이터를 디스크에서 메인 메모리로 가져와 처리 후, 그 결과를 디스크로 보내는 작업이 필요하다.&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;1600&quot; data-origin-height=&quot;542&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c13eF6/btsOuXVhNdj/BNLTIinUDUpTTKWLBiAtHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c13eF6/btsOuXVhNdj/BNLTIinUDUpTTKWLBiAtHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c13eF6/btsOuXVhNdj/BNLTIinUDUpTTKWLBiAtHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc13eF6%2FbtsOuXVhNdj%2FBNLTIinUDUpTTKWLBiAtHk%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;508&quot; height=&quot;172&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;542&quot;/&gt;&lt;/span&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;h4 data-ke-size=&quot;size20&quot;&gt;메인 메모리 &amp;harr; 프로그램 변수 데이터 이동 연산: read/write&lt;/h4&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;1564&quot; data-origin-height=&quot;538&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xv8GV/btsOwaTEffn/M4fwm7oCOEltudHl1WCk0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xv8GV/btsOwaTEffn/M4fwm7oCOEltudHl1WCk0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xv8GV/btsOwaTEffn/M4fwm7oCOEltudHl1WCk0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxv8GV%2FbtsOwaTEffn%2FM4fwm7oCOEltudHl1WCk0k%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;558&quot; height=&quot;192&quot; data-origin-width=&quot;1564&quot; data-origin-height=&quot;538&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;회복(recovery)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장애가 발생했을 때 데이터베이스를 장애가 발생하기 전의 일관된 상태로 복구시키는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션의 특성을 보장하고, DB를 일관된 상태로 유지하기 위해 필수적인 기능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회복 관리자가 담당하여, 장애 발생을 탐지하고, 장애가 탐지되면 DB 복구 기능을 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;회복을 위해 데이터베이스 복사본 생성&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스 회복의 핵심 원리 = &lt;b&gt;데이터 중복&lt;/b&gt;!&lt;/p&gt;
&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;544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OQZmY/btsOuJiepxD/5yKWK9Fb4LweGpLMTKwKvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OQZmY/btsOuJiepxD/5yKWK9Fb4LweGpLMTKwKvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OQZmY/btsOuJiepxD/5yKWK9Fb4LweGpLMTKwKvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOQZmY%2FbtsOuJiepxD%2F5yKWK9Fb4LweGpLMTKwKvK%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;539&quot; height=&quot;183&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;544&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;회복을 위한 기본 연산&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1726&quot; data-origin-height=&quot;562&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HVov0/btsOvbyIP5h/rGOrgDJAg0yDIDBvkFF3QK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HVov0/btsOvbyIP5h/rGOrgDJAg0yDIDBvkFF3QK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HVov0/btsOvbyIP5h/rGOrgDJAg0yDIDBvkFF3QK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHVov0%2FbtsOvbyIP5h%2FrGOrgDJAg0yDIDBvkFF3QK%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;593&quot; height=&quot;193&quot; data-origin-width=&quot;1726&quot; data-origin-height=&quot;562&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;로그 파일&lt;/h4&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&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bggZSR/btsOvVWNEeF/cKNazExH9mj1shnbWUOSJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bggZSR/btsOvVWNEeF/cKNazExH9mj1shnbWUOSJ1/img.png&quot; data-origin-width=&quot;1380&quot; data-origin-height=&quot;770&quot; data-is-animation=&quot;false&quot; width=&quot;575&quot; height=&quot;321&quot; style=&quot;width: 49.9105%; margin-right: 10px;&quot; data-widthpercent=&quot;50.5&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bggZSR/btsOvVWNEeF/cKNazExH9mj1shnbWUOSJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbggZSR%2FbtsOvVWNEeF%2FcKNazExH9mj1shnbWUOSJ1%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;1380&quot; height=&quot;770&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOuPyU/btsOuBLMNZK/oPKQ6HzE1h9qohIKzXWZA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOuPyU/btsOuBLMNZK/oPKQ6HzE1h9qohIKzXWZA1/img.png&quot; data-origin-width=&quot;1532&quot; data-origin-height=&quot;872&quot; data-is-animation=&quot;false&quot; style=&quot;width: 48.9267%;&quot; data-widthpercent=&quot;49.5&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOuPyU/btsOuBLMNZK/oPKQ6HzE1h9qohIKzXWZA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOuPyU%2FbtsOuBLMNZK%2FoPKQ6HzE1h9qohIKzXWZA1%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;1532&quot; height=&quot;872&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;회복 기법&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1650&quot; data-origin-height=&quot;746&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r88ZV/btsOwEfDSk9/hhHREBE7ukkPFzFXgEtl8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r88ZV/btsOwEfDSk9/hhHREBE7ukkPFzFXgEtl8k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r88ZV/btsOwEfDSk9/hhHREBE7ukkPFzFXgEtl8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr88ZV%2FbtsOwEfDSk9%2FhhHREBE7ukkPFzFXgEtl8k%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;504&quot; height=&quot;228&quot; data-origin-width=&quot;1650&quot; data-origin-height=&quot;746&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 로그 회복 기법 - 즉시 갱신 회복 기법&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션 수행 중에 데이터 변경 연산 결과를 &lt;u&gt;데이터베이스에 즉시 반영&lt;/u&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;u&gt;로그 레코드를 먼저 기록&lt;/u&gt;한 다음 데이터베이스에 변경 연산을 반영&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장애 발생 시점에 따라 redo나 undo 연산으로 데이터베이스를 복구&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 트랜잭션 완료 전 장애 발생 시 = 로그 파일에 &amp;lt;Ti, start&amp;gt;는 존재하지만 &amp;lt;Ti, commit&amp;gt;은 존재하지 않는 상태: undo 연산&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 트랜잭션 완료 후 장애 발생 시 = 로그 파일에 &amp;lt;Ti, start&amp;gt;와 &amp;lt;Ti, commit&amp;gt; 모두 존재하는 상태: redo 연산&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 로그 회복 기법 - 지연 갱신 회복 기법&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션 수행 중에 데이터 변경 연산의 결과를 &lt;u&gt;로그에만 기록&lt;/u&gt;해두고, 트랜잭션이 부분 완료된 후에 로그에 기록된 내용을 이용해 &lt;u&gt;데이터베이스에 한번에 반영&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션 수행 중 장애가 발생할 경우, 로그에 기록된 내용을 버리기만 하면 DB가 원래 상태를 그대로 유지하게 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;undo 연산이 필요 없고, redo 연산만 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 트랜잭션 완료 전 장애 발생 시: 로그 내용을 무시하고 버림&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 트랜잭션 완료 후 장애 발생 시: redo 연산&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그 레코드에는 변경 후 값만 기록하면 됨: &amp;lt;Ti, X, new_value&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 검사 시점 회복 방법&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그 기록을 사용하되, 일정 시간 간격으로&lt;u&gt; 검사 시점(checkpoint)을 만듦&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검사 시점이 되면 모든 로그 레코드를 로그 파일에 기록하고, 데이터 변경 내용을 데이터베이스에 반영한 후, 검사 시점을 표시하는 &amp;lt;checkpoint L&amp;gt; 로그 레코드를 로그 파일에 기록(L은 현재 실행 중인 트랜잭션 리스트)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장애 발생 시 &lt;u&gt;가장 최근 검사 시점 이후의 트랜잭션에만 회복 작업 수행&lt;/u&gt;; 회복 작업은 로그 회복 기법 중 하나로 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 로그 전체를 대상으로 회복 기법을 적용할 때 발생할 수 있는 &lt;u&gt;비효율성 문제 해결&lt;/u&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 미디어 회복 기법&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디스크에 발생할 수 있는 장애에 대비한 회복 기법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;덤프(복사본) 이용 &amp;rarr; 전체 데이터베이스의 내용을 &lt;u&gt;일정 주기마다 다른 안전한 저장 장치에 복사&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디스크 장애 발생 시: &lt;u&gt;가장 최근에 복사해둔 덤프를 이용해&lt;/u&gt; 장애 발생 이전의 DB 상태로 복구, 필요에 따라 redo 연산 수행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;병행 제어&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;병행 수행(concurrency): 여러 사용자가 데이터베이스를 동시 공유할 수 있도록 여러 개의 트랜잭션을 동시에 수행하는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 트랜잭션이 차례로 번갈아 수행되는 인터리빙(interleaving) 방식으로 진행&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;병행 제어(concurrency control) = 동시성 제어: 병행 수행 시 같은 데이터에 접근해 연산을 수행해도 문제가 발생하지 않고, 정확한 수행 결과를 얻을 수 있도록 트랜잭션 수행을 제어하는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;병행 수행 시 발생할 수 있는 문제점&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;갱신 분실(lost update)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 트랜잭션이 수행한 데이터 변경 연산 결과를 &lt;u&gt;다른 트랜잭션이 덮어써 변경 연산이 무효화&lt;/u&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;1778&quot; data-origin-height=&quot;904&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLjZ1d/btsOv6Rh2hd/Yti1o452d6RdF0C3QhxCxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLjZ1d/btsOv6Rh2hd/Yti1o452d6RdF0C3QhxCxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLjZ1d/btsOv6Rh2hd/Yti1o452d6RdF0C3QhxCxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLjZ1d%2FbtsOv6Rh2hd%2FYti1o452d6RdF0C3QhxCxk%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;622&quot; height=&quot;316&quot; data-origin-width=&quot;1778&quot; data-origin-height=&quot;904&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;모순성(inconsistency)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 트랜잭션이 여러 개 데이터 변경 연산을 실행할 때 &lt;u&gt;일관성 없는 상태의 데이터베이스에서 데이터를 가져와 연산&lt;/u&gt;함으로써 모순된 결과가 발생하는 것&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1528&quot; data-origin-height=&quot;997&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cVqMuW/btsOwehtGDT/KcY7G8tRPKPvqmtvkQlwq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cVqMuW/btsOwehtGDT/KcY7G8tRPKPvqmtvkQlwq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cVqMuW/btsOwehtGDT/KcY7G8tRPKPvqmtvkQlwq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcVqMuW%2FbtsOwehtGDT%2FKcY7G8tRPKPvqmtvkQlwq0%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;614&quot; height=&quot;401&quot; data-origin-width=&quot;1528&quot; data-origin-height=&quot;997&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;연쇄 복귀(cascading rollback)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션이 완료되기 전 장애가 발생하여 rollback 연산을 수행하면, 장애 발생 전에 이 트랜잭션이 변경한 데이터를 가져가, 변경 연산을 실행한 &lt;u&gt;다른 트랜잭션에도 rollback 연산을 연쇄적으로 실행&lt;/u&gt;해야 한다는 것&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1552&quot; data-origin-height=&quot;906&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bof1SA/btsOwJH2kAc/d5N0WMHhpmcwhT5b6RZP1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bof1SA/btsOwJH2kAc/d5N0WMHhpmcwhT5b6RZP1K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bof1SA/btsOwJH2kAc/d5N0WMHhpmcwhT5b6RZP1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbof1SA%2FbtsOwJH2kAc%2Fd5N0WMHhpmcwhT5b6RZP1K%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;627&quot; height=&quot;366&quot; data-origin-width=&quot;1552&quot; data-origin-height=&quot;906&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 직렬 스케줄(serial schedule)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;다른 트랜잭션의 방해를 받지 않고 독립적으로 수행되어 항상 모순 없는 정확한 결과를 얻게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다양한 직렬 스케줄이 만들어질 수 있고, &lt;u&gt;결과는 모두 정확&lt;/u&gt;하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;But 병행 수행으로 볼 수 없음!&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1664&quot; data-origin-height=&quot;1042&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A7A6Z/btsOvH5CRtl/yCoW15viporJPymKAw61KK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A7A6Z/btsOvH5CRtl/yCoW15viporJPymKAw61KK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A7A6Z/btsOvH5CRtl/yCoW15viporJPymKAw61KK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA7A6Z%2FbtsOvH5CRtl%2FyCoW15viporJPymKAw61KK%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;346&quot; data-origin-width=&quot;1664&quot; data-origin-height=&quot;1042&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 비직렬 스케줄(nonserial schedule)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;rarr; 한 트랜잭션이 완료되기 전에 다른 트랜잭션의 연산 실행 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;갱신 분실, 모순성, 연쇄 복귀 등의 문제가 발생할 수 있어 &lt;u&gt;결과의 정확성 보장 불가&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다양한 비직렬 스케줄이 만들어질 수 있고, 그중 잘못된 결과를 생성하는 것도 존재한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOSD4A/btsOwGYR4gQ/tkEaL5BmwQC2YBedLvrUCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOSD4A/btsOwGYR4gQ/tkEaL5BmwQC2YBedLvrUCK/img.png&quot; data-origin-width=&quot;1558&quot; data-origin-height=&quot;1002&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.9222%; margin-right: 10px;&quot; data-widthpercent=&quot;50.51&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOSD4A/btsOwGYR4gQ/tkEaL5BmwQC2YBedLvrUCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOSD4A%2FbtsOwGYR4gQ%2FtkEaL5BmwQC2YBedLvrUCK%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;1558&quot; height=&quot;1002&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GffUy/btsOwP9nusm/8OCA0SCQs8lyRJ3ilVczuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GffUy/btsOwP9nusm/8OCA0SCQs8lyRJ3ilVczuk/img.png&quot; data-origin-width=&quot;1490&quot; data-origin-height=&quot;978&quot; data-is-animation=&quot;false&quot; style=&quot;width: 48.915%;&quot; data-widthpercent=&quot;49.49&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GffUy/btsOwP9nusm/8OCA0SCQs8lyRJ3ilVczuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGffUy%2FbtsOwP9nusm%2F8OCA0SCQs8lyRJ3ilVczuk%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;1490&quot; height=&quot;978&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;한 트랜잭션의 read와 write 사이에 다른 트랜잭션에서 관련된 변수의 연산 수행 시 문제 발생&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 직렬 가능 스케줄&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직렬 스케줄에 따라 수행한 것과 같이 정확한 결과를 생성하는 비직렬 스케줄&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;비직렬 스케줄 중에서 수행 결과가 동일한 직렬 스케줄&lt;/u&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;인터리빙 방식으로 &lt;u&gt;병행 수행하면서도 정확한 결과&lt;/u&gt;를 얻을 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;직렬 가능 스케줄인지 판단&lt;/u&gt;하는 것의 어려움 &amp;rarr; 직렬 가능성을 보장하는 &lt;u&gt;병행 제어 기법을 사용&lt;/u&gt;하는 것이 일반적&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;로킹(locking) 기법&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 원리: 한 트랜잭션이 먼저 접근한 데이터에 대한 연산을 끝낼 때까지는 다른 트랜잭션이 그 데이터에 접근하지 못하도록 &lt;u&gt;상호 배제(mutual exclusion)&lt;/u&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;방법: 병행 수행되는 트랜잭션들이 같은 데이터에 동시에 접근하지 못하도록&lt;u&gt; lock과 unlock 연산을 이용해 제어&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- lock: 트랜잭션이 데이터에 대한 독점권을 &lt;u&gt;요청&lt;/u&gt;하는 연산&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- unlock: 트랜잭션이 데이터에 대한 독점권을 &lt;u&gt;반환&lt;/u&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;기본 로킹 규약:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션이 데이터에 접근하기 위해 먼저 &lt;u&gt;read나 write 실행 전 lock 연산&lt;/u&gt;으로 독점권 획득&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 트랜잭션에 의해 lock 연산이 실행된 데이터에는 lock 연산 실행 불가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;독점권을 획득한 데이터에 대한 &lt;u&gt;모든 연산 수행이 끝난 뒤 unlock 연산을 실행&lt;/u&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;로킹 단위:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;lock 연산을 실행하는 대상 데이터의 크기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체 DB부터 릴레이션, 투플, 속성까지도 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;로킹 단위가 커질수록 병행성은 낮아지지만 제어가 쉽고, 단위가 작아질수록 제어는 어렵지만 병행성은 높아진다.&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2344&quot; data-origin-height=&quot;989&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cd1yw1/btsOuznbfXA/3uxPNylgnCqiSkybC3cKuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cd1yw1/btsOuznbfXA/3uxPNylgnCqiSkybC3cKuk/img.png&quot; data-alt=&quot;T1의 COMMIT된 결과에 대해 T2가 연산 수행&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cd1yw1/btsOuznbfXA/3uxPNylgnCqiSkybC3cKuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcd1yw1%2FbtsOuznbfXA%2F3uxPNylgnCqiSkybC3cKuk%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;756&quot; height=&quot;319&quot; data-origin-width=&quot;2344&quot; data-origin-height=&quot;989&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;T1의 COMMIT된 결과에 대해 T2가 연산 수행&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;기본 로킹 규약의 효율성을 높이기 위한 방법&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션들이 같은 데이터에 &lt;u&gt;동시에 read 연산을 실행&lt;/u&gt;하는 것을 허용&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8keNA/btsOuE2onpX/AfOUxhIyG6ydLBKiHaxEP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8keNA/btsOuE2onpX/AfOUxhIyG6ydLBKiHaxEP0/img.png&quot; data-origin-width=&quot;1740&quot; data-origin-height=&quot;702&quot; data-is-animation=&quot;false&quot; width=&quot;575&quot; height=&quot;232&quot; style=&quot;width: 47.4943%; margin-right: 10px;&quot; data-widthpercent=&quot;48.05&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8keNA/btsOuE2onpX/AfOUxhIyG6ydLBKiHaxEP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8keNA%2FbtsOuE2onpX%2FAfOUxhIyG6ydLBKiHaxEP0%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;1740&quot; height=&quot;702&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rT52f/btsOuvymbyZ/CMLzciIdJQB39mepFJleOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rT52f/btsOuvymbyZ/CMLzciIdJQB39mepFJleOK/img.png&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;468&quot; data-is-animation=&quot;false&quot; style=&quot;width: 51.3429%;&quot; data-widthpercent=&quot;51.95&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rT52f/btsOuvymbyZ/CMLzciIdJQB39mepFJleOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrT52f%2FbtsOuvymbyZ%2FCMLzciIdJQB39mepFJleOK%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;1254&quot; height=&quot;468&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서로 다른 트랜잭션이 같은 데이터에 공용 lock 연산만 동시에 실행 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전용 lock을 실행한 데이터에는 모두 실행 불가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;기본 로킹 규약으로 직렬 가능성이 보장되지 않는 스케줄 예&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1088&quot; data-origin-height=&quot;972&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dfTu83/btsOuPv06ml/p0ADH1GhkEH6NcNaNMhD71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dfTu83/btsOuPv06ml/p0ADH1GhkEH6NcNaNMhD71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dfTu83/btsOuPv06ml/p0ADH1GhkEH6NcNaNMhD71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdfTu83%2FbtsOuPv06ml%2Fp0ADH1GhkEH6NcNaNMhD71%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;569&quot; height=&quot;508&quot; data-origin-width=&quot;1088&quot; data-origin-height=&quot;972&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션 T1이 너무 빨리 unlock 연산을 실행하여 트랜잭션 T2가 일관성 없는 데이터에 접근하게 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;T1의 데이터 Y에 대한 연산이 끝나기 전에 T2에서 Y에 대한 연산을 수행해 Y의 데이터 값이 일관성을 잃게 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2단계 로킹 규약(2PLP; 2 Phase Locking Protocol)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 로킹 규약의 문제를 해결하고 트랜잭션의 직렬 가능성을 보장하기 위해 lock과 unlock 연산의 수행 시점에 대한 새로운 규약을 추가한 것&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;방법:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션이 lock과 unlock 연산을 &lt;u&gt;확장 단계와 축소 단계로 나누어&lt;/u&gt; 실행&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;276&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmUtEu/btsOwJnMB9J/JKi6epit6YigXBYgZECqFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmUtEu/btsOwJnMB9J/JKi6epit6YigXBYgZECqFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmUtEu/btsOwJnMB9J/JKi6epit6YigXBYgZECqFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmUtEu%2FbtsOwJnMB9J%2FJKi6epit6YigXBYgZECqFk%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;575&quot; height=&quot;139&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;276&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션 처음 실행 시 확장 단계로 들어가 lock 연산만 실행 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;unlock 연산을 실행하면 축소 단계로 들어가 unlock 연산만 실행 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션은 &lt;u&gt;첫번째 unlock 연산 실행 전에 필요한 모든 lock 연산을 실행&lt;/u&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;rarr; 확장 단계 &amp;rarr; lock 연산(1) &amp;rarr; lock 연산(2)&amp;nbsp; &amp;rarr; unlock 연산(2)&amp;nbsp; &amp;rarr; 축소 단계 &amp;rarr; unlock 연산(1)&amp;nbsp; &amp;rarr; 완료&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;즉, 한 트랙잭션 안에서 lock-unlock 과정이 교차되지 않고 중첩되어 발생하도록 제한함&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1282&quot; data-origin-height=&quot;1188&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkBsp4/btsOuWIYZT6/kH9MqaVHPLkVpbKGylQu50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkBsp4/btsOuWIYZT6/kH9MqaVHPLkVpbKGylQu50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkBsp4/btsOuWIYZT6/kH9MqaVHPLkVpbKGylQu50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkBsp4%2FbtsOuWIYZT6%2FkH9MqaVHPLkVpbKGylQu50%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;552&quot; height=&quot;512&quot; data-origin-width=&quot;1282&quot; data-origin-height=&quot;1188&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;교착 상태(deadlock)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션들이 상대가 독점하고 있는 데이터에 unlock 연산이 실행되기를 서로 기다리면서 트랜잭션 수행을 중단하고 있는 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 발생하지 않도록 예방하거나, 빨리 탐지해 조치해야 함&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;676&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLFYcE/btsOuLf6HPb/Sbrh1WpkpSZZhFVomkiAy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLFYcE/btsOuLf6HPb/Sbrh1WpkpSZZhFVomkiAy0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLFYcE/btsOuLf6HPb/Sbrh1WpkpSZZhFVomkiAy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLFYcE%2FbtsOuLf6HPb%2FSbrh1WpkpSZZhFVomkiAy0%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;404&quot; height=&quot;353&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;676&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Time 8: T1이 X를 읽고자 하지만 T2의 read_lock(X)로 읽지 못하고 중단됨&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;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;출처: 데이터베이스 개론 2판 김연희 저, MySQL로 배우는 데이터베이스 개론과 실습 박우창 외2&lt;/blockquote&gt;</description>
      <category>Study/DateBase</category>
      <category>DATABASE</category>
      <category>DB</category>
      <category>SQL</category>
      <category>SQLD</category>
      <category>데이터베이스</category>
      <category>데이터베이스개론</category>
      <category>병행제어</category>
      <category>트랜잭션</category>
      <category>회복</category>
      <author>harchiving</author>
      <guid isPermaLink="true">https://harchiving.tistory.com/21</guid>
      <comments>https://harchiving.tistory.com/21#entry21comment</comments>
      <pubDate>Tue, 10 Jun 2025 20:22:59 +0900</pubDate>
    </item>
  </channel>
</rss>