<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>A BETTER DAY</title>
    <link>https://soom-tech.tistory.com/</link>
    <description>병아리 개발자의 메모장  </description>
    <language>ko</language>
    <pubDate>Sat, 1 Aug 2026 13:37:13 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor> ruby</managingEditor>
    <image>
      <title>A BETTER DAY</title>
      <url>https://tistory1.daumcdn.net/tistory/6279518/attach/3cb3969719394d08a1a48ce0aad47d8f</url>
      <link>https://soom-tech.tistory.com</link>
    </image>
    <item>
      <title>[OS] Lecture 5. Process Scheduling</title>
      <link>https://soom-tech.tistory.com/64</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 스케줄링의 목적&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로세스 스케줄링이란&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 개의 프로세스가 시스템 내 존재&lt;/li&gt;
&lt;li&gt;자원을 할당할 프로세스를 선택 해야 함 &amp;rArr; &lt;code&gt;스케줄링&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;자원 관리
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 분할 관리
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 자원을 여러 스레드들이 번갈아 가며 사용&lt;/li&gt;
&lt;li&gt;예) 프로세서&lt;/li&gt;
&lt;li&gt;프로세스 스케줄링: 프로세서 사용 시간을 프로세스들에게 분배&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;공간 분할 관리
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 자원을 분할하여 동시에 사용&lt;/li&gt;
&lt;li&gt;예) 메모리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스케줄링의 목적&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템의 성능 향상!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대표적인 시스템 성능의 지표
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;응답시간: 작업 요청으로부터 응답을 받을 때까지의 시간 &amp;rarr; 사용자 대화형 시스템, real-time 시스템에 적합&lt;/li&gt;
&lt;li&gt;작업 처리량: 단위 시간 동안 완료된 작업의 수 &amp;rarr; 일괄 처리 시스템&lt;/li&gt;
&lt;li&gt;자원 활용도: 주어진 시간 동안 자원이 활용된 시간&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;목적에 맞는 지표를 고려하여 스케줄링 기법을 선택한다.&lt;/li&gt;
&lt;li&gt;대기시간: 실행 시작까지의 시간&lt;/li&gt;
&lt;li&gt;응답 시간: 첫 번째 출력까지의 시간&lt;/li&gt;
&lt;li&gt;반환 시간: 실행 종료까지의 시간&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 스케줄링 기준 및 단계&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스케줄링의 기준&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스케줄링 기법이 고려하는 항목들&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스의 특성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;I/O Bounded or Compute-Bounded&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;시스템의 특성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Batch System(일괄 처리 시스템) or Interactive System&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;프로세스의 긴급성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Hard, soft real time, non-real time systems&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;프로세스 우선 순위&lt;/li&gt;
&lt;li&gt;프로세스 총 실행 시간&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CPU Burst vs I/O Burst&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스의 수행은 CPU 사용과 I/O 대기의 반복임!&lt;br /&gt;수행 시간을 나타내는 Burst time은 스케줄링의 중요한 기준 중 하나임&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU Burst: CPU 사용 시간 (CPU Burst가 더 긴 경우: Compute Bounded)&lt;/li&gt;
&lt;li&gt;I/O Burst: I/O 대기 시간 (I/O Burst가 더 긴 경우: I/O Bounded)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스케줄링의 단계&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;발생하는 빈도 및 할당 자원에 따른 구분&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Long-term scheduling
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Job scheduling: 시스템에 제출할 작업을 결정한다&lt;/li&gt;
&lt;li&gt;다중 프로그래밍의 정도를 조절한다 (시스템 내에 프로세스 수 조절)&lt;/li&gt;
&lt;li&gt;I/O Bounded와 Compute Bounded 프로세스들을 잘 섞어서 선택해야 함&lt;/li&gt;
&lt;li&gt;시분할 시스템에서는 모든 작업을 시스템에 등록한다 &amp;rarr; Long-term scheduling이 불필요함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Mid-term scheduling
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메모리 할당을 결정 (memory allocation)&lt;/li&gt;
&lt;li&gt;Intermediate-level scheduling&lt;/li&gt;
&lt;li&gt;Swapping (Swap in/Swap out)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Short-term Scheduling
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Process 할당해주는 스케줄링&lt;/li&gt;
&lt;li&gt;Low-level scheduling&lt;/li&gt;
&lt;li&gt;프로세서를 할당할 프로세스를 결정한다.&lt;/li&gt;
&lt;li&gt;가장 빈번하게 발생한다 (interrupt, block, time-out 등)&lt;/li&gt;
&lt;li&gt;매우 빨라야 함 !&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/SSAFY11thDaejeon7/cs_study/assets/110437548/784492fd-a1e1-4c56-a56f-0900fd961885&quot; alt=&quot;스케줄링의단계&quot; width=&quot;650&quot; /&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 스케줄링 정책&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;선점 vs 비선점 (뺏을 수 있는가 없는가?)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Non-preemptive scheduling: 할당 받을 자원을 스스로 반납할 때까지 사용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) System Call, I/O&lt;/li&gt;
&lt;li&gt;장점: context switch overhead가 적음&lt;/li&gt;
&lt;li&gt;단점: 잦은 우선순위 역전, 평균 응답 시간 증가&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;preemptive scheduling: 타의에 의해 자원을 빼앗길 수 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) 할당 시간 종료, 우선순위가 높은 프로세스 등장&lt;/li&gt;
&lt;li&gt;단점: context switch overhead가 큼&lt;/li&gt;
&lt;li&gt;Time-sharing System, real-time System 등에 적합 (응답성이 좋음)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;우선순위&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스의 중요도&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Static priority (정적 우선순위)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스 생성 시 한번 우선순위가 결정되면 유지됨&lt;/li&gt;
&lt;li&gt;구현이 쉽고, overhead가 적음&lt;/li&gt;
&lt;li&gt;시스템 환경 변화에 대한 적응이 어려움&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Dynamic priority (동적 우선순위)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스의 상태 변화에 따라 priority 변경&lt;/li&gt;
&lt;li&gt;구현이 복잡, priority 재계산 overhead가 큼&lt;/li&gt;
&lt;li&gt;시스템 환경 변화에 유연한 대응이 가능하다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 기본 스케줄링 알고리즘&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1) FCFS (First-Come-First-Service)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Non-preemptive scheduling (비선점 스케줄링)&lt;/li&gt;
&lt;li&gt;스케줄링 기준 (criteria)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;도착 시간 (ready queue 기준)&lt;/li&gt;
&lt;li&gt;먼저 도착한 프로세스를 먼저 처리한다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;자원을 효율적으로 사용 가능: High resource utilization / Why?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Batch system (일괄 처리 시스템)에 적합하다 - 들어오는 것에 빨리 응답하는 것보다 퍼포먼스 높이는 게 목적&lt;/li&gt;
&lt;li&gt;interactive system에 부적합 - 반응이 빨리오길 바라는 대화형 시스템에서는 부적합하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;단점:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Convey effect&lt;/b&gt;: 하나의 수행시간이 긴 프로세스에 의해 다른 프로세스들이 긴 대기시간을 가지게 되는 현상 (대기 시간 &amp;gt;&amp;gt; 실행 시간)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;긴 평균 응답시간&lt;/b&gt; (Response time)&lt;img src=&quot;https://github.com/SSAFY11thDaejeon7/cs_study/assets/110437548/d0142454-705e-4859-b99f-66f7be83c640&quot; alt=&quot;FCFS&quot; width=&quot;585&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Process ID&lt;/th&gt;
&lt;th&gt;Arrival time&lt;/th&gt;
&lt;th&gt;Burst Time(BT)&lt;/th&gt;
&lt;th&gt;Waiting Time(WT)&lt;/th&gt;
&lt;th&gt;Turnaround Time(TT)&lt;/th&gt;
&lt;th&gt;Normalized TT (NTT = TT / BT)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;P1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;P2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;9/7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;P3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;9/2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;P4&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;12/5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;P5&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;14/3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2) RR (Round-Robin)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Preemptive scheduling&lt;/li&gt;
&lt;li&gt;스케줄링 기준
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;도착 시간&lt;/li&gt;
&lt;li&gt;먼저 도착한 프로세스를 먼저 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자원 사용 제한 시간 (Time Quantum)이 있음&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;System parameter&lt;/li&gt;
&lt;li&gt;프로세스는 할당된 시간이 지나면 자원 반납&lt;/li&gt;
&lt;li&gt;특정 프로세스의 자원 독점(monopoly)을 방지&lt;/li&gt;
&lt;li&gt;Context Switch overhead가 큼!&lt;/li&gt;
&lt;li&gt;Time Quantum이 끝나면 Ready queue 맨 뒤에 가서 줄을 선다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;대화형, 시분할 시스템에 적합&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Time Quantum이 시스템 성능을 결정하는 핵심 요소&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Very large (infinite) &amp;rarr; FCFS&lt;/li&gt;
&lt;li&gt;Very small time quantum &amp;rarr; processor sharing
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자는 모든 프로세스가 각각의 프로세서 위에서 실행되는 것처럼 느낌&lt;/li&gt;
&lt;li&gt;체감 프로세서 속도 = 실제 프로세서 성능의 1/n&lt;/li&gt;
&lt;li&gt;High context switch overhead&lt;img src=&quot;https://github.com/SSAFY11thDaejeon7/cs_study/assets/110437548/1550eadc-8959-4dfb-bfab-1a3fd3930120&quot; alt=&quot;RR&quot; width=&quot;674&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Process ID&lt;/th&gt;
&lt;th&gt;Arrival time&lt;/th&gt;
&lt;th&gt;Burst Time(BT)&lt;/th&gt;
&lt;th&gt;Waiting Time(WT)&lt;/th&gt;
&lt;th&gt;Turnaround Time(TT)&lt;/th&gt;
&lt;th&gt;Normalized TT (NTT = TT / BT)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;P1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;5 / 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;P2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;18 / 7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;P3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4 / 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;P4&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;15 / 5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;P5&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;12 / 3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(Time Quantum = 2) Average response time(TT) = 10.8..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(Time Quantum = 3) Average response time(TT) = 9.8&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3) SPN (Shortest Process Next)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Non-preemptive scheduling&lt;/li&gt;
&lt;li&gt;스케줄링 기준
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행 시간&lt;/li&gt;
&lt;li&gt;현재 Ready queue내에 Burst time이 가장 작은 프로세스를 먼저 처리&lt;/li&gt;
&lt;li&gt;= SJF(Shortest Job First) scheduling&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;장점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;평균 대기시간을 초기화 할 수 있음&lt;/li&gt;
&lt;li&gt;시스템 내 프로세스 수를 최소화할 수 있음&lt;/li&gt;
&lt;li&gt;스케줄링의 부하도 감소하여 메모리 절약을 하여 시스템 효율이 향상된다.&lt;/li&gt;
&lt;li&gt;많은 프로세스들에게 빠른 응답 시간을 제공할 수 있다!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;단점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Starvation (무한 대기) 현상 발생&lt;/li&gt;
&lt;li&gt;BT가 긴 프로세스는 일찍 wait 상태에 들어가더라도 자원을 할당 받지 못 할 수 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Aging 등으로 해결 (HRRN)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;정확한 실행시간을 알 수 없어 실행시간 예측 기법이 필요하다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4) SRTN (Shortest Remaining Time Next)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SPN의 변형&lt;/li&gt;
&lt;li&gt;Preemptive scheduling&lt;/li&gt;
&lt;li&gt;잔여 실행 시간이 더 적은 프로세스가 Ready 상태가 되면 선점됨&lt;/li&gt;
&lt;li&gt;장점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SPN의 장점 극대화&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;단점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스 생성 시, 총 실행 시간 예측이 필요함&lt;/li&gt;
&lt;li&gt;잔여 실행을 계속 추적해야 함 = overhead 발생&lt;/li&gt;
&lt;li&gt;context switching overhead&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;구현 및 사용이 비현실적이다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5) HRRN (High-Response-Ratio-Next)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SPN의 변형 (Aging을 통해 기아 현상을 막는다)&lt;/li&gt;
&lt;li&gt;non-preemptive scheduling&lt;/li&gt;
&lt;li&gt;Aging Concepts : 프로세스의 대기 시간을 고려하여 기회를 제공 (노약자 배려)&lt;/li&gt;
&lt;li&gt;스케줄링 기준: Response ratio가 높은 프로세스 우선&lt;/li&gt;
&lt;li&gt;Response ratio = (WT+BT/BT) = (waiting time + burst time) / burst time
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SPN의 장점 + Starvation 방지&lt;/li&gt;
&lt;li&gt;실행 시간 예측 기법이 필요하다는 단점이 여전히 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/SSAFY11thDaejeon7/cs_study/assets/110437548/fd921416-ff84-4841-88f2-e4dd4c1e62f0&quot; alt=&quot;summary&quot; width=&quot;796&quot; /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6) MLQ (Multi-level Queue)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;작업 (or 우선순위)별 별도의 ready queue를 가짐
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최초 배정 된 queue를 벗어나지 못함&lt;/li&gt;
&lt;li&gt;각각의 queue는 자신만의 스케줄링 기법을 사용함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Queue 사이에는 우선순위 기반의 스케줄링을 사용한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Fixed-priority preemptive scheduling&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;장점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;빠른 응답 시간&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;단점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 개의 Queue 관리 등 스케줄링 overhead&lt;/li&gt;
&lt;li&gt;우선순위가 낮은 queue는 startvation 현상 발생 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/SSAFY11thDaejeon7/cs_study/assets/110437548/c8c7d65a-5ae5-40f1-9ac0-9e8f8eda159c&quot; alt=&quot;MultiLevelQueue&quot; width=&quot;716&quot; /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;7) MFQ (Multi-level Feedback Queue)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스의 Queue간 이동이 허용된 MLQ (MLQ의 queue 이동 불가 단점 보완)&lt;/li&gt;
&lt;li&gt;Feed back을 통해 우선 순위 조정
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재까지의 프로세서 사용 정보(패턴) 활용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;특성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Dynamic priority: 동적인 우선순위&lt;/li&gt;
&lt;li&gt;Preemptive Scheduling&lt;/li&gt;
&lt;li&gt;Favor short burst-time processes&lt;/li&gt;
&lt;li&gt;Favor I/O bounded processes&lt;/li&gt;
&lt;li&gt;Improve adaptability&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;프로세스에 대한 사전 정보 없이 SPN, SRTN, HRRN 기반의 효과를 볼 수 있음 (BT 예상없이 비슷한 효과!)&lt;img src=&quot;https://github.com/SSAFY11thDaejeon7/cs_study/assets/110437548/04530761-68e9-46b7-97fb-8c6960a80ef1&quot; alt=&quot;MultiLevelFeedbackQueue&quot; width=&quot;752&quot; /&gt;&lt;/li&gt;
&lt;li&gt;단점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설계 및 구현이 복잡하고, 스케줄링의 overhead가 크다&lt;/li&gt;
&lt;li&gt;Starvation 문제등이 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;변형(장점)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 준비 큐마다 시간 할당량을 다르게 배정한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스의 특성에 맞는 형태로 시스템 운영이 가능함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;입출력 위주 프로세스들을 상위 단계로 큐로 이동하여 우선순위를 높인다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스가 block될 때 상위의 준비 큐로 진입하게 함&lt;/li&gt;
&lt;li&gt;시스템 전체의 평균 응답 시간을 줄임&lt;/li&gt;
&lt;li&gt;입출력 작업 분산&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;대기 시간이 지정된 시간을 초과한 프로세스들을 상위 큐로 이동시킨다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;에이징 기법&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS/운영체제</category>
      <author> ruby</author>
      <guid isPermaLink="true">https://soom-tech.tistory.com/64</guid>
      <comments>https://soom-tech.tistory.com/64#entry64comment</comments>
      <pubDate>Wed, 24 Jan 2024 20:59:00 +0900</pubDate>
    </item>
    <item>
      <title>[OS] Lecture 4. Thread Management</title>
      <link>https://soom-tech.tistory.com/63</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. Thread의 정의&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로세스와 스레드&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스: &lt;b&gt;자원&lt;/b&gt;을 할당받고 &lt;b&gt;제어&lt;/b&gt;하여 원하는 작업을 수행하는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스레드란?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;: 코드, 전역 데이터, 힙으로 구성&lt;/li&gt;
&lt;li&gt;: 제어 정보/스택 포인터/지역 데이터/스택을 가지고 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 프로세스 내에 여러 개 존재한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Light Weight Process (LWP: 가벼운 프로세스 / 프로세스의 제어 부분만 가지고 있음)&lt;/li&gt;
&lt;li&gt;프로세서 (e.g CPU) 활용의 기본 단위&lt;/li&gt;
&lt;li&gt;구성 요소
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Thread ID&lt;/li&gt;
&lt;li&gt;Register set(PC, SP 등)&lt;/li&gt;
&lt;li&gt;Stack (i.e. local data)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;제어 요소 외 코드, 데이터 및 &lt;b&gt;자원들은 프로세스 내 다른 스레드들과 공유&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;전통적 프로세스 = 단일 스레드 프로세스&lt;img src=&quot;https://github.com/SSAFY11thDaejeon7/cs_study/assets/110437548/8f2e9337-5d68-4534-9800-cbc60934bbd9&quot; alt=&quot;프로세스와 자원&quot; width=&quot;898&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스레드의 메모리 공간&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/SSAFY11thDaejeon7/cs_study/assets/110437548/32b2db79-7aaa-49a8-abc1-a16ff57ffc6b&quot; alt=&quot;프로세스의 메모리 공간&quot; width=&quot;980&quot; /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스레드의 장점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자 응답성(Responsiveness)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일부 스레드의 처리가 지연되어도, 다른 스레드는 작업을 계속 처리할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;자원 공유(Resource sharing)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자원을 공유해서 효율성 증가 (커널의 개입을 피할 수 있음) &amp;rarr; context switching이 발생하지 않음&lt;/li&gt;
&lt;li&gt;동일 address space에서 스레드가 여러 개 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;경제성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스의 생성, context switch에 비해 효율적&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;멀티 프로세서(multi-processor) 활용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;병렬 처리를 통해 성능을 향상시킴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스레드 사용의 예&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;게임을 수행할때 화면 출력, 사용자 입력, 스피커/마이크 출력 등을 동시에 처리해야 된다. &amp;rarr; 여러 스레드들을 활용&lt;/li&gt;
&lt;li&gt;스레드 간에 게임에 대한 데이터 정보들은 공유한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2) 스레드의 구현&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자 수준 스레도와 커널 수준 스레드로 구혀닝 가능하다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용자 수준 스레드 (User Thread)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;사용자의 영역의 스레드 라이브러리로 구현 됨&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스레드의 생성, 스케줄링 등&lt;/li&gt;
&lt;li&gt;POSIX threads, Win32 threads Java thread API 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;커널은 스레드의 존재를 모른다.&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;커널의 관리 (개입)을 받지 않는다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;생성 및 관리의 부하가 적고 유연한 관리가 가능하다.&lt;/li&gt;
&lt;li&gt;이식성 (Portability)이 높음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;커널은 프로세스 단위로 자원을 할당한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 스레드가 block 상태가 되면, 모든 스레드가 대기한다.&lt;/li&gt;
&lt;li&gt;(single-threaded kernel의 경우)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;여러 개의 사용자 수준 스레드가 하나의 커널 수준 스레드에 일대다 mapping&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;커널 수준 스레드 (Kernel Threads)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;OS가 직접 스레드를 관리함.&lt;/li&gt;
&lt;li&gt;커널 영역에서 스레드의 생성, 관리를 수행함
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Context Switching 등 부하(Overhead)가 큼&lt;/li&gt;
&lt;li&gt;사용자 수준 스레드에 비해 무겁다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;커널이 각 스레드를 개별적으로 관리함
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스 내 스레드들이 병행 수행이 가능하다.&lt;/li&gt;
&lt;li&gt;하나의 스레드가 block 상태가 되어도, 다른 스레드는 계속 작업 수행이 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;하나의 사용자 수준 스레드가 하나의 커널 수준 스레드에 일대일 mapping&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;혼합형 스레드 모델&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;n개 사용자 수준 스레드 - m개의 커널 스레드 (n&amp;gt;m)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자는 원하는 수 만큼 스레드를 사용함.&lt;/li&gt;
&lt;li&gt;커널 스레드는 자신에게 할당된 하나의 사용자 스레드가 block 상태가 되어도, 다른 스레드 수행 가능&lt;/li&gt;
&lt;li&gt;병행 처리 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;효율적이면서 유연함!&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS/운영체제</category>
      <author> ruby</author>
      <guid isPermaLink="true">https://soom-tech.tistory.com/63</guid>
      <comments>https://soom-tech.tistory.com/63#entry63comment</comments>
      <pubDate>Wed, 24 Jan 2024 20:57:49 +0900</pubDate>
    </item>
    <item>
      <title>[OS] Lecture 3. Precess Management</title>
      <link>https://soom-tech.tistory.com/62</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 프로세스의 개념&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;작업(job) / 프로그램(Program) vs 프로세스&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[작업(job) / 프로그램(Program)]&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행 할 프로그램 + 데이터 (우리가 짠 프로그램)&lt;/li&gt;
&lt;li&gt;컴퓨터 시스템에 실행 요청 전의 상태&lt;/li&gt;
&lt;li&gt;Disk에 보관되어 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[프로세스]&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;job이 시스템에 등록된 상태 (메모리를 할당받음)&lt;/li&gt;
&lt;li&gt;실행을 위해 시스템(커널)에 등록된 작업&lt;/li&gt;
&lt;li&gt;시스템 성능 향상을 위해 커널에 의해 관리 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;프로세스의 정의&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행중인 프로그램
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;커널에 등록되고 &lt;b&gt;커널의 관리&lt;/b&gt;하에 있는 작업&lt;/li&gt;
&lt;li&gt;각종 &lt;b&gt;자원들을 요청&lt;/b&gt;하고 할당 받을 수 있는 개체&lt;/li&gt;
&lt;li&gt;프로세스 관리 블록 (&lt;b&gt;PCB&lt;/b&gt;)을 할당 받은 개체&lt;/li&gt;
&lt;li&gt;능동적인 개체(active entity) : 실행 중에 각종 자원을 요구, 할당, 반납하며 진행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;PCB(Process Control Block)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;커널 공간 (kernel space) 내에 존재&lt;/li&gt;
&lt;li&gt;각 프로세스들에 대한 정보를 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;프로세스의 종류&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/SSAFY11thDaejeon7/cs_study/assets/110437548/397317ff-1db3-44af-9216-2824c7fefdee&quot; alt=&quot;프로세스의 종류&quot; width=&quot;999&quot; /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;자원의 개념&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;커널의 관리 하에 프로세스에게 할당/반납 되는 수동적 개체(passive entity)&lt;/li&gt;
&lt;li&gt;자원의 분류
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;H/W resources
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Processor, memory, disk, monitor, keyboard&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;S/W resources
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Message, signal, files, installed SWs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. PCB(Process Control Block)&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;PCB란&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;OS가 프로세스 관리에 필요한 상태 정보를 저장함.&lt;/li&gt;
&lt;li&gt;프로세스 생성 시 생성된다.&lt;/li&gt;
&lt;li&gt;커널에 저장이 된다.&lt;img src=&quot;https://github.com/SSAFY11thDaejeon7/cs_study/assets/110437548/6d9f4925-0d87-4915-b98b-92836ca8b63e&quot; alt=&quot;PCB&quot; width=&quot;816&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;PCB가 관리하는 정보&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PID: Process Identification Number
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스 고유 식별 번호&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;스케줄링 정보
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스 우선순위 등과 같은 스케줄링 관련 정보들&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;프로세스 상태
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자원 할당, 요청 정보 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;메모리 관리 정보
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Page table, segment table 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;입출력 상태 정보
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;할당 받은 입출력 장치, 파일 등에 대한 정보 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;문맥 저장 영역 (context save area)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스의 레지스터 상태를 저장하는 공간 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;계정 정보
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자원 사용 시간 등을 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PCB 정보는 OS 별로 서로 다름&lt;/li&gt;
&lt;li&gt;PCB 참조 및 갱신 속도는 OS의 성능을 결정 짓는 중요한 요소 중 하나임&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 프로세스의 상태 (Process States)&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스는 시스템에 등록된 후, 여러 가지 상태를 거치면서 작업을 수행한다 (&lt;b&gt;자원 간의 상호작용&lt;/b&gt;에 의해 결정)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;프로세스의 상태 및 특성&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/SSAFY11thDaejeon7/cs_study/assets/110437548/773479f6-ab90-4efe-9a3f-796da3681636&quot; alt=&quot;프로세스의 상태 및 특성&quot; width=&quot;935&quot; /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Process State Transition Diagram&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/SSAFY11thDaejeon7/cs_study/assets/110437548/a92e540b-2bac-45cf-a238-548e13f59009&quot; alt=&quot;Process State Transition Diagram&quot; width=&quot;556&quot; /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Active 상태 (메모리 O)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Created State (생성된 상태)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;작업 (job)을 커널에 등록&lt;/li&gt;
&lt;li&gt;PCB 할당 및 프로세스 생성&lt;/li&gt;
&lt;li&gt;커널이 가용 메모리 공간을 체크하고 프로세스 상태를 전이한다. (Ready or Suspended ready)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ready State
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세서 외에 다른 모든 자원을 할당 받은 상태
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메모리를 할당받음&lt;/li&gt;
&lt;li&gt;프로세서(CPU) 할당 대기 상태&lt;/li&gt;
&lt;li&gt;즉시 실행 가능 상태&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Dispatch (or Schedule)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Ready State &amp;rarr; Running State&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Running State
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세서와 필요한 자원을 모두 할당 받은 상태
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Preemption (CPU를 뺏김)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Running State &amp;rarr; Ready State&lt;/li&gt;
&lt;li&gt;프로세서 스케줄링 (ex. time-out, priority changes)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Block/sleep
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Running State &amp;rarr; asleep State&lt;/li&gt;
&lt;li&gt;I/O 등 자원 할당 요청&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Blocked/Asleep State
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세서 외에 다른 자원을 기다리는 상태
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자원 할당은 system call에 의해 이루어짐&lt;/li&gt;
&lt;li&gt;자원마다 따로 큐로 각각 관리함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Wake-up
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Asleep State &amp;rarr; Ready State&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Suspended 상태 (메모리 X)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Suspended State
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메모리를 할당 받지 못한(빼앗긴) 상태
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Memory image를 swap device에 보관&lt;/li&gt;
&lt;li&gt;Memory image: 메모리를 빼앗길때 메모리를 사용하던 상태를 image로 저장한 것&lt;/li&gt;
&lt;li&gt;swap device: 프로그램 정보 저장을 위한 특별한 파일 시스템 (일종의 하드 디스크)&lt;/li&gt;
&lt;li&gt;커널 또는 사용자에 의해 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Swap-out (Suspended), Swap-in (resume)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Terminated/Zombie State
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스 수행이 끝난 상태&lt;/li&gt;
&lt;li&gt;모든 자원 반납 후, 커널 내에 일부 PCB 정보만 남아 있는 상태&lt;/li&gt;
&lt;li&gt;이후 프로세스 관리를 위해 정보를 수집한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 인터럽트 (Interrupt)&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예상치 못한, 외부에서 발생한 이벤트 (Unexpected, external events)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;인터럽트의 종류&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;I/O interrupt: 게임과 같은 프로세스가 예상하지 못한 순간에 마우스 클릭 등을 하면, 이를 알려주는 것&lt;/li&gt;
&lt;li&gt;Clock interrupt&lt;/li&gt;
&lt;li&gt;Console interrupt&lt;/li&gt;
&lt;li&gt;Program check interrupt&lt;/li&gt;
&lt;li&gt;Machine check interrupt&lt;/li&gt;
&lt;li&gt;Inter-process interrupt&lt;/li&gt;
&lt;li&gt;System call interrupt&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;인터럽트 처리 과정&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;인터럽트 발생&lt;/li&gt;
&lt;li&gt;프로세스 중단(커널의 개입)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;context saving 수행 (문맥을 PCB에 저장한다)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인터럽트 처리 (interrupt handling)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터럽트 발생 장소, 원인 파악&lt;/li&gt;
&lt;li&gt;인터럽트 서비스 할 것인지 결정 (어떤 서비스 루틴 호출할 것인지)&lt;/li&gt;
&lt;li&gt;인터럽트 서비스 루틴 호출&lt;/li&gt;
&lt;li&gt;Ready 상태에 있던 프로세스 중 하나에 CPU를 할당한다. (context를 바탕으로 복구한다)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. Context Switching (문맥 교환)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Context
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스와 관련된 정보들의 집합
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU Register context &amp;rArr; in CPU&lt;br /&gt;(CPU가 어떤 프로세스를 처리할 때는 반드시 해당 데이터를 레지스터에 올린다. 그 레지스터에 있는 context)&lt;/li&gt;
&lt;li&gt;Code &amp;amp; Data &amp;amp; Stack &amp;amp; PCB &amp;rArr; in memory&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Context Saving
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 프로세스의 Register context를 저장하는 작업&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Context restoring
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Register context를 프로세스로 복구하는 작업&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Context Switching
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행중인 프로세스의 context를 저장하고, 앞으로 실행할 프로세스의 context를 복구하는 일&lt;/li&gt;
&lt;li&gt;커널의 개입으로 이루어짐&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Context Switch Overhead&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Context switching에 소요되는 비용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;OS마다 다름&lt;/li&gt;
&lt;li&gt;매우 자주 발생함 &amp;rArr; OS의 성능에 큰 영향을 줌&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;불필요한 Context switching을 줄이는 것이 중요하다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex ) &lt;b&gt;스레드&lt;/b&gt;를 활용해서 멀티스레드 프로그래밍을 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS/운영체제</category>
      <author> ruby</author>
      <guid isPermaLink="true">https://soom-tech.tistory.com/62</guid>
      <comments>https://soom-tech.tistory.com/62#entry62comment</comments>
      <pubDate>Sat, 20 Jan 2024 16:35:15 +0900</pubDate>
    </item>
    <item>
      <title>[JAVA] 자바 기초 - 입력받기</title>
      <link>https://soom-tech.tistory.com/61</link>
      <description>&lt;h1&gt;입력받기&lt;/h1&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. nextLine() vs next()&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;nextLine()만 개행 문자(\n)를 기준으로 입력을 받는다.&lt;/li&gt;
&lt;li&gt;next(), nextInt()등은 공백(띄어쓰기, 탭 등)을 기준으로 입력을 받는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;char bloodType = sc.next().charAt(0); 
String info = sc.nextLine(); // nextLine은 줄 넘김 문자가 인식되기 때문에, \r\n이 입력으로 들어온다.


// info에 문자열 입력을 받기 위해서는 다음과 같이 작성
char bloodType = sc.next().charAt(0); 
sc.nextLine();
String info = sc.nextLine();

// 다음과 같이 순서가 바뀌는 것은 가능
String info = sc.nextLine();
char bloodType = sc.next().charAt(0); &lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. BufferedReader&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;알고리즘 풀이를 할 경우에는 Scanner 사용은 시간 초과를 유발할 수 있음! -&amp;gt; Buffered를 사용한다!!&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BufferedReader를 생성할때, 매개변수로 Reader 타입이 들어와야하는데,&lt;/li&gt;
&lt;li&gt;System.in은 InputStream 타입이다.&lt;/li&gt;
&lt;li&gt;=&amp;gt; InputStreamReader (InputStream -&amp;gt; Reader 반환) 사용!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);

// 대부분 다음과 같이 생성과 동시에 사용
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

// BufferedReader를 활용한 한 문장 읽기
String info = br.readLine();&lt;/code&gt;&lt;/pre&gt;</description>
      <author> ruby</author>
      <guid isPermaLink="true">https://soom-tech.tistory.com/61</guid>
      <comments>https://soom-tech.tistory.com/61#entry61comment</comments>
      <pubDate>Thu, 11 Jan 2024 00:26:03 +0900</pubDate>
    </item>
    <item>
      <title>[백준/Swift] 17140 이차원 배열과 연산</title>
      <link>https://soom-tech.tistory.com/59</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  문제 정보&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문제 출처:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;http://boj.kr/&quot;&gt;백준 온라인 저지&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;문제 링크:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://www.acmicpc.net/problem/17140&quot;&gt;17140 이차원 배열과 연산&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;제출 언어: Swift&lt;/li&gt;
&lt;li&gt;알고리즘 분류:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구현&lt;/li&gt;
&lt;li&gt;정렬&lt;/li&gt;
&lt;li&gt;시뮬레이션&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1570&quot; data-origin-height=&quot;1366&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7F4qO/btsjPpf6ttA/1bKu0cijTEj1cxH3gIFpj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7F4qO/btsjPpf6ttA/1bKu0cijTEj1cxH3gIFpj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7F4qO/btsjPpf6ttA/1bKu0cijTEj1cxH3gIFpj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7F4qO%2FbtsjPpf6ttA%2F1bKu0cijTEj1cxH3gIFpj1%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;1570&quot; height=&quot;1366&quot; data-origin-width=&quot;1570&quot; data-origin-height=&quot;1366&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt; ️ 풀이&lt;/h2&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;복잡하지만 문제를 잘 읽고 분석하면 구현할 수 있는 문제이다.&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;주어진 조건&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;행의 개수가 더 많거나 같으면 R 연산, 열의 개수가 더 많은 C 연산 실행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;연산은 각각의 수가 몇 번 나왔는지 구하여서 오름차순 정렬하여 배열에 넣는다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;(우선순위 : 등장 횟수 -&amp;gt; 수) ( 넣는 순서 : 수 , 등장 횟수)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;크기가 커진 곳은 0 으로 채운다, 수 연산 시 0은 무시한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;행 또는 열의 크기가 100 넘어가면 100개 제외한 나머지는 버린다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;A[r][c] == k가 되기 위한 연산의 최소 시간 출력 100초가 지나도 안되면 -1 출력&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;접근 방법&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;1. Dictionary로 등장 횟수 세기&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;연산은 Dictionary에 해당 원소가 등장한 횟수를 저장했다.&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;Swift는 Dictionary 원소에 접근할 때 항상 optional 값으로 반환한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;즉, Dictionary[key] 형태로 접근했을 때 value가 있는 경우 optioanl(value)값, value가 없는 경우 nil값을 반환한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;아래의 코드와 같이 삼항 연산자로 해당 key의 value값이 nil일 경우 1, 아닐 경우 1을 더해줘서 원소의 개수를 count하였다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1686664296223&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dic[num] == nil ? (dic[num] = 1) : (dic[num] = dic[num]! + 1)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;2. dictionary 정렬하기&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;클로저를 매개변수로 넣어서 dictionary를 정렬해주었다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이 또한, 삼항 연산자를 이용하여 우선순위(&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;등장 횟수 -&amp;gt; 수 )&lt;/span&gt;에 맞게 정렬했다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;key가 수이고 value가 등장 횟수이므로 등장횟수가 같다면 수를 오름차순으로, 같지 않다면 등장 횟수를 오름차순으로 정렬했다.&lt;/p&gt;
&lt;pre id=&quot;code_1686664716266&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dic.sorted(by: { $0.value == $1.value ? $0.key &amp;lt; $1.key : $0.value &amp;lt; $1.value})&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #000000; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;3. C 연산&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;R 연산은 2차원 배열을 다루던 방식으로 익숙하게 수행할 수 있었지만, C 연산은 열 기준이므로 세로로 봐야했기에 복잡했다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그래서, tempArr를 만들어 정렬된 결과 배열을 R 연산과 같이 가로로 구한 다음, tempArr의 행과 열을 바꾸어 주었다.&lt;/p&gt;
&lt;pre id=&quot;code_1686665168150&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ex)
// 1 2 3
// 4 5 6
-&amp;gt;
// 1 4
// 2 5
// 3 6&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt; &amp;zwj;  전체 코드&lt;/h2&gt;
&lt;pre id=&quot;code_1686664165561&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let n = readLine()!.split(separator: &quot; &quot;).map{Int(String($0))!}
let (r, c, k) = (n[0], n[1] ,n[2])
var A: [[Int]] = []
for _ in 1...3 {
    A.append(readLine()!.split(separator: &quot; &quot;).map{Int(String($0))!})
}

func operation() -&amp;gt; Int {
    var timer = 0
    while timer &amp;lt;= 100 {
        // 배열의 크기가 원하는 r, c값보다 작아질 경우 index out 방지
        if r-1 &amp;lt; A.count &amp;amp;&amp;amp; c-1 &amp;lt; A[0].count {
            if A[r-1][c-1] == k { return timer }
        }
        // 행의 개수가 같거나 더 많을 경우 R 연산 실행
        if A[0].count &amp;lt;= A.count {
            rOperation()
        }
        // 열의 개수가 더 클경우 C 연산 실행
        else {
            cOperation()
        }
        timer += 1
    }
    return -1
}

// R 연산
func rOperation() {
    var maxLength = 0
    for i in 0..&amp;lt;A.count {
        var dic: [Int:Int] = [:] // 개수 count 딕셔너리
        for num in A[i] {
            if num == 0 { continue } // 0인 경우 개수를 세지 않는다
            dic[num] == nil ? (dic[num] = 1) : (dic[num] = dic[num]! + 1)
        }
        A[i] = []
        // 새로운 배열에 해당 조건으로 정렬한 딕셔너리를 돌며 수, 등장 횟수 순으로 넣어준다
        for (key, value) in dic.sorted(by: { $0.value == $1.value ? $0.key &amp;lt; $1.key : $0.value &amp;lt; $1.value}) {
            if A[i].count &amp;gt;= 100 { break } // 100개 이상일 경우 중단
            A[i].append(contentsOf: [key, value])
        }
        maxLength = max(maxLength, A[i].count)
    }
    // 빈 공간을 0으로 채워주기
    for i in 0..&amp;lt;A.count {
        A[i].append(contentsOf: Array(repeating: 0, count: maxLength - A[i].count))
    }
}
// C 연산
func cOperation() {
    var maxLength = 0
    var tempArr: [[Int]] = Array(repeating: [], count: A[0].count)
    
    for i in 0..&amp;lt;A[0].count {
        var dic: [Int:Int] = [:]
        for j in 0..&amp;lt;A.count {
            if A[j][i] == 0 { continue }
            dic[A[j][i]] == nil ? (dic[A[j][i]] = 1) : (dic[A[j][i]]! = dic[A[j][i]]! + 1)
        }
        // tempArr에 R 연산과 유사하게 하나의 열을 계산한 후, 행 형태로 넣어준다
        for (key, value) in dic.sorted(by: { $0.value == $1.value ? $0.key &amp;lt; $1.key : $0.value &amp;lt; $1.value}) {
            tempArr[i].append(contentsOf: [key, value])
        }
        maxLength = max(maxLength, tempArr[i].count)
    }
    for i in 0..&amp;lt;tempArr.count {
        tempArr[i].append(contentsOf: Array(repeating: 0, count: maxLength - tempArr[i].count))
    }
    
    // 행 -&amp;gt; 열 회전
    A = Array(repeating: [], count: tempArr[0].count)
    for i in 0..&amp;lt;tempArr.count {
        for j in 0..&amp;lt;tempArr[0].count {
            A[j].append(tempArr[i][j])
        }
    }
}
print(operation())&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Algorithm/문제풀이</category>
      <category>구현</category>
      <category>문제풀이</category>
      <category>백준</category>
      <category>시뮬레이션</category>
      <category>정렬</category>
      <author> ruby</author>
      <guid isPermaLink="true">https://soom-tech.tistory.com/59</guid>
      <comments>https://soom-tech.tistory.com/59#entry59comment</comments>
      <pubDate>Tue, 13 Jun 2023 23:07:01 +0900</pubDate>
    </item>
    <item>
      <title>[컴퓨터 네트워크] 응용 계층 - 웹</title>
      <link>https://soom-tech.tistory.com/58</link>
      <description>&lt;h1&gt;1. 웹 서비스&lt;/h1&gt;
&lt;h3&gt;클라이언트 - 서버 모델&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;웹 (WWW→ World Wide Web) 서버의 TCP 포트 번호 80번으로 지정&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL (Uniform Resource Locator)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;웹 서버 지칭&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;프로토콜, 연결하는 서버의 호스트 이름, 서버 내부의 파일 경로명으로 표현&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;https://www.korea.co.kr/welcome.html
프로토콜 이름 / 웹 서버 host 이름 / 서버 내부의 파일 경로명&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;유닉스, 리눅스 시스템에서의 웹 서버 구현&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;http://www.korea.co.kr/~hong
// 로그인 이름 : hong
// 홈 디렉토리 : /public_html/index.html&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;웹 서비스의 동작 원리&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;사용자가 웹 브라우저에 URL 입력&lt;/li&gt;
&lt;li&gt;클라이언트는 서버 호스트 이름을 DNS 서버에 전송하여 서버의 IP주소를 얻음&lt;ul&gt;
&lt;li&gt;DNS 응답 수신 전까지 인터넷이 안됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;IP주소와 Well-known 포트 80번을 이용하여 웹 서버와 TCP 연결(3-hand shake)시도&lt;ul&gt;
&lt;li&gt;해당 목적지 주소로 데이터 패킷을 생성하여 전송&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;TCP연결이 설정되고 클라이언트가 서버에게 GET 명령(html, css등)을 전송&lt;/li&gt;
&lt;li&gt;서버가 클라이언트에게 요청받은 웹 문서 회신&lt;/li&gt;
&lt;li&gt;둘 사이의 TCP 연결 해제&lt;/li&gt;
&lt;li&gt;웹 브라우저는 해당 파일의 내용 사용자가 볼 수 있게끔 화면에 표시&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock left&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;784&quot; data-origin-height=&quot;522&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1zD0C/btsjct3KxDE/OarexM5JDJqDAd01JI4ISK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1zD0C/btsjct3KxDE/OarexM5JDJqDAd01JI4ISK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1zD0C/btsjct3KxDE/OarexM5JDJqDAd01JI4ISK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1zD0C%2Fbtsjct3KxDE%2FOarexM5JDJqDAd01JI4ISK%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;433&quot; height=&quot;288&quot; data-origin-width=&quot;784&quot; data-origin-height=&quot;522&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3&gt;APM의 웹 서비스 구조&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;APM : Apache + PHP + MySQL&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Apache : 웹 서버 프로그램, 계속 80번 포트를 열고 프로세스를 돌림&lt;/li&gt;
&lt;li&gt;PHP&lt;ul&gt;
&lt;li&gt;동적 문서를 생성하는 프로그래밍 언어&lt;/li&gt;
&lt;li&gt;HTML 언어의 기능을 보완하여 문서 내부에 PHP 코드를 추가하는 형식&lt;/li&gt;
&lt;li&gt;모든 종류의 운영체제에서 지원(ASP는 Window에서만 작동)&lt;/li&gt;
&lt;li&gt;공개용 데이터베이스인 MySQL과도 연동이 쉬움&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MySQL : 동적인 부분을 채워줄 데이터베이스&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;APM 관점에서의 웹 서비스의 동작 원리&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;웹 브라우저가 Apache에 웹 문서 요청&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PHP 코드 처리 필요 시 PHP에게 요청&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;데이터베이스 처리 필요 시 MySQL에게 요청&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;데이터베이스 결과 회신&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PHP가 실행 결과인 HTML 코드 회신&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;웹 문서를 웹 브라우저에 회신&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/70D4u/btsjaV0XZLJ/SvinyKla7xFIMRUxnBvvdK/img.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;PHP 코드의 처리&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;HTML 문서 내용의 일부로 작성&lt;/li&gt;
&lt;li&gt;&lt;?, ?&gt; 구분자 사용&lt;/li&gt;
&lt;li&gt;PHP 코드가 포함된 HTML 문서는 확장자가 .php임&lt;/li&gt;
&lt;li&gt;PHP 코드는 서버에서 실행되고 결과만 회신된다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;// 서버에서 작성한 문서
&amp;lt;HTML&amp;gt;
    &amp;lt;BODY&amp;gt;
        &amp;lt;? $value = 10;?&amp;gt;
        출력&amp;lt;br&amp;gt;
        &amp;lt;? echo $value;?&amp;gt;
    &amp;lt;/BODY&amp;gt;
&amp;lt;/HTML&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;// 클라이언트에서 확인되는 문서
&amp;lt;HTML&amp;gt;
    &amp;lt;BODY&amp;gt;
        출력&amp;lt;br&amp;gt;
        10
    &amp;lt;/BODY&amp;gt;
&amp;lt;/HTML&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;2. HTML&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;HTML이란&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HyperText Markup Language로 웹 문서를 작성하는 언어임&lt;/li&gt;
&lt;li&gt;어느 위치에 어떤 데이터를 어떤 모양으로 표시할지 tag등으로 나타냄&lt;/li&gt;
&lt;li&gt;HTML 문서는 웹 서버에 보관됨&lt;/li&gt;
&lt;li&gt;웹 브라우저는 클라이언트에게 HTML 문서를 해석해서 나타냄&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HTML 문서의 구조&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;헤더와 바디로 구성&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;시작 tag와 끝 tag로 감싸는 형식임&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;&amp;lt;HTML&amp;gt;
      &amp;lt;HEAD&amp;gt;
              &amp;lt;TITLE&amp;gt; HTML의 예 &amp;lt;/TITLE&amp;gt;
      &amp;lt;/HEAD&amp;gt;
      &amp;lt;BODY&amp;gt;
              HTML 문서의 내용
      &amp;lt;/BODY&amp;gt;
&amp;lt;HTML&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;3. HTTP&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;HTTP란&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HyperText Transfer Protocol&lt;/li&gt;
&lt;li&gt;웹 문서를 전송하는 프로토콜&lt;/li&gt;
&lt;li&gt;HTTP: TCP 포트 80번 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HTTP의 요청과 응답 (RFC 2616으로 발표된 HTTP 1.1 버전)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;클라이언트의 요청과 서버의 응답에 의해 동작하는 간단한 프로토콜&lt;/li&gt;
&lt;li&gt;동작 원리&lt;ul&gt;
&lt;li&gt;HTTP 클라이언트가 서버에 요청 전송(요청 메서드, URL, HTTP 버전과 기타 부가 정보 포함)&lt;/li&gt;
&lt;li&gt;HTTP 서버가 요청의 결과인 응답 코드가 포함된 정보를 회신&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;비상태 연결&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;요청과 응답 이후, 연결이 끊어지므로 비상태 프로토콜&lt;/li&gt;
&lt;li&gt;state-less protocol&lt;/li&gt;
&lt;li&gt;web 문서가 클 경우 복잡하므로 연결 존재에 따른 상태정보를 저장하지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MIME 유사 메시지&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTTP의 요청 및 응답 메세지는 MIME 유사 구조를 사용해 데이터 전송&lt;/li&gt;
&lt;li&gt;MIME : Multipurpose Internet Message Extensions&lt;/li&gt;
&lt;li&gt;대용량 binary file, ASCII code encoding 가능 등 다양한 메세지를 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;요청&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;요청 메시지 구조&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;| 요청문(Request Line) | &amp;lt;요청 메서드&amp;gt; &amp;lt;URL&amp;gt; &amp;lt;HTTP 버전&amp;gt; (예 GET /file HTTP/1.1)
| 헤더(Header) | &amp;lt;헤더 이름&amp;gt; : &amp;lt;헤더 값&amp;gt; |
| 공백 한 줄 |
| 바디(Body) |&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;요청 메서드: 클라이언트가 서버에 실행을 요구하는 명령&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;요청 메서드의 명령&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;| GET | 클라이언트가 서버에 URL이 가리키는 웹 문서의 내용을 전송하도록 요구
              문서의 내용은 서버가 회신하는 응답 메시지의 바디에 포함 |
| HEAD | 문서 내용보다는 특정 문서의 정보를 원할 때 사용 |
| POST | 클라이언트가 서버에 정보를 전송
              게시판, 방명록과 같이 사용자가 입력한 정보를 서버에 전달하는 용도로 사용 |
| PUT | 클라이언트가 서버에 문서를 전달하려고 사용
              문서 내용은 바디에 포함 |&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;응답&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;응답 메시지 구조&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;| 상태문( Status Line) | &amp;lt;HTTP 버전&amp;gt; &amp;lt;상태 코드&amp;gt; &amp;lt;상태 이름&amp;gt; |
| 헤더 (Header) |
| 공백 한 줄 |
| 바디 (Body) |&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;상태 코드&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;코드&lt;/th&gt;
&lt;th&gt;이름&lt;/th&gt;
&lt;th&gt;의미&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;OK&lt;/td&gt;
&lt;td&gt;요청이 성공적으로 수행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;202&lt;/td&gt;
&lt;td&gt;Accepted&lt;/td&gt;
&lt;td&gt;클라이언트의 요청을 수신하였으나, 즉각 실행되지 않고 있다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;Bad Request&lt;/td&gt;
&lt;td&gt;요청 메시지의 내용에 문법 오류가 존재한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;401&lt;/td&gt;
&lt;td&gt;Unauthorized&lt;/td&gt;
&lt;td&gt;요청을 실행하는 데 필요한 적절한 권한이 존재하지 않는다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;td&gt;Forbidden&lt;/td&gt;
&lt;td&gt;서비스 요청이 거부되었다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;404&lt;/td&gt;
&lt;td&gt;Not Found&lt;/td&gt;
&lt;td&gt;원하는 문서를 찾을 수 없다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;500&lt;/td&gt;
&lt;td&gt;Internal Server Error&lt;/td&gt;
&lt;td&gt;서버 내부에 불가피한 오류가 발생하였다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;501&lt;/td&gt;
&lt;td&gt;Not Implemented&lt;/td&gt;
&lt;td&gt;요청 사항을 수행할 수 없다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HTTP의 동작 과정&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;요청 메시지&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;GET /index.php HTTP/1.1 # 요청문
Host: uu.ac.kr # 헤더
            # 공백 한 줄&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;응답 메시지&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;HTTP/1.1 200 OK                      # 상태문 
Date: Thu, 12, Feb 2023 03:45:32 GMT # 헤더
Server: Apache/1.3.29 ~~
~~
~~
~~
                                  # 공백 한 줄
&amp;lt;HTML&amp;gt;                               # 바디
     &amp;lt;HEAD&amp;gt; 
~~~~
&amp;lt;/HTML&amp;gt; &lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS</category>
      <category>html</category>
      <category>HTTP</category>
      <category>네트워크</category>
      <category>컴퓨터 네트워크</category>
      <author> ruby</author>
      <guid isPermaLink="true">https://soom-tech.tistory.com/58</guid>
      <comments>https://soom-tech.tistory.com/58#entry58comment</comments>
      <pubDate>Fri, 9 Jun 2023 00:38:02 +0900</pubDate>
    </item>
    <item>
      <title>블로그 옮긴 후기 (Gitblog -&amp;gt; tistory)</title>
      <link>https://soom-tech.tistory.com/57</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;개발자를 준비하면서 알고리즘 문제 풀이를 공유하고, 배운 내용을 복습하며 다른 개발자들과 나누고자 2023년 1월부터 깃블로그를 시작했습니다. 아래는 제 이전의 블로그입니다. ⬇️&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://sumin305.github.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://sumin305.github.io/&lt;/a&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초보 개발자 입장에서 Gitblog 사용하는데 불편했던 점들을 나열해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 방문자수, 방문 통계등의 기능이 없다. -&amp;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;3. 깃 폴더가 매우 많아 html, css의 수정이 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 광고 기능/  댓글기능을 넣는 것이 까다롭다.&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;처음 개발 블로그를 만드시는데 어떤 플랫폼을 사용할지 고민이시라면 저는 tistory를 추천합니다    &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;앞으로도 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;열심히 공부한 내용 블로그 포스팅할테니 지켜봐주세요&lt;/span&gt;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;friends1&quot; data-emoticon-name=&quot;002&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/002.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/002.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;</description>
      <category>회고</category>
      <category>gitblog</category>
      <category>TISTORY</category>
      <category>블로그</category>
      <category>블로그 이전</category>
      <category>블로그 추천</category>
      <author> ruby</author>
      <guid isPermaLink="true">https://soom-tech.tistory.com/57</guid>
      <comments>https://soom-tech.tistory.com/57#entry57comment</comments>
      <pubDate>Wed, 7 Jun 2023 18:38:40 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스/Swift] 이모티콘 할인행사</title>
      <link>https://soom-tech.tistory.com/56</link>
      <description>&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;문제 정보&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문제 링크&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1686030443276&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;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/150368&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cWniPL/hySTSN9zH9/dZPLTA5wuz4Fh5sf5BMf6k/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bFXqof/hySTPcO1to/7eJjnBLcB2MRpyKXF0fr8k/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/150368&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/150368&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cWniPL/hySTSN9zH9/dZPLTA5wuz4Fh5sf5BMf6k/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bFXqof/hySTPcO1to/7eJjnBLcB2MRpyKXF0fr8k/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&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;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;제출 언어: Swift&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;알고리즘 분류:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;구현&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #263747; color: #b2c0cc; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;문제 설명&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #263747; color: #b2c0cc; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;카카오톡에서는 이모티콘을 무제한으로 사용할 수 있는 이모티콘 플러스 서비스 가입자 수를 늘리려고 합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;이를 위해 카카오톡에서는 이모티콘 할인 행사를 하는데, 목표는 다음과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #263747; color: #b2c0cc; text-align: left;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;이모티콘 플러스 서비스 가입자를 최대한 늘리는 것.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;이모티콘 판매액을 최대한 늘리는 것.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #263747; color: #b2c0cc; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;b&gt;&lt;u&gt;1번 목표가 우선이며, 2번 목표가 그 다음입니다.&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #263747; color: #b2c0cc; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;이모티콘 할인 행사는 다음과 같은 방식으로 진행됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #263747; color: #b2c0cc; text-align: left;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;n명의 카카오톡 사용자들에게 이모티콘&amp;nbsp;m개를 할인하여 판매합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;이모티콘마다 할인율은 다를 수 있으며, 할인율은 10%, 20%, 30%, 40% 중 하나로 설정됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #263747; color: #b2c0cc; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;카카오톡 사용자들은 다음과 같은 기준을 따라 이모티콘을 사거나, 이모티콘 플러스 서비스에 가입합니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #263747; color: #b2c0cc; text-align: left;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;각 사용자들은 자신의 기준에 따라 일정 비율 이상 할인하는 이모티콘을 모두 구매합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;각 사용자들은 자신의 기준에 따라 이모티콘 구매 비용의 합이 일정 가격 이상이 된다면, 이모티콘 구매를 모두 취소하고 이모티콘 플러스 서비스에 가입합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #263747; color: #b2c0cc; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;다음은 2명의 카카오톡 사용자와 2개의 이모티콘이 있을때의 예시입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;사용자비율가격&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #263747; color: #b2c0cc; text-align: left; border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody style=&quot;color: #000000;&quot;&gt;
&lt;tr style=&quot;color: #000000;&quot;&gt;
&lt;td style=&quot;background-color: #202b3d; color: #000000;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;1&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #202b3d; color: #000000;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;40&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #202b3d; color: #000000;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;10,000&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;color: #000000;&quot;&gt;
&lt;td style=&quot;background-color: #202b3d; color: #000000;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;2&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #202b3d; color: #000000;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;25&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #202b3d; color: #000000;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;10,000&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;이모티콘가격&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #263747; color: #b2c0cc; text-align: left; border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody style=&quot;color: #000000;&quot;&gt;
&lt;tr style=&quot;color: #000000;&quot;&gt;
&lt;td style=&quot;background-color: #202b3d; color: #000000;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;1&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #202b3d; color: #000000;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;7,000&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;color: #000000;&quot;&gt;
&lt;td style=&quot;background-color: #202b3d; color: #000000;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;2&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #202b3d; color: #000000;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;9,000&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;background-color: #263747; color: #b2c0cc; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;1번 사용자는 40%이상 할인하는 이모티콘을 모두 구매하고, 이모티콘 구매 비용이 10,000원 이상이 되면 이모티콘 구매를 모두 취소하고 이모티콘 플러스 서비스에 가입합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;2번 사용자는 25%이상 할인하는 이모티콘을 모두 구매하고, 이모티콘 구매 비용이 10,000원 이상이 되면 이모티콘 구매를 모두 취소하고 이모티콘 플러스 서비스에 가입합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #263747; color: #b2c0cc; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;1번 이모티콘의 가격은 7,000원, 2번 이모티콘의 가격은 9,000원입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #263747; color: #b2c0cc; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;만약, 2개의 이모티콘을 모두 40%씩 할인한다면, 1번 사용자와 2번 사용자 모두 1,2번 이모티콘을 구매하게 되고, 결과는 다음과 같습니다&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; 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) 이모티콘 할인율 조합하기&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;3) 이모티콘 플러스 가입자 -&amp;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;&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;이모티콘마다 각자 다른 할인율을 가지게 하기 위해 이모티콘 할인율을 조합하는 방법은 재귀함수를 사용하였다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'var candidateRates: [[Int]] = []' 이 2차원 배열을 생성하여 할인율을 조합하는 후보들을 다 담아주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;할인율은 10,20,30,40 이렇게 4가지이고, 총 이모티콘 개수을 n개라고 하면 중복을 허락하기 때문에 4^n의 후보들이 나올 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;for문으로 할인율 4개에 해당하는 값들을 넣어주었고 할인율 조합이 이모티콘 개수와 같아졌을 때 candidateRates에 후보를 append해주고 재귀를 종료시켰다.&lt;/p&gt;
&lt;pre id=&quot;code_1686031436490&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let discountRate = [10, 20, 30, 40]
var candidateRates: [[Int]] = []

 // 이모티콘의 할인율 조합이 되는 경우의 수 모두 candidateRates 배열에 넣기
func makeCases(_ arr: [Int]) {
    if arr.count == emoticons.count {
        candidateRates.append(arr)
        return
    }
    for i in 0..&amp;lt;4 {
        var tempArr = arr
        tempArr.append(discountRate[i])
        makeCases(tempArr)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 각 할인율 후보들마다 이모티콘 플러스 가입자수 &amp;amp; 총 매출 계산하기&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;&amp;nbsp;&lt;/span&gt;for문을 돌면서&amp;nbsp;&lt;/span&gt;각 할인율 후보들의 각 유저들의 이모티콘 플러스 가입여부를 계산해준다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유저가 원하는 할인율의 이모티콘의 할인가들을 다 더해서,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유저의 일정 금액을 넘을 경우 이모티콘 플러스 가입자의 수 += 1&lt;/li&gt;
&lt;li&gt;넘지 않을 경우 각 할인율의 총 매출에 해당 금액을 더해준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1686032639751&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; // 각 할인율 후보들마다 이모티콘 플러스 가입자수와 전체 매출을 계산하고 최댓값을 갱신해준다
    for candidateRate in candidateRates {
        var plusServiceUsers = 0
        var totalSales = 0
        for user in users {
            var tempSales = 0
            for idx in 0..&amp;lt;candidateRate.count {
                if candidateRate[idx] &amp;gt;= user[0] {
                    tempSales += emoticons[idx] - (emoticons[idx] * candidateRate[idx] / 100)
                }
            }
            if tempSales &amp;gt;= user[1] {
                plusServiceUsers += 1
            } else {
                totalSales += tempSales
            }
        }&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; 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;'var result: [Int] = [0, 0]'를 초기값으로 두고&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;result[0] 값보다 현재 할인율 조합의 이모티콘 플러스 가입자수가 많을 경우&lt;/li&gt;
&lt;li&gt;result[0] 값과 이모티콘 플러스 가입자수가 같으면서 result[1] 값보다 현재 할인율 조합의 총 매출액이 높은 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 경우에 result값을 갱신해주었다.&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;전체 코드&lt;/h2&gt;
&lt;pre id=&quot;code_1686030417796&quot; class=&quot;swift&quot; style=&quot;background-color: #fafafa; color: #000000; text-align: start;&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import Foundation
func solution(_ users:[[Int]], _ emoticons:[Int]) -&amp;gt; [Int] {
    let discountRate = [10, 20, 30, 40]
    var candidateRates: [[Int]] = []
    var result: [Int] = [0, 0]
    
    // 이모티콘의 할인율 조합이 되는 경우의 수 모두 candidateRates 배열에 넣기
    func makeCases(_ arr: [Int]) {
        if arr.count == emoticons.count {
            candidateRates.append(arr)
            return
        }
        for i in 0..&amp;lt;4 {
            var tempArr = arr
            tempArr.append(discountRate[i])
            makeCases(tempArr)
        }
    }
    
    makeCases([])
    
    // 각 할인율 후보들마다 이모티콘 플러스 가입자수와 전체 매출을 계산하고 최댓값을 갱신해준다
    for candidateRate in candidateRates {
        var plusServiceUsers = 0
        var totalSales = 0
        for user in users {
            var tempSales = 0
            for idx in 0..&amp;lt;candidateRate.count {
                if candidateRate[idx] &amp;gt;= user[0] {
                    tempSales += emoticons[idx] - (emoticons[idx] * candidateRate[idx] / 100)
                }
            }
            if tempSales &amp;gt;= user[1] {
                plusServiceUsers += 1
            } else {
                totalSales += tempSales
            }
        }
        
        // 1순위: 이모티콘 플러스 가입자수, 2순위: 전체 매출
        if result[0] == plusServiceUsers {
            if result[1] &amp;lt; totalSales {
                result = [plusServiceUsers, totalSales]
            }
        } else if result[0] &amp;lt; plusServiceUsers {
            result = [plusServiceUsers, totalSales]
        }
    }
    return result
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Algorithm/문제풀이</category>
      <category>구현</category>
      <category>문제풀이</category>
      <category>카카오</category>
      <category>프로그래머스</category>
      <author> ruby</author>
      <guid isPermaLink="true">https://soom-tech.tistory.com/56</guid>
      <comments>https://soom-tech.tistory.com/56#entry56comment</comments>
      <pubDate>Tue, 6 Jun 2023 14:46:34 +0900</pubDate>
    </item>
    <item>
      <title>[백준/Swift] 16953 A -&amp;gt; B</title>
      <link>https://soom-tech.tistory.com/55</link>
      <description>&lt;h2&gt;문제 정보&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;문제 출처: &lt;a href=&quot;http://boj.kr/&quot;&gt;백준 온라인 저지&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;문제 링크: &lt;a href=&quot;https://www.acmicpc.net/problem/16953&quot;&gt;16953 A -&amp;gt; B&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;제출 언어: Swift&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;알고리즘 분류:    &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;그래프 이론&lt;/li&gt;
&lt;li&gt;그리디 알고리즘&lt;/li&gt;
&lt;li&gt;그래프 탐색&lt;/li&gt;
&lt;li&gt;너비 우선 탐색&lt;/li&gt;
&lt;/ul&gt;
&lt;br&gt;   

&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/110437548/226524103-cf1b0ca4-c351-4594-9197-3f021e2d72d7.png&quot; alt=&quot;image&quot;&gt;      &lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;풀이&lt;/h2&gt;
&lt;p&gt;숫자 A에서 B로 만드려면 2를 곱하기와 맨 뒷 자리에 1 붙이기를 반복해야 한다. 만약 예를 들어 2부터 시작한다면, 4와 21로 만들 수 있고,&lt;br&gt;또 4로는 8과 41, 21로는 42와 211을 만들 수 있다. 하나의 숫자로 두 개의 수를 만들 수 있으므로 다음과 같은 피라미드 형태의 수열이 생긴다.  &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/110437548/226524492-8cb97458-87fe-4ff8-8651-e1770b05526b.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;우리가 구하려는 것은 필요한 연산의 최솟값이므로 BFS로 Depth별로 탐색하여,&lt;br&gt;B의 숫자에 도달하면 해당 Depth를 반환하고, 도달하지 못하는 경우 -1을 반환하는 알고리즘을 작성하였다 &lt;/p&gt;
&lt;h3&gt;BFS 적용&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;먼저 처음 숫자인 A를 queue에 넣은 다음 queue에 원소가 없어질 때까지 queue의 가장 앞 부분을 target으로 꺼내서 2를 곱한 값과, 1을 뒤에 붙인 값을 queue에 넣어준다&lt;/li&gt;
&lt;li&gt;만약 target값이 B가 되었다면 해당 Depth를 반환한다&lt;/li&gt;
&lt;li&gt;만약 target값이 B를 넘겼다면 더 이상 연산해줄 필요가 없어지므로 continue한다&lt;/li&gt;
&lt;li&gt;B에 도달했을 때의 최종 Depth를 구하기 위해서 queue에 연산한 값과 함께 depth + 1값을 계속 넣어준다&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;전체 코드&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;import Foundation

let n = readLine()!.split(separator: &amp;quot; &amp;quot;).map{Int(String($0))!}
let (A,B) = (n[0], n[1])
func makeNum(_ A: Int, _ B: Int) -&amp;gt; Int {
    var queue: [(num: Int,count: Int)] = [(A, 1)]
    while !queue.isEmpty {
        let target = queue.removeLast()
        if target.num == B {
            return target.count
        }
        if target.num &amp;gt; B {
            continue
        }
        queue.append(((target.num * 10 + 1), target.count + 1))
        queue.append((target.num*2, target.count + 1))
    }
    return -1
}
print(makeNum(A, B))&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Algorithm/문제풀이</category>
      <category>BFS</category>
      <category>dfs</category>
      <category>문제풀이</category>
      <category>백준</category>
      <category>알고리즘</category>
      <author> ruby</author>
      <guid isPermaLink="true">https://soom-tech.tistory.com/55</guid>
      <comments>https://soom-tech.tistory.com/55#entry55comment</comments>
      <pubDate>Tue, 6 Jun 2023 01:00:11 +0900</pubDate>
    </item>
    <item>
      <title>[백준/Swift] 2606 바이러스</title>
      <link>https://soom-tech.tistory.com/54</link>
      <description>&lt;h2&gt;문제 정보&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;문제 출처: &lt;a href=&quot;http://boj.kr/&quot;&gt;백준 온라인 저지&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;문제 링크: &lt;a href=&quot;https://www.acmicpc.net/problem/2606&quot;&gt;2606 바이러스&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;제출 언어: Swift&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;알고리즘 분류:    &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;그래프 이론&lt;/li&gt;
&lt;li&gt;그래프 탐색&lt;/li&gt;
&lt;li&gt;너비 우선 탐색&lt;/li&gt;
&lt;/ul&gt;
&lt;br&gt;
&lt;img width=&quot;869&quot; alt=&quot;image&quot; src=&quot;https://user-images.githubusercontent.com/110437548/225836250-1418bf38-6b9a-402e-804e-2f279f73c38a.png&quot;&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;풀이&lt;/h2&gt;
&lt;p&gt;해당 문제는 그래프에서 쌍방향으로 연결되어 있는 노드의 개수를 카운트하는 것으로 이해하였다&lt;br&gt;나는 이 문제를 BFS(Breadth-First-Search)를 이용하여 풀이하였다&lt;br&gt;DFS로도 풀 수 있는 문제였지만 점진적으로 퍼져가는 바이러스를 시각적으로 표현하기에는 BFS가 적당할 것 같았다&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;for i in 0..&amp;lt;M {
    let a = readLine()!.split(separator: &amp;quot; &amp;quot;).map{Int(String($0))!}
    lst[a[0]].append(a[1])
}
visited[1] = true
while !queue.isEmpty {
    let target = queue.removeFirst()
    for node in lst[target] {
        if !visited[node] {
            queue.append(node)
            visited[node] = true
            count += 1
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;처음 틀린 풀이에서는 쌍방향이라는 것을 고려하지 못하고 &lt;code&gt;1 2&lt;/code&gt;가 들어오면 배열 index 1에 2를 넣어주는 방식으로 접근하여&lt;br&gt;queue에서 하나씩 꺼내 아직 방문하지 않은 해당 index에 있는 배열의 원소값을 queue에 다시 넣는 방식으로 진행하였다&lt;br&gt;이런 식으로 풀이를 할 경우 주어진 입력 데이터에서 정상적으로 작동하지만 단방향으로만 그래프 탐색이 작동하여 다음과 같은 반례가 존재하였다      &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;6
5
6 5
5 4
4 3
3 2
2 1
-&amp;gt; count = 0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;분명히 컴퓨터들은 쌍방향 연결이지만, 내가 직전에 짠 코드는 앞에 써져 있는 숫자의 컴퓨터가 뒤에 써져 있는 숫자의 컴퓨터로 바이러스가 퍼지는 경우만 고려하였다&lt;br&gt;그러므로 다음과 같이 코드를 변경해주었다&lt;br&gt;단순히 반대방향으로의 경우도 배열에 넣어줌으로 해결될 수 있었던 이유는 vistied배열이 작동하기 때문이다     &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;for i in 0..&amp;lt;M {
    let a = readLine()!.split(separator: &amp;quot; &amp;quot;).map{Int(String($0))!}
    //양방향 그래프 처리
    lst[a[0]].append(a[1])
    lst[a[1]].append(a[0])
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이번 문제를 통해서 단방향, 쌍방향 그래프의 구분을 할 수 있게 되었고&lt;br&gt;BFS 문제를 항상 풀던 방식이 아닌 다른 방식으로 풀 수 있었다    &lt;/p&gt;
&lt;h2&gt;전체 코드&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;import Foundation
let N = Int(readLine()!)!
let M = Int(readLine()!)!
var lst: [[Int]] = Array(repeating: [], count: N+1)
var visited: [Bool] = Array(repeating: false, count: N+1)
//1번 컴퓨터부터 바이러스가 퍼지기 시작함
var queue: [Int] = [1]
var count = 0
for i in 0..&amp;lt;M {
    let a = readLine()!.split(separator: &amp;quot; &amp;quot;).map{Int(String($0))!}
    //양방향 그래프 처리
    lst[a[0]].append(a[1])
    lst[a[1]].append(a[0])
}
visited[1] = true
while !queue.isEmpty {
    let target = queue.removeFirst()
    //queue에서 꺼낸 컴퓨터와 연결된 컴퓨터 찾음
    for com in lst[target] {
        //아직 방문하지 않은 노드일경우
        if !visited[com] {
            queue.append(com)
            visited[com] = true
            count += 1
        }
    }
}
print(count)&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Algorithm/문제풀이</category>
      <category>BFS</category>
      <category>dfs</category>
      <category>그래프 탐색</category>
      <category>문제풀이</category>
      <category>백준</category>
      <category>알고리즘</category>
      <author> ruby</author>
      <guid isPermaLink="true">https://soom-tech.tistory.com/54</guid>
      <comments>https://soom-tech.tistory.com/54#entry54comment</comments>
      <pubDate>Tue, 6 Jun 2023 00:58:03 +0900</pubDate>
    </item>
  </channel>
</rss>