<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>sungeun_yyy.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Fri, 11 Oct 2024 00:41:01 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>sungeun_yyy.log</title>
            <url>https://velog.velcdn.com/images/sungeun_yyy/profile/8708b887-37c5-4b40-9961-e930aff68406/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. sungeun_yyy.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/sungeun_yyy" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Swift Concurrency 공식문서]]></title>
            <link>https://velog.io/@sungeun_yyy/Concurrency</link>
            <guid>https://velog.io/@sungeun_yyy/Concurrency</guid>
            <pubDate>Fri, 11 Oct 2024 00:41:01 GMT</pubDate>
            <description><![CDATA[<h1 id="동시성">동시성</h1>
<p>비동기: </p>
<p>병렬: 동시에 여러부분이 실행됨</p>
<ul>
<li><p><strong>동기 vs 비동기</strong></p>
<ul>
<li>&quot;시간 흐름/기다림&quot; 관점: 하나의 작업 단위 처리시 “기다리는가”</li>
</ul>
</li>
<li><p><strong>직렬 vs 동시(하나일 수도) vs 병렬(멀티코어)</strong></p>
<ul>
<li>&quot;처리 구조/실행 방식&quot; 관점: 여러 작업이 있을 때 “어떻게 처리되는가”</li>
</ul>
</li>
<li><p><em>동시성</em> 이라는 용어를 사용하여 비동기와 병렬 코드의 일반적인 조합을 나타냄</p>
</li>
</ul>
<h2 id="비동기-함수-정의와-호출">비동기 함수 정의와 호출</h2>
<p><strong>비동기함수</strong></p>
<ul>
<li>”완료될 때까지 실행되거나/ 오류가 발생하거나/ 반환되지않거나”하는 실행 도중에 일시적으로 중단될 수 있는 특수한 함수</li>
<li>파라미터 뒤에, → 전에, <code>throws</code>전에 <code>async</code> 키워드 작성</li>
</ul>
<pre><code class="language-swift">func listPhotos(inGallery name: String) async -&gt; [String] {
    let result = // ... some asynchronous networking code ...
    return result
}</code></pre>
<ul>
<li><p>비동기함수 호출시 중단 가능성 지점을 <code>await</code>으로 표시</p>
</li>
<li><p>Swift 가 <code>await</code>을 만나면 현재 쓰레드에서 코드의 실행을 일시 중단하고 대신 해당 쓰레드에서 다른 코드를 실행하기 때문에 이것을 <em>쓰레드 양보 (yielding the thread)</em> 라고함</p>
</li>
<li><p>실행을 일시 중단할 수 있어야 하므로 프로그램의 특정 위치에서만 비동기 함수나 메서드를 호출할 수 있음</p>
<ul>
<li><p>비동기 함수, 메서드 또는 프로퍼티의 본문에 있는 코드</p>
</li>
<li><p><code>@main</code> 으로 표시된 구조체, 클래스, 또는 열거형의 정적 (static) <code>main()</code> 메서드에 있는 코드</p>
</li>
<li><p>구조화되지 않은 하위 작업의 코드</p>
<ul>
<li><p><code>Task.yeilde()</code> : 명시적으로 중단 지점 추가</p>
</li>
<li><p><code>Task.sleep(for:tolerance:clock:)</code>: 주어진 시간만큼 현재 작업 중단</p>
<pre><code class="language-swift">  func listPhotos(inGallery name: String) async throws -&gt; [String] {
      try await Task.sleep(for: .seconds(2))
      return [&quot;IMG001&quot;, &quot;IMG99&quot;, &quot;IMG0404&quot;]
  }</code></pre>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><strong>비동기 함수와 던지는 함수의 비교</strong></p>
<ul>
<li>공통점<ul>
<li>표현방식 유사(<code>async</code>/<code>await</code>, <code>throws</code>/<code>try</code>)</li>
<li>비동기 함수는 다른 비동기 함수를, 던지는 함수는 다른 던지는 함수를 내부에서 호출할 수 있음</li>
</ul>
</li>
<li>차이점<ul>
<li>던지는 함수는 <strong><code>Result</code> 타입</strong>이나 <strong><code>do-catch</code> 블록</strong>을 이용해 <strong>동기 코드에서도 호출 가능</strong></li>
<li>비동기 함수는 반드시 <code>await</code>로 호출해야 하며, 동기 코드에서는 호출 불가능(구현시 하면 race condition, 데드락 등 문제 발생)</li>
</ul>
</li>
<li><code>throws</code>는 동기 코드에서도 유연하게 처리 가능 (<code>Result</code>, <code>do-catch</code>)</li>
<li><code>async</code>는 무조건 비동기 흐름 안에서만 실행 가능</li>
<li>비동기 도입은 <strong>코드 구조를 재설계해야 하는 일</strong>, 작은 단위부터 위로가 아닌 <strong>최상위부터 아래로(top-down)</strong> 진행해야 함</li>
</ul>
<h2 id="비동기-시퀀스asynchronous-sequences">비동기 시퀀스<strong>(Asynchronous Sequences)</strong></h2>
<ul>
<li><p><code>for</code>-<code>await</code>-<code>in</code> 루프는 다음 요소를 사용할 수 있을 때까지 기다리고 각 반복이 시작될 때 잠재적으로 실행을 일시 중단함</p>
<pre><code class="language-swift">  import Foundation

  let handle = FileHandle.standardInput
  for try await line in handle.bytes.lines {
      print(line)
  }</code></pre>
</li>
</ul>
<h2 id="비동기-함수-병렬로-호출-calling-asynchronous-functions-in-parallel"><strong>비동기 함수 병렬로 호출 (Calling Asynchronous Functions in Parallel)</strong></h2>
<ul>
<li><p>비동기 함수를 호출하고 주변의 코드와 병렬로 실행시 상수를 정의할 때 <code>let</code> 앞에 <code>async</code> 를 작성하고 상수를 사용할 때마다 <code>await</code> 를 작성함</p>
<pre><code class="language-swift">  async let firstPhoto = downloadPhoto(named: photoNames[0])
  async let secondPhoto = downloadPhoto(named: photoNames[1])
  async let thirdPhoto = downloadPhoto(named: photoNames[2])

  let photos = await [firstPhoto, secondPhoto, thirdPhoto]
  show(photos)</code></pre>
</li>
</ul>
<h2 id="task-task-groups">Task/ Task Groups</h2>
<ul>
<li><strong><em>작업 (task):</em></strong> 프로그램의 일부로 비동기적으로 실행할 수 있는 작업 단위</li>
<li>작업은 <strong>자기 자신은 한 번에 하나의 일만 처리</strong>하지만, 여러 개의 작업을 동시에 만들면 Swift가 이를 <strong>자동으로 병렬 실행</strong>하도록 스케줄링함</li>
</ul>
<h3 id="async-let-vs-taskgroup">async let vs TaskGroup</h3>
<p><strong>async let</strong></p>
<ul>
<li><strong>정해진 수의 작업을 동시에 실행</strong>할 때 유용</li>
<li>컴파일러가 자동으로 하위 작업을 생성</li>
<li>예: 몇 개의 이미지 다운로드를 병렬 처리</li>
</ul>
<p><strong>TaskGroup</strong></p>
<ul>
<li><strong>작업 수가 동적일 때</strong> 적합 (for문 등에서 반복적으로 작업을 추가할 때)</li>
<li><strong>우선순위, 취소, 결과 누적 등을 제어할 수 있음</strong></li>
<li>명시적으로 하위 작업을 추가하고 관리 가능</li>
</ul>
<h3 id="작업-취소-task-cancellation"><strong>작업 취소 (Task Cancellation)</strong></h3>
<ul>
<li>Swift Concurrency는 협동 취소 모델(cooperative cancellation model)을 사용함</li>
<li><strong>작업</strong>(task)이 스스로 “취소되었는지”를<strong>확인하고 대응하는 방식</strong></li>
</ul>
<p><strong>취소의 응답방식</strong></p>
<ul>
<li><code>CancellationError</code>를 던짐 (에러 전파)</li>
<li><code>nil</code>이나 빈 배열 반환 (부분적인 결과)</li>
<li>완료된 작업만 반환 (진행 중이던 건 무시)</li>
</ul>
<p><strong>취소여부 확인 방법</strong></p>
<ul>
<li><code>checkCancellation()</code>은 취소 시 에러로 처리 (간단)</li>
<li><code>isCancelled</code>은 <strong>조건문으로 유연하게</strong> 대응 가능 (예: 정리, 로그, 반환값 조절 등)</li>
</ul>
<p><strong>취소 핸들러 사용(즉시반응 필요시)</strong></p>
<ul>
<li><a href="https://developer.apple.com/documentation/swift/withtaskcancellationhandler(operation:oncancel:isolation:)"><code>Task.withTaskCancellationHandler(operation:onCancel:isolation:)</code></a>메서드를 사용</li>
<li><strong>취소 타이밍</strong>과 작업 실행 중 <strong>상태 공유</strong>에는 주의가 필요(경쟁 조건 가능성 있음)</li>
</ul>
<pre><code class="language-swift">let task = await Task.withTaskCancellationHandler {
    // ...
} onCancel: {
    print(&quot;Canceled!&quot;)
}

// ... some time later...
task.cancel()  // Prints &quot;Canceled!&quot;</code></pre>
<h2 id="구조화-되지-않은-동시성">구조화 되지 않은 동시성</h2>
<ul>
<li><strong>상위 작업과 관계 없이 동작해야 할 때</strong></li>
<li><strong>UI 바깥 또는 독립된 비동기 흐름이 필요할 때</strong></li>
<li>예: <strong>알림 전송</strong>, <strong>백그라운드 로깅</strong>, <strong>앱 외부 이벤트 대응</strong></li>
<li><code>Task {}</code>를 사용해 <strong>현재 컨텍스트에서 독립적으로</strong> 작업 생성</li>
<li><code>Task.detached {}</code>는 <strong>현재 actor나 context와 완전히 분리된 작업</strong> 생성</li>
</ul>
<h2 id="액터actors">액터(Actors)</h2>
<ul>
<li><p>동시성 환경에서 <strong>안전하게 상태를 보호하면서 데이터를 공유</strong>하기 위한 Swift의 구조</p>
</li>
<li><p>클래스처럼 생겼지만, “한 번에 하나의 작업만 상태를 바꿀 수 있게 해주는 참조 타입”</p>
</li>
<li><p>액터 외부 접근은 <code>await</code> 필요</p>
<ul>
<li><p>이유: 액터는 격리된 상태를 가지며, 외부 접근 시에는 <strong>비동기 중단점</strong>을 통해 조정해야 함</p>
<pre><code class="language-swift">let logger = TemperatureLogger(label: &quot;Outdoors&quot;, measurement: 25)
print(await logger.max)  // ✅ OK
print(logger.max)        // ❌ 컴파일 에러
</code></pre>
</li>
</ul>
</li>
<li><p>액터 내부 코드는 <code>await</code> 없이도 안전하게 실행</p>
<ul>
<li><strong>중단 지점이 없기 때문에</strong> 실행 중간에 다른 코드가 끼어들 수 없음</li>
</ul>
</li>
</ul>
<h2 id="전송-가능-타입-sendable-types">전송 가능 타입 (Sendable Types)</h2>
<ul>
<li><strong>Sendable</strong>은 Swift에서 <strong>동시성 도메인(concurrency domain)</strong> 간에 데이터를 <strong>안전하게 주고받을 수 있음을 나타내는 프로토콜</strong><ul>
<li>작업(Task)이나 액터(Actor) 내부는 <strong>서로 다른 동시성 환경</strong></li>
<li>어떤 데이터를 이들 사이에서 주고받을 때, 해당 타입이 안전한지 보장해야함</li>
<li><strong>Sendable을 만족하는 타입</strong>만이 <strong>동시성 도메인 간 전송 가능함</strong></li>
<li></li>
</ul>
</li>
</ul>
<p><strong>필요성</strong></p>
<ul>
<li>Swift에서는 여러 작업/스레드가 동시에 데이터를 읽고 쓸 수 있음</li>
<li>만약 <strong>상태 보호 없이 공유</strong>하면 <strong>race condition, memory corruption, 예측 불가능한 버그</strong> 발생 가능</li>
<li>따라서 <strong>안전한 타입만 공유할 수 있도록 명시적으로 제한</strong>→ Sendable의 역할</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>