<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>iOYES</title>
    <link>https://green1229.tistory.com/</link>
    <description>Green is Green </description>
    <language>ko</language>
    <pubDate>Tue, 25 Aug 2026 10:58:09 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>GREEN.1229</managingEditor>
    <image>
      <title>iOYES</title>
      <url>https://tistory1.daumcdn.net/tistory/4326025/attach/5dc0ba3d4d3c460d8c291fa6a8cfb2d1</url>
      <link>https://green1229.tistory.com</link>
    </image>
    <item>
      <title>[SE-0538] Disconnected</title>
      <link>https://green1229.tistory.com/634</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;안녕하세요. &lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;그린&lt;/b&gt;&lt;/span&gt;입니다  &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이번 포스팅에서는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;SE-0538 &amp;mdash; Disconnected&lt;/b&gt;&lt;/span&gt;에 대해 정리해보겠습니다  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;daf.001.jpeg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boXVpZ/dJMcaikbwB3/RfjEYMeDOuUcniriMKVls0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boXVpZ/dJMcaikbwB3/RfjEYMeDOuUcniriMKVls0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boXVpZ/dJMcaikbwB3/RfjEYMeDOuUcniriMKVls0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboXVpZ%2FdJMcaikbwB3%2FRfjEYMeDOuUcniriMKVls0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;400&quot; data-filename=&quot;daf.001.jpeg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Intro&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;div style=&quot;background: #f2f8ee; border-radius: 10px; padding: 16px 20px; margin: 16px 0;&quot;&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;Proposal:&lt;/b&gt; SE-0538&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;Author:&lt;/b&gt; Franz Busch&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;Review Manager:&lt;/b&gt; Holly Borla&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;Status:&lt;/b&gt; Active review (July 17 - July 31, 2026)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;Implementation:&lt;/b&gt; swiftlang/swift#89597&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0414-region-based-isolation.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SE-0414&lt;/a&gt;는 control flow 기반 진단을 활용해서 non-Sendable 값을 isolation 경계 너머로 안전하게 보낼 수 있는지 판단하는 region-based isolation을 도입했어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0430-transferring-parameters-and-results.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SE-0430&lt;/a&gt;은 함수 경계에서 disconnected region에 있어야 하는 값을 명시적으로 표시하는 &lt;code&gt;sending&lt;/code&gt; 파라미터/리턴 어노테이션을 도입했고요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 제안은 값의 &lt;b&gt;disconnected 속성을 자료구조나 actor 같은 저장소를 거쳐서도 유지해주는 &lt;code&gt;Disconnected&lt;/code&gt; 타입을 도입&lt;/b&gt;해요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;제네릭 타입이 &lt;code&gt;sending&lt;/code&gt; 이펙트를 신경 쓰지 않고도 non-Sendable 값을 isolation region 너머로 안전하게 옮길 수 있게 해줍니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Motivation&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;region-based isolation 덕분에 &lt;b&gt;값이 disconnected region에 있으면 isolation 경계를 넘어 non-Sendable 값을 전달할 수 있어요. &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;SE-0430의 &lt;code&gt;sending&lt;/code&gt; 파라미터/리턴 어노테이션은 함수 경계에서 disconnected 값을 명시적으로 요구할 수 있게 해주지만, 저장 프로퍼티나 컬렉션 타입, 제네릭 컨테이너를 거치면 &lt;code&gt;sending&lt;/code&gt;은 유지되지 않아요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;isolation 경계 너머로 처리할 원소를 저장하는 큐 구현을 생각해볼게요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;가상의 UniqueDeque를 예로 들어봅니다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;struct UniqueDeque: ~Copyable {
  func append(_ element: consuming Element) { ... }
  func popFirst() -&amp;gt; Element? { ... }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 &lt;code&gt;UniqueDeque&lt;/code&gt;에 non-Sendable한 disconnected 값을 append하고, 나중에 pop할 때 다른 isolation region으로 보내고 싶은 경우가 있을 수 있어요  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;var deque = UniqueDeque()
deque.append(NonSendable())

guard let element = deque.popFirst() else { return }

Task {
    print(element) // Error: Element is assumed to be in the same isolation region as uniqueDeque
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이걸 되게 하려면 &lt;code&gt;append&lt;/code&gt;에서 원소를 consume하고, &lt;code&gt;popFirst&lt;/code&gt;에서 &lt;code&gt;sending&lt;/code&gt;으로 반환해야 해요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;하지만 그러면 non-Sendable이지만 &lt;b&gt;disconnected는 아닌&lt;/b&gt; 원소를 저장하고 싶은 다른 중요한 용례에서 이 타입이 크게 제약을 받게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;근본적인 한계는 &lt;code&gt;sending&lt;/code&gt;이 함수 경계의 속성이지 타입의 속성이 아니라는 점이에요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;UniqueDeque&lt;/code&gt; 같은 제네릭 타입은 저장된 원소가 disconnected 상태를 유지해야 하는지를 조건부로 제어할 수 없어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;append&lt;/code&gt;와 &lt;code&gt;popFirst&lt;/code&gt;를 &lt;code&gt;sending&lt;/code&gt;으로 요구하면 결국 disconnected 값만 &lt;code&gt;UniqueDeque&lt;/code&gt;에 담을 수 있게 되는 셈입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Proposed Solution&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;disconnected 값을 모델링할 수 있는 새로운 Disconnected 타입을 도입합니다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre class=&quot;arduino&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;var deque = UniqueDeque&amp;lt;Disconnected&amp;gt;()
deque.append(Disconnected(NonSendable()))

guard var disconnected = deque.popFirst() else { return }
let element = disconnected.take()

Task {
    print(element)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;Disconnected&lt;/code&gt; 타입은 값을 wrap해서 disconnected region에 머물도록 보장해줘요. &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;take()&lt;/code&gt; 메서드는 &lt;code&gt;Disconnected&lt;/code&gt; wrapper를 consume하고 값을 &lt;code&gt;sending&lt;/code&gt;으로 반환해서 isolation 경계를 넘을 수 있게 해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Detailed Design&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Disconnected 타입은 타입 시스템을 통해 region isolation을 강제하는 wrapper예요.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Disconnected 타입 정의&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;@frozen
public struct Disconnected: ~Copyable, Sendable {
    public init(_ value: consuming sending Value)

    public consuming func take() -&amp;gt; sending Value

    @discardableResult
    public mutating func swap(
        newValue: consuming sending Value
    ) -&amp;gt; sending Value

    public mutating func withValue(
        body: (inout sending Value) throws(Failure) -&amp;gt; Return
    ) throws(Failure) -&amp;gt; Return
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;disconnected region이란?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;region-based isolation은 프로그램 실행 중 어느 시점에 존재하는 값들을, 어떤 참조가 어떤 저장소에 도달하는지에 따라 isolation region으로 나눕니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;어떤 값의 저장소에 다른 region으로부터/다른 region으로의 참조가 전혀 도달하지 않으면, 그 값은 disconnected region에 있는 거예요. &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이런 값은 actor, Task, 다른 동시성 컨텍스트 등 다른 isolation region으로 옮겨도 안전한데, 옮기는 행위 자체가 데이터 레이스를 만들 수 없기 때문이에요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;실제로 disconnected region은 보통 다음 중 하나에서 생겨요.&lt;br /&gt;&lt;/span&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;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;초기화 인자 자체가 disconnected였던, 새로 생성된 값&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;다른 disconnected 컨테이너에서 막 꺼낸 값&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;함수 경계의 &lt;code&gt;sending&lt;/code&gt; 파라미터 (callee가 disconnected region으로 전달받음)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;함수의 &lt;code&gt;sending&lt;/code&gt; 리턴 값 (caller가 disconnected region으로 전달받음)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;disconnected 속성은 보통 &lt;code&gt;sending&lt;/code&gt; 경계에서만 추적돼요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt; &lt;code&gt;Disconnected&amp;lt;Value&amp;gt;&lt;/code&gt;는 그렇지 않았다면 &lt;code&gt;sending&lt;/code&gt; 경계를 벗어나는 순간 region 정보를 잃어버렸을 저장 경계(제네릭 컨테이너, 저장 프로퍼티, 큐)를 거치면서도 이 속성을 유지할 수 있게 해줘요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;연산들&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;값은 &lt;code&gt;init(_:)&lt;/code&gt;을 통해 wrapper 안으로 들어오는데, 이때 &lt;code&gt;sending&lt;/code&gt; 인자가 필요해요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;값은 &lt;code&gt;take()&lt;/code&gt;나 &lt;code&gt;swap(newValue:)&lt;/code&gt;를 통해 나가는데, 둘 다 &lt;code&gt;sending Value&lt;/code&gt;를 반환합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt; &lt;code&gt;withValue(body:)&lt;/code&gt;는 wrap된 값을 &lt;code&gt;inout sending Value&lt;/code&gt;로 받는 클로저에 그 자리에서 빌려줘요.&lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;모든 연산은 wrapper를 consume하거나, &lt;code&gt;sending&lt;/code&gt; 경계를 통해 wrap된 값을 교체하기 때문에, wrapper의 저장소로 향하는 alias가 transfer보다 오래 살아남을 수 없어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 특성 덕분에 &lt;code&gt;Value&lt;/code&gt; 자체가 &lt;code&gt;Sendable&lt;/code&gt;인지와 무관하게 &lt;code&gt;Disconnected&lt;/code&gt;가 &lt;code&gt;Sendable&lt;/code&gt;을 채택할 수 있는 겁니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;isolation 경계를 넘을 수 있는 값 만들기&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;take()&lt;/code&gt;로 wrap된 값을 꺼낼 수 있어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 호출은 wrapper를 consume해서, 그 이후로는 wrapper에 어떤 연산도 할 수 없습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;반환된 값은 disconnected region에 있어서, 같은 표현식 안에서 바로 isolation 경계를 넘어 전달하거나 저장해뒀다가 나중에 전달할 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;final class Resource: ~Sendable {}

// wrapper는 Disconnected 값을 담고 있던 큐 등에서 꺼낸 것이라,
// 그 안의 resource는 이미 주변 컨텍스트와 disconnected된 것으로 알려져 있어요.
func process(wrapper: consuming Disconnected) async {
    let resource = wrapper.take()
    await Task.detached {
        use(resource) // OK: 'resource'는 disconnected region에 있음
    }.value
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;결과에 disconnected 보장이 없었다면, 캡처된 &lt;code&gt;resource&lt;/code&gt;는 caller의 region에 속한 것으로 간주되어 detached task에서의 캡처가 허용되지 않았을 거예요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;wrap된 값을 제자리에서 교체하기&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;swap(newValue:)&lt;/code&gt;로 한 번에 값을 새 값으로 교체할 수 있어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;newValue&lt;/code&gt; 인자는 disconnected region에 있어야 하고, &lt;code&gt;swap&lt;/code&gt;은 이전에 저장돼 있던 값을 반환하는데 이 값도 disconnected region에 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;final class Resource: ~Sendable {}

func swapResources(in wrapper: inout Disconnected) async {
    let old = wrapper.swap(newValue: Resource())
    await Task.detached {
        dispose(old) // OK: 'old'는 disconnected region에 있음
    }.value
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;swap의 양방향 모두 disconnected-region 경계를 넘나들어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;새 값은 들어갈 때 disconnected여야 하고, 예전 값은 나올 때 disconnected로 알려집니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;꺼내지 않고 wrap된 값 mutate하기&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;값을 꺼내지 않고 임시로 mutable 접근이 필요하면 &lt;code&gt;withValue(body:)&lt;/code&gt;를 쓰면 돼요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;클로저는 값을 &lt;code&gt;inout sending Value&lt;/code&gt;로 전달받고, &lt;code&gt;withValue&lt;/code&gt;는 &lt;code&gt;body&lt;/code&gt;가 반환한 값을 그대로 반환합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;var wrapper = Disconnected([Int]())
wrapper.withValue { array in
    array.append(42)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;inout sending&lt;/code&gt; 파라미터 형태는 보통의 &lt;code&gt;inout&lt;/code&gt;보다 더 많은 것을 의미해요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;클로저 안에서는 값을 다른 isolation region으로 옮길 수 있는데, 단 클로저가 반환될 때 wrapper에는 disconnected 값이 남아 있어야 합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;보통은 클로저가 제자리 mutation을 수행하지만, 이 더 관대한 형태 덕분에 &lt;code&gt;withValue&lt;/code&gt;는 값을 다른 isolation region으로 보내고 싶어하는 코드와도 조합될 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;init(_:)&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;주어진 값을 감싸는 disconnected wrapper를 만들어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 인자는 호출 시점에 disconnected region에 있어야 하는데, alias가 없는 새로 생성된 값이 이 요구사항을 바로 만족시킵니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;final class Resource: ~Sendable {}
let wrapper = Disconnected(Resource())&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Sendable 채택과 exclusivity&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;Disconnected&lt;/code&gt; 타입은 wrap된 값이 disconnected region에 있음을 보장하기 때문에 &lt;code&gt;Sendable&lt;/code&gt;을 채택해요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;disconnected region은 isolation 경계를 안전하게 넘을 수 있기 때문에, &lt;code&gt;T&lt;/code&gt;가 &lt;code&gt;Sendable&lt;/code&gt;인지와 무관하게 &lt;code&gt;Disconnected&amp;lt;T&amp;gt;&lt;/code&gt;를 공유하는 게 안전합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;더불어 &lt;code&gt;Disconnected&lt;/code&gt;의 모든 메서드는 &lt;code&gt;consuming&lt;/code&gt;이거나 &lt;code&gt;mutating&lt;/code&gt;이라서, 컴파일러가 정적/동적 exclusivity 검사를 강제해서 겹치거나 동시적인 접근을 금지해요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 API는 의도적으로 &lt;code&gt;sending&lt;/code&gt; 경계에서의 atomic transfer로만 제한돼요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;init&lt;/code&gt;은 &lt;code&gt;sending&lt;/code&gt; 값을 consume하고, &lt;code&gt;take&lt;/code&gt;는 wrapper를 consume해서 &lt;code&gt;sending&lt;/code&gt; 값을 반환하고, &lt;code&gt;swap&lt;/code&gt;은 wrap된 값을 다른 &lt;code&gt;sending&lt;/code&gt; 값과 교환하고, &lt;code&gt;withValue&lt;/code&gt;는 클로저가 끝날 때 disconnected 값을 남겨야 하는 조건으로 wrap된 값을 &lt;code&gt;inout sending&lt;/code&gt;으로 빌려줘요. &lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;wrap된 값을 consume하거나 교체하지 않고 노출하는 accessor는 없습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;왜 borrow accessor가 무조건적인 &lt;code&gt;Sendable&lt;/code&gt; 채택과 함께라면 안전하지 않은지는 Alternatives Considered 섹션에서 다룹니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;Disconnected&lt;/code&gt;는 &lt;code&gt;Mutex&lt;/code&gt;, &lt;code&gt;Atomic&lt;/code&gt; 등 표준 라이브러리가 제공하는 isolation 경계를 넘기 위한 다른 primitive들과 함께 &lt;code&gt;Synchronization&lt;/code&gt; 모듈에 자리합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Conclusion&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;Disconnected&lt;/code&gt;는 &lt;code&gt;sending&lt;/code&gt;이 함수 경계에만 머물던 정보를 저장소를 통과해서도 유지할 수 있게 해줘요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt; non-Sendable 값을 담는 제네릭 컨테이너나 큐를 만들 때, 그 원소가 disconnected인지 아닌지를 타입 하나로 명확히 구분할 수 있게 된 셈이죠. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;init&lt;/code&gt;/&lt;code&gt;take&lt;/code&gt;/&lt;code&gt;swap&lt;/code&gt;/&lt;code&gt;withValue&lt;/code&gt; 모두 &lt;code&gt;sending&lt;/code&gt; 경계에서의 atomic transfer로만 제한된 설계 덕분에, 무조건적인 &lt;code&gt;Sendable&lt;/code&gt; 채택에도 안전성이 깨지지 않는다는 점이 인상적입니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;References&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1787290188122&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;swift-evolution/proposals/0538-disconnected.md at main &amp;middot; swiftlang/swift-evolution&quot; data-og-description=&quot;This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0538-disconnected.md&quot; data-og-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0538-disconnected.md&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bXQJAN/dJMb8SpZkr9/h4EYGPXkYIWw7gjtG0l3e1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/b1kbFB/dJMb9cBYUsT/KzjB2j1cFKL9caKgqLdDCk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0538-disconnected.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0538-disconnected.md&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bXQJAN/dJMb8SpZkr9/h4EYGPXkYIWw7gjtG0l3e1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/b1kbFB/dJMb9cBYUsT/KzjB2j1cFKL9caKgqLdDCk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;swift-evolution/proposals/0538-disconnected.md at main &amp;middot; swiftlang/swift-evolution&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>Swift</category>
      <author>GREEN.1229</author>
      <guid isPermaLink="true">https://green1229.tistory.com/634</guid>
      <comments>https://green1229.tistory.com/634#entry634comment</comments>
      <pubDate>Sat, 22 Aug 2026 08:38:31 +0900</pubDate>
    </item>
    <item>
      <title>[SE-0537] Section Placement Control for Functions</title>
      <link>https://green1229.tistory.com/633</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;안녕하세요. &lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;그린&lt;/b&gt;&lt;/span&gt;입니다  &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이번 포스팅에서는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;SE-0537 &amp;mdash; 함수를 위한 섹션 배치 제어&lt;/b&gt;&lt;/span&gt;에 대해 정리해보겠습니다  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;123123.001.jpeg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WnegN/dJMcajwz1YG/GBpQrSQ9jJNtfQdt5UKAek/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WnegN/dJMcajwz1YG/GBpQrSQ9jJNtfQdt5UKAek/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WnegN/dJMcajwz1YG/GBpQrSQ9jJNtfQdt5UKAek/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWnegN%2FdJMcajwz1YG%2FGBpQrSQ9jJNtfQdt5UKAek%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;400&quot; data-filename=&quot;123123.001.jpeg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Intro&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;div style=&quot;background: #f2f8ee; border-radius: 10px; padding: 16px 20px; margin: 16px 0;&quot;&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;Proposal:&lt;/b&gt; SE-0537&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;Author:&lt;/b&gt; Doug Gregor&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;Review Manager:&lt;/b&gt; Becca Royal-Gordon&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;Status:&lt;/b&gt; Accepted&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;Implementation:&lt;/b&gt; swiftlang/swift#89740&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0492-section-control.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SE-0492&lt;/a&gt;에서 도입된 &lt;code&gt;@section&lt;/code&gt; 어트리뷰트를 함수에도 붙일 수 있도록 확장하는 제안이에요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;임베디드 시스템에서 펌웨어 부팅 코드처럼 바이너리의 특정 섹션에 들어가야 하는 코드가 있을 때 유용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Motivation&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;&lt;code&gt;@section&lt;/code&gt; 어트리뷰트는 특정 엔티티가 오브젝트 파일의 어느 섹션에 배치될지 지정&lt;/b&gt;해요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;특히 임베디드 환경에서는 링커나 다른 도구들이 특정 종류의 심볼이 특정 섹션에 있길 기대하는 경우가 많죠. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;S&lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;E-0492는 전역/static 변수에 대한 &lt;code&gt;@section&lt;/code&gt; 지원을 도입했지만, 함수는 future direction으로 남겨뒀어요.&lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하지만 함수에도 이 지원이 필요합니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;대표적인 사례가 펌웨어 진입점이나 부팅 스킴인데, startup 코드가 미리 정의된 섹션에 있어야 하는 경우가 많거든요.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;autoit&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;// 이 함수의 코드는 커스텀 섹션에 배치됩니다
@section(&quot;__TEXT,boot&quot;)
func firmwareBootEntrypoint() { ... }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이건 SE-0492의 &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0492-section-control.md#section-placement-for-functions&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Future Directions에서도 이미 언급&lt;/a&gt;됐던 내용이에요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Proposed Solution&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;일반 함수(&lt;code&gt;func&lt;/code&gt;), 이니셜라이저(&lt;code&gt;init&lt;/code&gt;), deinitializer(&lt;code&gt;deinit&lt;/code&gt;), 클로저, accessor(&lt;code&gt;get&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt; 등)를 포함한 &lt;b&gt;모든 종류의 함수에 &lt;code&gt;@section&lt;/code&gt; 어트리뷰트를 쓸 수 있게 합니다. &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그리고 어떤 추론 규칙이든 무시하고 플랫폼 기본 섹션을 적용하는 &lt;code&gt;@section(default)&lt;/code&gt; 표기법도 함께 도입해요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Detailed Design&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;@section&lt;/code&gt; 어트리뷰트는 어떤 종류의 함수에도 적용할 수 있어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;문법을 보여주는 몇 가지 예시입니다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre class=&quot;less&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;@section(&quot;__TEXT,boot&quot;)
func firmwareBootEntrypoint() { ... }

struct MyBootConfig: ~Copyable {
  @section(&quot;__TEXT,boot&quot;) init() { 
    registerCallback { @section(&quot;__TEXT,boot&quot;) in 
      ...
    }
  }

  @section(&quot;__TEXT,boot&quot;) deinit { }

  var bootPhase: Int {
    @section(&quot;__TEXT,boot&quot;) get { ... }
    @section(&quot;__TEXT,boot&quot;) set { ... } 
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;변수에 붙이는 &lt;code&gt;@section&lt;/code&gt;과 달리, 제네릭 함수나 제네릭 컨텍스트 안의 함수에 쓰는 데는 아무런 제약이 없어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;모든 함수는 결국 text 섹션에 들어가기 때문이에요.&lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그래서 &lt;code&gt;@section&lt;/code&gt;은 타입의 인스턴스 함수에도 적용할 수 있습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;@section&lt;/code&gt; 어트리뷰트는 그 함수뿐 아니라 구현이 함께 만들어내는 관련 함수들에도 적용돼요. &lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;예를 들어 &lt;code&gt;async&lt;/code&gt; 함수에 붙이면, 구현이 생성하는 각각의 partial function들도 이 &lt;code&gt;@section&lt;/code&gt;을 따릅니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;마찬가지로 제네릭 함수에 &lt;code&gt;@section&lt;/code&gt;을 붙이면, 컴파일러가 만들어내는 그 제네릭 함수의 모든 specialization에도, 그리고 원본 제네릭 정의에도 적용돼요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;마지막으로 &lt;b&gt;&lt;code&gt;@main&lt;/code&gt; 타입의 &lt;code&gt;main&lt;/code&gt; 함수에 &lt;code&gt;@section&lt;/code&gt;이 있으면, 컴파일러가 만들어내는 실제 &lt;code&gt;main&lt;/code&gt; 진입점에도 같은 섹션이 쓰입니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;accessor, closure, 지역 함수에서의 @section 추론&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;accessor나 closure에 &lt;code&gt;@section&lt;/code&gt;을 명시하지 않으면 다음 규칙으로 추론될 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;클로저나 지역 함수는 (있다면) 감싸고 있는 함수로부터 &lt;code&gt;@section&lt;/code&gt;을 추론합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;autoit&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;@section(&quot;__TEXT,boot&quot;)
func firmwareBootEntrypoint() {
  func helper() { // @section(&quot;__TEXT,boot&quot;) 추론됨

  }

  registerCallback { // @section(&quot;__TEXT,boot&quot;) 추론됨
    ...
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;구현이 합성하는 읽기 전용 접근자(&lt;code&gt;get&lt;/code&gt;, &lt;code&gt;borrow&lt;/code&gt;, &lt;code&gt;yielding borrow&lt;/code&gt; 등)는, 명시적으로 작성된 다른 접근자로부터 &lt;code&gt;@section&lt;/code&gt;을 추론합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;구현이 합성하는 읽기/쓰기 또는 쓰기 접근자(&lt;code&gt;set&lt;/code&gt;, &lt;code&gt;mutate&lt;/code&gt;, &lt;code&gt;yielding mutate&lt;/code&gt;, &lt;code&gt;init&lt;/code&gt;, &lt;code&gt;didSet&lt;/code&gt;, &lt;code&gt;willSet&lt;/code&gt;)도, 명시적으로 작성된 다른 접근자로부터 &lt;code&gt;@section&lt;/code&gt;을 추론합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;예를 들면 이렇게요.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre class=&quot;less&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;  var scratchSpace: MutableSpan {
    @section(&quot;__TEXT,boot&quot;) borrow { ... }
    // 합성된 &quot;get&quot;이 'borrow'로부터 @section(&quot;__TEXT,boot&quot;)를 추론함
    
    @section(&quot;__TEXT,boot&quot;) mutate { ... }
    // 합성된 &quot;set&quot;이 'mutate'로부터 @section(&quot;__TEXT,boot&quot;)를 추론함 
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;border-left: 4px solid #3a8c28; background: #f2f8ee; padding: 8px 16px; margin: 16px 0;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;변수에서 그 accessor로는 &lt;code&gt;@section&lt;/code&gt;이 추론되지 않아요. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;border-left: 4px solid #3a8c28; background: #f2f8ee; padding: 8px 16px; margin: 16px 0;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;코드와 데이터는 보통 서로 다른 섹션에 들어가기 때문이에요. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;border-left: 4px solid #3a8c28; background: #f2f8ee; padding: 8px 16px; margin: 16px 0;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;local 타입(과 그 멤버)도 섹션이 추론되지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;@section 추론 억제하기&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;default&lt;/code&gt; 키워드를 섹션 값으로 쓰면, 이 선언에는 플랫폼에 맞는 기본 섹션을 쓰라는 뜻이 돼요. &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그러면 원래 적용됐을 추론 규칙을 모두 무시합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;autoit&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;@section(&quot;__TEXT,boot&quot;)
func firmwareBootEntrypoint() {
  @section(default) func helper() { // @section(&quot;__TEXT,boot&quot;) 추론을 억제함

  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;didSet/willSet 제약 완화&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;SE-0492는 &lt;code&gt;@section&lt;/code&gt;이 붙은 변수에 다음 제약을 뒀었어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그 변수는 프로퍼티 옵저버(didSet, willSet)를 가질 수 없다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 제약은 불필요한 것으로 판단되어 이번 제안에서 없앱니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;didSet&lt;/code&gt;이나 &lt;code&gt;willSet&lt;/code&gt;에도 &lt;code&gt;@section&lt;/code&gt;을 붙일 수 있고, 이 값은 구현이 실제로 합성하는 접근자(예: &lt;code&gt;set&lt;/code&gt;)에 대한 추론에 쓰입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Future Directions&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;데이터와 함수 섹션 어트리뷰트 분리하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Swift의 일부 선언은 데이터 심볼과 함수 심볼을 동시에 내보내요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;예를 들어 타입을 정의할 때 메타데이터 심볼(데이터)과 메타데이터 접근자 함수(함수)가 함께 생길 수 있죠. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 제안도 SE-0492도 타입 정의에 &lt;code&gt;@section&lt;/code&gt;을 허용하진 않지만, 만약 허용한다면 데이터용과 함수용 섹션을 따로 표현할 방법이 필요할 거예요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;예를 들면 이런 모습일 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre class=&quot;less&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;@section(data: &quot;__DATA,mysection&quot;)
@section(function: &quot;__FUNCTION,mysection&quot;)
public struct MyStruct { ... }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;data&lt;/code&gt;도 &lt;code&gt;function&lt;/code&gt;도 지정하지 않은 &lt;code&gt;@section&lt;/code&gt;은, 이 제안과 SE-0492가 다루는 것처럼 데이터/함수 구분이 모호하지 않은 곳에서만 적용될 거예요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;타입 정의, extension, 프로토콜 conformance, 파일 단위 기본값처럼 데이터와 함수 심볼을 동시에 내보내는 새로운 자리들이 이 새 문법을 쓸 수 있게 될 겁니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 제안이 승인되는 과정에서, 추론을 억제하고 기본 섹션을 지정하는 @section(default) 기능이 새로 도입됐어요.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Conclusion&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;변수에만 적용되던 &lt;code&gt;@section&lt;/code&gt;이 이제 &lt;code&gt;func&lt;/code&gt;, &lt;code&gt;init&lt;/code&gt;, &lt;code&gt;deinit&lt;/code&gt;, 클로저, accessor까지 아우르게 됐어요  &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;특히 감싸는 함수로부터 &lt;code&gt;@section&lt;/code&gt;이 자동으로 추론되는 규칙 덕분에, 펌웨어 부팅 코드처럼 특정 섹션에 몰아넣어야 하는 코드 전체를 일일이 어트리뷰트로 도배하지 않아도 될 것 같아요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;임베디드 환경에서 Swift를 쓰는 개발자들에게 꽤 실용적인 도구가 하나 더 생긴 셈입니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;References&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;/span&gt;&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1786745937935&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;swift-evolution/proposals/0537-function-sections.md at main &amp;middot; swiftlang/swift-evolution&quot; data-og-description=&quot;This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0537-function-sections.md&quot; data-og-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0537-function-sections.md&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bw8GeD/dJMb9efueSx/TECZqY5kb1kkkyCOiEePY0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/brCzKH/dJMb9frVzgx/biA718xCSbOGapEJmoOeP0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0537-function-sections.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0537-function-sections.md&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bw8GeD/dJMb9efueSx/TECZqY5kb1kkkyCOiEePY0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/brCzKH/dJMb9frVzgx/biA718xCSbOGapEJmoOeP0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;swift-evolution/proposals/0537-function-sections.md at main &amp;middot; swiftlang/swift-evolution&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>Swift</category>
      <category>@section</category>
      <category>SE-0537</category>
      <category>SWIFT</category>
      <author>GREEN.1229</author>
      <guid isPermaLink="true">https://green1229.tistory.com/633</guid>
      <comments>https://green1229.tistory.com/633#entry633comment</comments>
      <pubDate>Sat, 15 Aug 2026 07:20:04 +0900</pubDate>
    </item>
    <item>
      <title>[SE-0535] Add CLI for editing global mirrors configuration</title>
      <link>https://green1229.tistory.com/632</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;안녕하세요. &lt;b&gt;그린&lt;/b&gt;입니다  &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이번 포스팅에서는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;SE-0535 &amp;mdash; 전역 mirrors 설정을 위한 CLI 추가&lt;/b&gt;&lt;/span&gt;에 대해 정리해보겠습니다  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;123.001.jpeg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kzmdg/dJMcaafgnfB/JginJjfYXHUs8tNKmKUXAk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kzmdg/dJMcaafgnfB/JginJjfYXHUs8tNKmKUXAk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kzmdg/dJMcaafgnfB/JginJjfYXHUs8tNKmKUXAk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fkzmdg%2FdJMcaafgnfB%2FJginJjfYXHUs8tNKmKUXAk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;400&quot; data-filename=&quot;123.001.jpeg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Intro&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;div style=&quot;background: #f2f8ee; border-radius: 10px; padding: 16px 20px; margin: 16px 0;&quot;&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;Proposal:&lt;/b&gt; SE-0535&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;Author:&lt;/b&gt; Samuel Murray&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;Review Manager:&lt;/b&gt; Tim Condon&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;Status:&lt;/b&gt; Accepted&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;Implementation:&lt;/b&gt; swiftlang/swift-package-manager#9950&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;SPM은 로컬(프로젝트 단위)과 공유(사용자 단위) mirrors 설정을 둘 다 지원하지만, CLI로는 로컬 설정 파일만 편집할 수 있었어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 제안은 기존 CLI에 전역 설정을 편집할 수 있는 --global 플래그를 옵션으로 추가합니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Motivation&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;원래 mirrors는 &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0219-package-manager-dependency-mirroring.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;최초 제안&lt;/a&gt;에서 설명된 대로 프로젝트별 로컬 설정만 가능했어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이후 릴리스에서 &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/swiftlang/swift-package-manager/pull/3670&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;전역 설정 파일 지원&lt;/a&gt;이 추가됐는데, &lt;b&gt;처음부터 로컬/전역 설정을 모두 지원해온 package registry의 디자인을 따른 거예요.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;mirrors와 package registry의 전역 설정 파일은 특정 패키지를 항상 커스텀 URL에서 받아와야 하는 엔터프라이즈 환경에서 특히 유용해요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;게다가 곧 추가될 &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/swiftlang/swift-package-manager/pull/9647&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;바이너리 타깃 미러링 지원&lt;/a&gt;으로 전역 설정의 유용함은 더 커질 예정입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;하지만 현재는 전역 mirrors 설정을 쉽게 편집하고 확인할 방법이 없어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;유일한 방법은 설정 파일을 직접 만들고 손으로 편집하는 것뿐이죠. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이걸 위한 CLI를 제공하면 이미 있는 전역 package registry 기능과 결을 맞추면서, 전역 mirrors 설정의 발견 가능성도 높일 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Proposed Solution&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;로컬 설정 파일을 다루는 기존 CLI는 다음과 같아요.&lt;/span&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;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;swift package config set-mirror&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;swift package config unset-mirror&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;swift package config get-mirror&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 제안은 이 명령어들 각각에 선택적인 &lt;code&gt;--global&lt;/code&gt; 플래그를 추가합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;예시&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;https://example.com/file.json&lt;/code&gt;의 mirror를 전역으로 추가하려면:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;dsconfig&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;$ swift package config set-mirror --global --original https://example.com/file.json --mirror https://internal.com/file.json&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그러면 &lt;code&gt;~/.swiftpm/configuration/mirrors.json&lt;/code&gt;에 아래 내용이 추가돼요. (파일이 없으면 새로 만듭니다)&lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;json&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;{
  &quot;object&quot; : [
    {
      &quot;mirror&quot; : &quot;https://internal.com/file.json&quot;,
      &quot;original&quot; : &quot;https://example.com/file.json&quot;
    }
    // ...
  ],
  &quot;version&quot; : 1
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 설정을 확인하려면:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;dsconfig&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;$ swift package config get-mirror --global --original https://example.com/file.json
https://internal.com/file.json&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;설정을 해제하려면:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;tcl&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;$ swift package config unset-mirror --global --original https://example.com/file.json&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;package registry용 CLI에서 아이디어를 얻어서, 이 명령어들 각각에 &lt;code&gt;--global&lt;/code&gt; 플래그를 추가하자고 제안해요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;예를 들면 &lt;code&gt;swift package config set-mirror --global [...]&lt;/code&gt; 이렇게요. &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 플래그와 함께 쓰면 명령어는 전역 설정 파일만 고려하게 됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 플래그를 쓰면 명령어를 어느 디렉터리에서든 실행할 수 있어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;반면 지금의 (플래그 없는) 명령어는 현재 디렉터리나 그 상위 디렉터리 어디에도 &lt;code&gt;Package.swift&lt;/code&gt;가 없으면 실패하죠.&lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;현재 swift package config get-mirror의 동작은, 로컬 설정 파일이 비어 있거나 없으면 전역 설정 파일을 읽는 방식이에요. &lt;br /&gt;제안자는 이 동작을 그대로 두자고 제안합니다. &lt;br /&gt;로컬 설정이 하나라도 있으면 전역 설정을 완전히 무시하는 것보다, 로컬을 더 높은 우선순위로 두고 로컬/전역을 병합하는 게 더 합리적이라고 생각하지만, 이건 이 제안과는 다소 별개의 주제라 후속 제안으로 다루는 게 좋겠다고 봤다고 합니다!&lt;/blockquote&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Detailed Design&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;--global&lt;/code&gt; 플래그와 함께 쓰는 모든 명령어는 어느 디렉터리에서든 사용할 수 있어요. &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;즉, 현재 디렉터리(또는 그 상위 디렉터리)에 &lt;code&gt;Package.swift&lt;/code&gt; 파일이 있을 필요가 없습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;code&gt;--global&lt;/code&gt; 플래그 없이 쓰면 모든 명령어의 동작은 기존과 동일합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;set-mirror&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;$ swift package config set-mirror --help
OVERVIEW: Set a mirror for a dependency.

USAGE: swift package config set-mirror [--global] [--original ] [--mirror ]

OPTIONS:
  --global                Apply settings to all projects for this user.
  --original    The original url or identity.
  --mirror        The mirror url or identity.
  --version               Show the version.
  -h, -help, --help       Show help information.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 명령어를 실행하면 &lt;code&gt;~/.swiftpm/configuration/mirrors.json&lt;/code&gt;에 mirror 설정을 추가하거나, 파일이 없으면 새로 만듭니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;unset-mirror&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;$ swift package config unset-mirror --help
OVERVIEW: Remove an existing mirror.

USAGE: swift package config unset-mirror [--original ] [--mirror ]

OPTIONS:
  --global                Apply settings to all projects for this user.
  --original    The original url or identity.
  --mirror        The mirror url or identity.
  --version               Show the version.
  -h, -help, --help       Show help information.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 명령어를 실행하면 &lt;code&gt;~/.swiftpm/configuration/mirrors.json&lt;/code&gt;에서 일치하는 mirror 설정을 제거해요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;일치하는 항목이 없거나 파일이 없으면 에러 메시지를 표시합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;get-mirror&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;OVERVIEW: Print mirror configuration for the given package dependency.

USAGE: swift package config get-mirror [--original ]

OPTIONS:
  --global                Only read settings applied to all projects for this user.
  --original    The original url or identity.
  --version               Show the version.
  -h, -help, --help       Show help information.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 명령어를 실행하면 &lt;code&gt;~/.swiftpm/configuration/mirrors.json&lt;/code&gt;에서 일치하는 mirror 설정을 가져와요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;일치하는 항목이 없거나 파일이 없으면 에러 메시지를 표시합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Security&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 제안이 보안에 미치는 영향은 미미해요. 사용자 홈 디렉터리에 있는 파일을 수정하거나 읽는 정도입니다. mirrors의 &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0219-package-manager-dependency-mirroring.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;최초 제안&lt;/a&gt;에서는 전역 설정이 &quot;예상 못한 함정&quot; 같은 순간을 만들 수 있다는 우려가 있었지만, SPM에 전역 mirrors 설정 지원이 이미 추가된 상태라 이 CLI를 추가한다고 해서 새로운 이슈가 생기진 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Impact on Existing Packages&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 제안은 기존 패키지에 아무런 영향을 주지 않아요. 새 CLI 플래그를 추가할 뿐, 기존 동작은 전혀 바뀌지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Conclusion&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;작지만 실용적인 CLI 개선이에요. 그동안 전역 mirrors 설정을 편집하려면 &lt;code&gt;~/.swiftpm/configuration/mirrors.json&lt;/code&gt;을 직접 손으로 만지는 수밖에 없었는데, &lt;code&gt;--global&lt;/code&gt; 플래그 하나로 &lt;code&gt;set-mirror&lt;/code&gt;, &lt;code&gt;unset-mirror&lt;/code&gt;, &lt;code&gt;get-mirror&lt;/code&gt;를 어느 디렉터리에서든 쓸 수 있게 됐어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;엔터프라이즈 환경에서 특정 패키지를 항상 내부 URL로 받아오게 설정해두고 싶을 때, 그리고 곧 추가될 바이너리 타깃 미러링과 함께 쓰기에도 훨씬 편리해질 것 같습니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;References&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1786189403564&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;swift-evolution/proposals/0535-global-mirrors-configuration-cli.md at main &amp;middot; swiftlang/swift-evolution&quot; data-og-description=&quot;This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0535-global-mirrors-configuration-cli.md&quot; data-og-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0535-global-mirrors-configuration-cli.md&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/chaC8q/dJMb8Xku60Y/CXWKyTWcewmOCqXsS7KXN1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/btxF3C/dJMb8TCpsj9/hJ1yPW3IKLQsvDu5vfSb6K/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0535-global-mirrors-configuration-cli.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0535-global-mirrors-configuration-cli.md&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/chaC8q/dJMb8Xku60Y/CXWKyTWcewmOCqXsS7KXN1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/btxF3C/dJMb8TCpsj9/hJ1yPW3IKLQsvDu5vfSb6K/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;swift-evolution/proposals/0535-global-mirrors-configuration-cli.md at main &amp;middot; swiftlang/swift-evolution&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>Swift</category>
      <category>ios</category>
      <category>Mirrors</category>
      <category>SE-0535</category>
      <category>SWIFT</category>
      <author>GREEN.1229</author>
      <guid isPermaLink="true">https://green1229.tistory.com/632</guid>
      <comments>https://green1229.tistory.com/632#entry632comment</comments>
      <pubDate>Sat, 8 Aug 2026 20:44:33 +0900</pubDate>
    </item>
    <item>
      <title>[SE-0527] RigidArray &amp;amp; UniqueArray</title>
      <link>https://green1229.tistory.com/631</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;안녕하세요. &lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;그린&lt;/b&gt;&lt;/span&gt;입니다  &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이번 포스팅에서는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;SE-0527 &amp;mdash; RigidArray와 UniqueArray&lt;/b&gt;&lt;/span&gt;에 대해 정리해보겠습니다  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;123123.001.jpeg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6TCH1/dJMcajiSpJc/xxoLjgkKDu4GPsXcmzkmh1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6TCH1/dJMcajiSpJc/xxoLjgkKDu4GPsXcmzkmh1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6TCH1/dJMcajiSpJc/xxoLjgkKDu4GPsXcmzkmh1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6TCH1%2FdJMcajiSpJc%2FxxoLjgkKDu4GPsXcmzkmh1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;400&quot; data-filename=&quot;123123.001.jpeg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Intro&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;div style=&quot;background: #f2f8ee; border-radius: 10px; padding: 16px 20px; margin: 16px 0;&quot;&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Proposal:&lt;/b&gt; SE-0527&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Authors:&lt;/b&gt; Karoy Lorentey, Alejandro Alonso&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Review Manager:&lt;/b&gt; Steve Canon&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Status:&lt;/b&gt; Implemented (Swift 6.4)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Implementation:&lt;/b&gt; swiftlang/swift#87521&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Motivation&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Swift 5.9에서 noncopyable struct/enum이 들어온 이후로 이를 지원하는 API가 하나둘 추가되어 왔습니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;표준 라이브러리도 &lt;code&gt;Atomic&lt;/code&gt;, &lt;code&gt;Mutex&lt;/code&gt;, inline 저장소에 noncopyable 값을 담을 수 있는 &lt;code&gt;InlineArray&lt;/code&gt; 같은 타입을 직접 구현했죠. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하지만 noncopyable 원소를 지원하는 크기 조절 가능한(resizable) 자료구조는 아직 없었습니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Swift 개발자라면 동적으로 크기가 변하는 값 목록이 필요할 때 &lt;code&gt;Array&lt;/code&gt;를 찾게 마련&lt;/b&gt;인데, 안타깝게도 클래식 &lt;code&gt;Array&lt;/code&gt;는 noncopyable 값을 지원하지 않아요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;noncopyable 원소 지원을 Array에 억지로 끼워 넣는 방법은 두 가지가 있을 수 있어요.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;1️⃣ &lt;b&gt;&lt;code&gt;Array&lt;/code&gt;를 copyable로 유지하면서, mutation 연산이 원소를 복사하는 대신 다른 방식으로 uniqueness를 보장하게 만드는 방법&lt;/b&gt;. &lt;br /&gt;예를 들어 mutation이 런타임 에러를 일으키게 하거나, 원소를 어떻게 clone할지 설명하는 새 인자를 추가하는 방식이 있는데, 둘 다 실제로는 받아들이기 힘든 프로그래밍 경험으로 이어집니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;2️⃣ &lt;b&gt;&lt;code&gt;Array&lt;/code&gt;를 원소의 copyability에 따라 조건부로 copyable하게 만드는 방법.&lt;/b&gt; &lt;br /&gt;이러려면 mutation 연산이 &lt;code&gt;Element&lt;/code&gt;가 copyable인 경우에만 copy-on-write 경로로 분기하는 런타임 조건을 추가로 가져야 해요. 여기엔 두 가지 기술적 문제가 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Swift 코드는 현재 런타임에 타입 인자가 copyable인지 확인할 방법이 없고, 이런 &quot;conformance&quot; 체크는 모든 배열 mutation에 잠재적 오버헤드를 더하게 됩니다.&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;첫 번째 문제는 해결 가능하지만, 두 번째는 굉장히 가져가기 어려운 문제예요.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;특히 noncopyable 원소를 허용하는 제네릭 컨텍스트에 큰 영향을 주는데, 그런 컨텍스트에서는 copyability 체크가 런타임 조건이어야만 하거든요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;noncopyable 원소를 허용하는 컨텍스트에서 호출됐다는 이유만으로 &lt;code&gt;append&lt;/code&gt;가 storage가 unique하다고 가정할 순 없으니까요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이미 복잡한 &lt;code&gt;Array&lt;/code&gt;의 성능 분석을 더 어렵게 만드는 건 noncopyable 타입 도입의 배경이 된 &lt;a href=&quot;https://github.com/swiftlang/swift/blob/main/docs/OwnershipManifesto.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Swift Ownership Manifesto&lt;/a&gt;의 목표에 정면으로 반하는 일이에요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;목표는 단순히 noncopyable 값을 담는 배열이 아니라, 예측 가능하고 분석하기 쉬운 좋은 성능으로 그걸 해내는 겁니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 외에도 Array에는 예측 불가능한 복잡도 급증을 만드는 두 가지 주요 원인이 있어요.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;1️⃣ copy-on-write 값 시맨틱스&lt;/b&gt; &amp;mdash; 공유된 복사본을 실수로 mutate하기 쉽습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그럴 때마다 배열 전체를 새로 할당해야 해서, 평소엔 상수 복잡도인 단순 subscript 재할당 같은 연산도 선형 복잡도 괴물이 될 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;2️⃣ 동적 자료구조&lt;/b&gt; &amp;mdash; 필요할 때마다 암묵적으로 크기를 재조정합니다. 적&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;절한 크기의 새 버퍼를 할당하고 기존 원소를 복사하거나 옮기는 방식이라, 대부분은 상수 시간/공간에 실행되지만 어쩌다 한 번씩 resize가 트리거되면서 갑자기 선형이 돼요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;기하급수적 성장 패턴 덕분에 &lt;code&gt;append&lt;/code&gt;는 평균적으로 amortized O(1)이지만,&lt;b&gt; 실제 최악의 경우 복잡도는 O(count)입니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 두 특징 자체가 나쁜 건 아니에요. &lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;오히려 Swift의 프로그래밍 모델을 크게 단순화해주는 바람직한 이점이죠. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;하지만 신뢰할 수 있는 고성능이 필요한 컨텍스트에서는 이 특징들이 코드가 런타임에 어떻게 동작할지 분석하고 보장하기 어렵게 만드는 걸림돌이 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Array에 기능을 계속 덧붙이는 건 답이 아니에요.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;필요한 건 &lt;code&gt;Array&lt;/code&gt;보다 더 예측 가능한 성능이 필요한 용례에 특화된 추가 배열 구현체입니다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size18&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그럼 새 배열 타입이 몇 개나 필요할까요? &lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;위 두 특징은 기술적으로 서로 독립적이라 개별적으로 켜고 끌 수 있어요. &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그러면 &lt;b&gt;이론상 네 가지 조합&lt;/b&gt;이 나오는데, 그중 하나는 이미 존재하는 &lt;code&gt;Array&lt;/code&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; margin: 16px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 8px;&quot;&gt;&amp;nbsp;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 8px;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Noncopyable&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 8px;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Copy-on-write&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Fixed capacity&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;???&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;???&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Dynamic&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;???&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;Array&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;fixed-capacity 자료구조를 쓰는 주된 이유는 암묵적 할당을 피하기 위해서인데, copy-on-write는 그것과 정면으로 충돌해요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그래서 오른쪽 위 칸은 비워둘 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; margin: 16px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 8px;&quot;&gt;&amp;nbsp;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 8px;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Noncopyable&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 8px;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Copy-on-write&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Fixed capacity&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;???&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;---&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Dynamic&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;???&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;Array&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Proposed Solution&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;표준 라이브러리에 RigidArray와 UniqueArray라는 두 새 배열 타입을 추가할 것을 제안합니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;둘 다 진짜 배열 타입으로, append, insert, replace, remove, 임의 재정렬, 정수 오프셋을 통한 빠른 접근 등 익숙한 배열 연산을 제공&lt;/b&gt;해요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;둘 다 하나의 힙 할당된 연속 메모리 영역을 저장소로 쓰고, 부분적으로만 초기화될 수 있으며, 초기화된 항목들은 앞쪽에 모여 있어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;요컨대 기존 &lt;code&gt;Array&lt;/code&gt;, &lt;code&gt;ContiguousArray&lt;/code&gt;와 마찬가지로 고전적인 가변 크기 배열 자료구조를 구현합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 타입들은 Swift 툴체인의 새 모듈 &lt;code&gt;Containers&lt;/code&gt;에 포함돼요. s&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;wift-collections의 &lt;code&gt;Collections&lt;/code&gt;처럼, 이 모듈은 앞으로 ring buffer 같은 자료구조들의 집합이 될 예정입니다 ☺️&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;UniqueArray&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;UniqueArray&lt;/code&gt;는 &lt;b&gt;copy-on-write 컨테이너를 피하고 싶지만 메모리를 엄격하게 관리할 필요는 없는, 일반적인 고성능 컨텍스트에 좋은 선택&lt;/b&gt;이에요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;C++의 &lt;code&gt;std::vector&lt;/code&gt;나 Rust의 &lt;code&gt;Vec&lt;/code&gt;처럼 단순하고 동적으로 크기가 조정되는 배열 타입입니다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;UniqueArray는 저장소가 항상 유일하게(uniquely) 소유되는 Array variant예요.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;UniqueArray&lt;/code&gt;를 noncopyable 타입으로 선언해서 정적으로 강제하는데, 그래서 &lt;code&gt;UniqueArray&lt;/code&gt; 자신은 한 번에 하나의 변수(저장 프로퍼티, 지역 변수, 함수 인자 등)만 가질 수 있고 그 변수를 통해서만 mutate할 수 있어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;다른 변수로 옮길 수는 있지만, 이건 원본을 consume해서 사용 불가능/미초기화 상태로 만듭니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;import Containers

struct FileHandle: ~Copyable {
  let fd: UInt32

  init(reading path: String) throws { fd = try open(path, .read) }

  deinit {
    try! close(fd)
  }
}

let foo = try FileHandle(reading: &quot;foo.txt&quot;)
let bar = try FileHandle(reading: &quot;bar.md&quot;)

var a = UniqueArray()
a.append(foo) // OK, consumes \`foo\`
a.append(bar) // OK, consumes \`bar\`

var b = a // OK, consumes \`a\`, moving the array instance into \`b\`

b.append(try FileHandle(reading: &quot;baz.swift&quot;)) // OK
// \`b\`는 이제 foo.txt, bar.md, baz.swift에 대한 열린 핸들을 담고 있음

a.append(try FileHandle(reading: &quot;Info.plist&quot;)) // error: \`a\` used after consume (used here)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;noncopyable 자신인 덕분에 &lt;code&gt;UniqueArray&lt;/code&gt;는 위 예시의 파일 핸들처럼 noncopyable 원소도 자연스럽게 담을 수 있어요.&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;원소를 다루는 배열 연산들은 소유권을 신중하게 고려해서 설계되었고, &lt;code&gt;consuming&lt;/code&gt;이나 &lt;code&gt;borrowing&lt;/code&gt; 키워드로 원소 소유권과 어떻게 상호작용하는지 표시되어 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;제대로 된 동적 크기 조정 컨테이너답게, &lt;code&gt;UniqueArray&lt;/code&gt;도 기하급수적 성장 곡선에 의존해서 (amortized) 성능을 확보해요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;resize가 필요할 때 이전 capacity에 상수 배율을 곱하는 방식이지, 단순히 그 연산에 필요한 만큼만 선형으로 키우지 않습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 키워지는 비율은 내부 구현 세부사항이라 환경/플랫폼/Swift 릴리스에 따라 바뀔 수 있고, 사용자가 설정할 수 없습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;RigidArray&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;핵심 시스템 프로그래밍, 메모리 제약이 있는 임베디드 플랫폼, 실시간 컨텍스트 같은 가장 low-level인 용례에는 UniqueArray만으로는 충분하지 않아요.&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;고정 capacity를 갖는 noncopyable 배열 타입이 필요합니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;가용 메모리가 킬로바이트 단위인 환경을 위한 Swift 코드를 작성한다고 생각해보면, 모든 할당이 소스에 명시적으로 드러나서 정확히 계산하고 예산을 세울 수 있어야 해요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이런 컨텍스트에서는 알아서 resize하거나 복사하는 컨테이너 타입이 들어설 자리가 없죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;RigidArray는 이런 용례를 위한 타입이고, 이름 그대로 유연하지 않고 rigid(경직된)한 성격을 반영합니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;RigidArray&lt;/code&gt; 인스턴스는 항상 특정 capacity로 할당되고, 그 안에서만 동작해야 해요. &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그래서 더 이상 새 항목을 담을 수 없는 &quot;가득 찬&quot; 상태가 될 수 있고, 가득 찬 &lt;code&gt;RigidArray&lt;/code&gt;에 값을 추가하려 하면 런타임 트랩이 발생합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;stylus&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;var c = RigidArray(capacity: 2)
print(c.isFull)       // =&amp;gt; false
print(c.freeCapacity) // =&amp;gt; 2

c.append(23)
print(c.isFull)       // =&amp;gt; false
print(c.freeCapacity) // =&amp;gt; 1

c.append(42)
print(c.isFull)       // =&amp;gt; true
print(c.freeCapacity) // =&amp;gt; 0

c.append(7) // runtime error: RigidArray capacity overflow&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이걸 복구 가능한 에러가 아니라 precondition 위반으로 다루면, &lt;b&gt;&lt;code&gt;RigidArray&lt;/code&gt;가 &lt;code&gt;UniqueArray&lt;/code&gt;와 같은 기본 연산을 제공하면서도 향후 이 둘을 &lt;a href=&quot;https://github.com/apple/swift-collections/blob/1.4.1/Sources/ContainersPreview/Protocols/Container/RangeReplaceableContainer.swift&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ownership-aware RangeReplaceableCollection 같은 추상화&lt;/a&gt; 아래로 통합&lt;/b&gt;할 길을 열어둘 수 있어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;또한 연산들이 어떤 식으로든 실패를 복구 가능하게 보고하도록 억지로 복잡하게 만들 필요도 없어지고요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;실제로 &lt;code&gt;RigidArray&lt;/code&gt; 저장소를 오버플로우시키는 건 프로그래머의 실수처럼 느껴져요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;타입을 잘못 사용했다는 신호지, 일상적인 문제가 아닙니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;빈 &lt;code&gt;Array&lt;/code&gt;에서 마지막 항목을 지우려 하면 트랩이 나는 것처럼, 가득 찬 &lt;code&gt;RigidArray&lt;/code&gt;에 항목을 추가하려는 것도 자연스럽게 트랩으로 이어집니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;RigidArray&lt;/code&gt;는 스스로 resize하지 않지만, capacity가 타입의 일부는 아니에요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;rigid array 인스턴스는 사실 &lt;code&gt;reallocate&lt;/code&gt; 연산을 명시적으로 호출해서 임의로 저장소를 키우거나 줄일 수 있습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;stylus&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;var d = RigidArray(capacity: 2)
d.append(10)
d.append(20)
print(d.isFull)       // =&amp;gt; true
print(d.freeCapacity) // =&amp;gt; 0

d.reallocate(capacity: 10)
print(d.isFull)       // =&amp;gt; false
print(d.freeCapacity) // =&amp;gt; 8

d.append(30) // OK!&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;배열은 요청한 만큼 정확히 저장소를 할당해요 (더 많지도 적지도 않게). &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 연산 덕분에 &lt;code&gt;RigidArray&lt;/code&gt;로 임의의 커스텀 resize 로직을 갖는 wrapper 배열 타입도 만들 수 있어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;사&lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;실 &lt;code&gt;UniqueArray&lt;/code&gt; 자체가 그렇게 구현되어 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Detailed Design&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;타입 선언&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;less&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;@frozen
public struct RigidArray: ~Copyable {}

extension RigidArray: Sendable where Element: Sendable &amp;amp; ~Copyable {}

@frozen
public struct UniqueArray: ~Copyable {}

extension UniqueArray: Sendable where Element: Sendable &amp;amp; ~Copyable {}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;둘 다 갖는 API &amp;mdash; 기본&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;capacity&lt;/code&gt;, &lt;code&gt;freeCapacity&lt;/code&gt;, &lt;code&gt;span&lt;/code&gt;/&lt;code&gt;mutableSpan&lt;/code&gt;, &lt;code&gt;isTriviallyIdentical(to:)&lt;/code&gt;, 그리고 &lt;code&gt;OutputSpan&lt;/code&gt;을 통해 저장소를 직접 편집하는 &lt;code&gt;edit(_:)&lt;/code&gt;, capacity를 조정하는 &lt;code&gt;reallocate(capacity:)&lt;/code&gt;와 &lt;code&gt;reserveCapacity(_:)&lt;/code&gt;가 공통으로 제공됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;copyable 원소에 대해서는 &lt;code&gt;clone()&lt;/code&gt; / &lt;code&gt;clone(capacity:)&lt;/code&gt;로 깊은 복사도 가능해요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension [Rigid|Unique]Array where Element: ~Copyable {
  public var capacity: Int { get }
  public var freeCapacity: Int { get }
  public var span: Span { get }
  public var mutableSpan: MutableSpan { mutating get }
  public func isTriviallyIdentical(to: borrowing Self) -&amp;gt; Bool

  public mutating func edit(
    _ body: (inout OutputSpan) throws(E) -&amp;gt; R
  ) throws(E) -&amp;gt; R

  public mutating func reallocate(capacity newCapacity: Int)
  public mutating func reserveCapacity(_ n: Int)
}

extension [Rigid|Unique]Array where Element: Copyable {
  public func clone() -&amp;gt; Self
  public func clone(capacity: Int) -&amp;gt; Self
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;둘 다 갖는 API &amp;mdash; 이니셜라이저&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension [Rigid|Unique]Array where Element: ~Copyable {
  public init()
  public init(capacity: Int)

  public init(
    capacity: Int,
    initializingWith initializer: (inout OutputSpan) throws(E) -&amp;gt; Void
  ) throws(E)
}

extension [Rigid|Unique]Array where Element: Copyable {
  public init(repeating repeatedValue: Element, count: Int)

  public init(
    capacity: Int? = nil,
    copying span: Span
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;둘 다 갖는 API &amp;mdash; 컬렉션 기반&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;배열의 위치를 나타내는 &lt;code&gt;Index&lt;/code&gt;는 정수 오프셋(&lt;code&gt;typealias Index = Int&lt;/code&gt;)이고, &lt;code&gt;isEmpty&lt;/code&gt;, &lt;code&gt;count&lt;/code&gt;, &lt;code&gt;startIndex&lt;/code&gt;, &lt;code&gt;endIndex&lt;/code&gt;, &lt;code&gt;indices&lt;/code&gt;, subscript, &lt;code&gt;swapAt&lt;/code&gt;, &lt;code&gt;index(after:)&lt;/code&gt;/&lt;code&gt;index(before:)&lt;/code&gt;, &lt;code&gt;formIndex&lt;/code&gt; 계열, &lt;code&gt;distance(from:to:)&lt;/code&gt; 등 기존 &lt;code&gt;Collection&lt;/code&gt; API와 결을 맞춘 연산들이 제공됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;성능을 위해 대부분의 인덱스 관련 연산은 인덱스 유효성을 미리 검증하지 않고, 실제로 접근할 때 검증을 미룹니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension [Rigid|Unique]Array where Element: ~Copyable {
  public typealias Index = Int

  public var isEmpty: Bool { get }
  public var count: Int { get }
  public var startIndex: Int { get }
  public var endIndex: Int { get }
  public var indices: Range { get }

  public subscript(position: Int) -&amp;gt; Element {
    borrow
    mutate
  }

  public mutating func swapAt(_ i: Int, _ j: Int)

  public func index(after index: Int) -&amp;gt; Int
  public func index(before index: Int) -&amp;gt; Int
  public func formIndex(after index: inout Int)
  public func formIndex(before index: inout Int)
  public func index(_ index: Int, offsetBy n: Int) -&amp;gt; Int
  public func distance(from start: Index, to end: Index) -&amp;gt; Int

  public func formIndex(
    _ index: inout Index,
    offsetBy n: inout Int,
    limitedBy limit: Index
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;둘 다 갖는 API &amp;mdash; Append&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;단일 원소 &lt;code&gt;append(_:)&lt;/code&gt; 외에, &lt;code&gt;OutputSpan&lt;/code&gt;을 직접 채우는 &lt;code&gt;append(addingCount:initializingWith:)&lt;/code&gt;, 버퍼나 &lt;code&gt;OutputSpan&lt;/code&gt;을 이동시키는 &lt;code&gt;append(moving:)&lt;/code&gt;, copyable 원소를 위한 버퍼/span/시퀀스 복사 &lt;code&gt;append(copying:)&lt;/code&gt; 계열이 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;capacity가 부족하면 &lt;code&gt;RigidArray&lt;/code&gt;는 런타임 에러, &lt;code&gt;UniqueArray&lt;/code&gt;는 기하급수적으로 storage를 늘려요.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension [Rigid|Unique]Array where Element: ~Copyable {
  public mutating func append(_ item: consuming Element)

  public mutating func append(
    addingCount newItemCount: Int,
    initializingWith initializer: (inout OutputSpan) throws(E) -&amp;gt; Void
  ) throws(E)

  public mutating func append(
    moving items: UnsafeMutableBufferPointer
  )

  public mutating func append(
    moving items: inout OutputSpan
  )
}

extension [Rigid|Unique]Array where Element: Copyable {
  public mutating func append(
    copying newElements: UnsafeBufferPointer
  )
  public mutating func append(
    copying newElements: UnsafeMutableBufferPointer
  )
  public mutating func append(copying newElements: Span)
  public mutating func append(copying newElements: some Sequence)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;둘 다 갖는 API &amp;mdash; Insert&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;지정한 위치에 원소를 끼워 넣는 &lt;code&gt;insert(_:at:)&lt;/code&gt;부터, &lt;code&gt;OutputSpan&lt;/code&gt;을 채우는 버전, 버퍼/span을 이동/복사하는 버전까지 append와 짝을 이루는 형태로 제공됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;지정 위치 이후 원소들은 뒤로 밀려서 공간을 만듭니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension [Rigid|Unique]Array where Element: ~Copyable {
  public mutating func insert(_ item: consuming Element, at index: Int)

  public mutating func insert(
    addingCount newItemCount: Int,
    at index: Int,
    initializingWith initializer: (inout OutputSpan) throws(E) -&amp;gt; Void
  ) throws(E)

  public mutating func insert(
    moving items: UnsafeMutableBufferPointer,
    at index: Int
  )

  public mutating func insert(
    moving items: inout OutputSpan,
    at index: Int
  )
}

extension [Rigid|Unique]Array where Element: Copyable {
  public mutating func insert(
    copying newElements: UnsafeBufferPointer, at index: Int
  )
  public mutating func insert(
    copying newElements: UnsafeMutableBufferPointer,
    at index: Int
  )
  public mutating func insert(
    copying newElements: Span, at index: Int
  )
  public mutating func insert(
    copying newElements: some Collection, at index: Int
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;둘 다 갖는 API &amp;mdash; Remove&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension [Rigid|Unique]Array where Element: ~Copyable {
  public mutating func popLast() -&amp;gt; Element?
  public mutating func removeLast() -&amp;gt; Element
  public mutating func removeLast(_ k: Int)
  public mutating func remove(at index: Int) -&amp;gt; Element
  public mutating func removeSubrange(_ bounds: Range)
  public mutating func removeSubrange(_ bounds: some RangeExpression)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;둘 다 갖는 API &amp;mdash; Replace&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;지정한 범위를 새 항목으로 교체하는 &lt;code&gt;replaceSubrange&lt;/code&gt; 계열이에요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;emove 후 insert하는 것과 같은 효과지만, 원소를 두 번 옮기지 않아서 상수 배 더 빠릅니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension [Rigid|Unique]Array where Element: ~Copyable {
  public mutating func replaceSubrange(
    _ subrange: Range,
    addingCount newItemCount: Int,
    initializingWith initializer: (inout OutputSpan) throws(E) -&amp;gt; Void
  ) throws(E) -&amp;gt; Void

  public mutating func replaceSubrange(
    _ subrange: Range,
    moving newElements: UnsafeMutableBufferPointer
  )

  public mutating func replaceSubrange(
    _ subrange: Range,
    moving items: inout OutputSpan
  )
}

extension [Rigid|Unique]Array where Element: Copyable {
  public mutating func replaceSubrange(
    _ subrange: Range,
    copying newElements: UnsafeBufferPointer
  )
  public mutating func replaceSubrange(
    _ subrange: Range,
    copying newElements: UnsafeMutableBufferPointer
  )
  public mutating func replaceSubrange(
    _ subrange: Range,
    copying newElements: Span
  )
  public mutating func replaceSubrange(
    _ subrange: Range,
    copying newElements: consuming some Collection
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;둘 다 갖는 API &amp;mdash; Conformance&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;두 타입 모두 &lt;code&gt;Equatable&lt;/code&gt;, &lt;code&gt;Hashable&lt;/code&gt;, &lt;code&gt;CustomStringConvertible&lt;/code&gt;, &lt;code&gt;CustomDebugStringConvertible&lt;/code&gt;을 채택하고, &lt;a href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0516-borrowing-sequence.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SE-0516&lt;/a&gt;에서 제안된 &lt;code&gt;BorrowingSequence&lt;/code&gt;도 채택해서 그 프로포절의 &lt;code&gt;SpanIterator&lt;/code&gt;를 iterator로 씁니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension [Rigid|Unique]Array: Equatable where Element: Equatable &amp;amp; ~Copyable {
  public static func ==(left: borrowing Self, right: borrowing Self) -&amp;gt; Bool
}

extension [Rigid|Unique]Array: Hashable where Element: Hashable &amp;amp; ~Copyable {
  public func hash(into hasher: inout Hasher)
}

extension [Rigid|Unique]Array: CustomStringConvertible where Element: ~Copyable {
  public var description: String { get }
}

extension [Rigid|Unique]Array: CustomDebugStringConvertible where Element: ~Copyable {
  public var debugDescription: String { get }
}

extension [Rigid|Unique]Array: BorrowingSequence where Element: ~Copyable {
  @lifetime(borrow self)
  public func makeBorrowingIterator() -&amp;gt; SpanIterator
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;border-left: 4px solid #3a8c28; background: #f2f8ee; padding: 8px 16px; margin: 16px 0;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;CustomStringConvertible&lt;/code&gt;과 &lt;code&gt;CustomDebugStringConvertible&lt;/code&gt; 채택은 &lt;a href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0499-support-non-copyable-simple-protocols.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SE-0499&lt;/a&gt;가 구현된 뒤에야 정식으로 배포될 수 있어요. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;border-left: 4px solid #3a8c28; background: #f2f8ee; padding: 8px 16px; margin: 16px 0;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그 전까지는 (지금으로선 다소 소박한) &lt;code&gt;description&lt;/code&gt;/&lt;code&gt;debugDescription&lt;/code&gt; 구현을 우선 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;RigidArray 전용 API&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;isFull&lt;/code&gt; 프로퍼티, 시퀀스/컬렉션을 복사해서 초기화하는 이니셜라이저, capacity가 부족하면 항목을 그대로 돌려주는 &lt;code&gt;pushLast(_:)&lt;/code&gt;, 저장 capacity는 유지한 채 모든 원소를 지우는 &lt;code&gt;removeAll()&lt;/code&gt;이 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension RigidArray where Element: ~Copyable {
  public var isFull: Bool { get }

  public init(
    capacity: Int,
    copying contents: some Sequence
  )

  public init(
    capacity: Int? = nil,
    copying contents: some Collection
  )

  public mutating func pushLast(_ item: consuming Element) -&amp;gt; Element?

  public mutating func removeAll()
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;UniqueArray 전용 API&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;초기 capacity를 지정하는 이니셜라이저와, capacity를 유지할지 선택할 수 있는 &lt;code&gt;removeAll(keepingCapacity:)&lt;/code&gt;가 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension UniqueArray where Element: ~Copyable {
  public init(
    capacity: Int? = nil,
    copying contents: some Sequence
  )

  public init(minimumCapacity: Int)

  public mutating func removeAll(keepingCapacity keepCapacity: Bool = false)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Source Compatibility&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;RigidArray와 UniqueArray는 표준 라이브러리의 새 타입이라 추가는 소스 호환적인 변경이에요.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;swift-collections에서 이 타입들을 import하고 있거나 같은 이름으로 커스텀 타입을 정의한 개발자라도, 표준 라이브러리 타입 이름에 대한 shadowing 규칙 덕분에 기존 import/커스텀 타입은 그대로 동작합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;ABI Compatibility&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 제안은 표준 라이브러리 ABI에 순수하게 추가만 하는 변경이라 기존 바이너리를 깨지 않아요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;두 타입은 frozen으로 제안되는데, 이는 향후 표현 방식 변경을 막습니다 (capacity 축소를 구현하려고 예약된 capacity를 추적하고 싶을 수 있는 &lt;code&gt;UniqueArray&lt;/code&gt;에 특히 관련이 있어요).&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Implications on Adoption&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;RigidArray&lt;/code&gt;와 &lt;code&gt;UniqueArray&lt;/code&gt;는 표준 라이브러리의 새 타입이므로, 적어도 이 타입들이 도입된 버전의 Swift를 써야 해요. &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;swift-collections에서 이 타입들을 쓰던 개발자라면, 패키지 소스의 하위 배포 특성 때문에 계속 그 버전을 쓰는 게 더 나을 수도 있습니다.&lt;/span&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;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Future Directions&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Clonable&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 제안은 &lt;a href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0517-uniquebox.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;UniqueBox&lt;/a&gt; 제안처럼 &lt;code&gt;RigidArray&lt;/code&gt;와 &lt;code&gt;UniqueArray&lt;/code&gt; 모두에 &lt;code&gt;clone()&lt;/code&gt;/&lt;code&gt;clone(capacity:)&lt;/code&gt;를 도입해요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;다만 지금은 &lt;code&gt;Element: Copyable&lt;/code&gt;을 요구해서 &lt;code&gt;UniqueArray&amp;lt;UniqueArray&amp;lt;Int&amp;gt;&amp;gt;&lt;/code&gt; 같은 중첩 2차원 배열은 불가능한데, &lt;code&gt;UniqueBox&lt;/code&gt; 제안에서 언급했듯 이런 기능을 가능하게 할 &lt;code&gt;Clonable&lt;/code&gt; 프로토콜의 여지가 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;public protocol Cloneable: ~Copyable {
  func clone() -&amp;gt; Self
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;다른 표준 자료구조의 Rigid/Unique variant&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 제안이 도입하는 &lt;code&gt;Rigid&lt;/code&gt;/&lt;code&gt;Unique&lt;/code&gt; 접두어는 비슷한 동작을 하는 컨테이너 타입들의 일반적인 네이밍 패턴으로 자리잡길 의도한 것이에요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;swift-collections 패키지는 이미 같은 시맨틱스의 ring buffer인 &lt;code&gt;RigidDeque&lt;/code&gt;, &lt;code&gt;UniqueDeque&lt;/code&gt;를 정의하고 있고, ownership-aware한 &lt;code&gt;Set&lt;/code&gt;/&lt;code&gt;Dictionary&lt;/code&gt; 프로토타입도 같은 접두어로 제공합니다. &lt;code&gt;RigidDeque&lt;/code&gt;, &lt;code&gt;UniqueDeque&lt;/code&gt;, &lt;code&gt;RigidSet&lt;/code&gt;, &lt;code&gt;UniqueSet&lt;/code&gt;, &lt;code&gt;RigidDictionary&lt;/code&gt;, &lt;code&gt;UniqueDictionary&lt;/code&gt; 모두 표준 라이브러리에 추가될 잠재적 후보들이에요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Container 프로토콜&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 제안이 두 배열 타입에 &lt;code&gt;BorrowingSequence&lt;/code&gt; 채택을 더하긴 하지만, 그 위에 컨테이너 프로토콜을 제안할 준비는 아직 안 됐어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;swift-collections에서 &lt;a href=&quot;https://github.com/apple/swift-collections/tree/1.4.1/Sources/ContainersPreview/Protocols/Container&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이런 추상화를 위한 설계 접근을 탐색&lt;/a&gt; 중입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;리터럴 초기화&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;제안된 배열 타입들은 원소가 copyable이든 아니든 &lt;code&gt;ExpressibleByArrayLiteral&lt;/code&gt;을 채택하지 않아요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;기존 프로토콜은 variadic 이니셜라이저를 통한 &lt;code&gt;Array&lt;/code&gt; 인스턴스 구성 위에 만들어져 있어서 일반화하기 쉽지 않고, &lt;code&gt;RigidArray&lt;/code&gt;/&lt;code&gt;UniqueArray&lt;/code&gt; 초기화가 임시 &lt;code&gt;Array&lt;/code&gt; 인스턴스를 거치도록 강제하면 이 타입들의 성능 목표를 만족시킬 수 없어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;대신 target 타입 저장 버퍼 위의 &lt;code&gt;OutputSpan&lt;/code&gt; 인스턴스를 채우는 방식으로 배열 리터럴 초기화를 재구성하는 방법을 하나 생각해볼 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;protocol ArrayLiterable: ~Copyable {
  associatedtype ArrayLiteralElement: ~Copyable

  init(
    arrayLiteralCount count: Int, 
    initializingWith initializer: (inout OutputSpan) throws(E) -&amp;gt; Void
  ) throws(E)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 방식이라면 타입 컨텍스트 T에서 &lt;code&gt;[a, b, c, d]&lt;/code&gt; 같은 배열 초기화 표현이 대략 이렇게 확장될 거예요.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;less&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;T(arrayLiteralCount: 4) { target in
  target.append(a)
  target.append(b)
  target.append(c)
  target.append(d)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;(T가 연속된 저장소를 갖는다고 가정한 것이고, 불연속적인 target 저장소를 초기화하도록 허용하는 건 항목을 반환하는 함수들의 inline array를 다루는 등 조금 더 까다로워요.) &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 방향이든 다른 방향이든, 후속 작업의 주제가 될 것으로 예상합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Alternatives Considered&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Allocator 인자와 비슷한 설정 값들&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;새 배열 타입을 제안하는 김에, 커스텀 allocator로 이 자료구조들을 할당할 수 있게 하는 방법도 고려했어요.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;public struct UniqueArray: ~Copyable {}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;allocator 제네릭 인자를 추가하는 건 C++이나 Rust의 컨테이너 타입과 비슷한 방식이에요. 이러려면 커스텀 allocator가 채택할 &lt;code&gt;Allocator&lt;/code&gt; 프로토콜과, 표준 라이브러리 기본으로 제공되는 &lt;code&gt;SystemAllocator&lt;/code&gt; 같은 것이 필요합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;protocol Allocator {
  func allocate(_: T.Type) -&amp;gt; UnsafeMutablePointer
  func deallocate(_: UnsafeMutablePointer)
  ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;하지만 이런 타입 인자는 함수 시그니처를 훨씬 번거롭게 만들어요.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;ada&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;func foo(_ x: borrowing UniqueArray)
// error: generic type 'UniqueArray' specialized with too few type parameters (got 1, but expected 2)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;C++과 Rust는 제네릭 타입 매개변수에 기본값을 허용해서 이 문제를 풀지만, Swift에는 아직 그런 언어 기능이 없어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;설령 있다 해도 &lt;code&gt;foo(_:)&lt;/code&gt;가 시스템 allocator를 쓰도록 과도하게 제약해버리는 더 나쁜 문제가 생겨요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;unique array를 그냥 borrow하는 함수는 어떤 allocator를 쓰는지 신경 쓸 이유가 없거든요 (어차피 mutate할 방법도 없으니까요). 결국 &lt;code&gt;foo&lt;/code&gt;도 제네릭이 되어야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;func foo(_ x: borrowing UniqueArray&amp;lt;Int, some Allocator&amp;gt;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;배열을 consume하거나 mutate하려는 함수라면 이 allocator 인자를 이름 붙여서 코드베이스 전체에 전파해야 하는 경우가 잦아, 인터페이스 정의를 오염시키고 코드를 흐릴 수 있어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이런 타입 인자 오염은 C++ 개발자들의 흔한 불만이기도 하죠. 게&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;다가 &lt;code&gt;Allocator&lt;/code&gt; 추상화는 구현체가 copyable이어야 하는지, allocate/deallocate가 mutating으로 표시돼서 동시 사용과 호환이 안 되는 건 아닌지, 애초에 Swift 개발자들이 allocator를 어떻게 구현해야 하는지 같은 질문도 남겨요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;무엇보다 allocator는 unsafe 포인터를 다루기 때문에 Swift 메모리 안전성 스토리에 눈에 띄는 구멍이 될 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;RigidArray/UniqueArray가 Array와 저장 표현을 공유하게 하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;UniqueArray는 사실 RigidArray 인스턴스를 감싼 얇은 wrapper 타입이라 서로  (1) 복잡도로 변환 가능해요.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;클래식 &lt;code&gt;Array&lt;/code&gt;도 이 상호 변환 가능한 패밀리에 들어오면 좋겠지만, &lt;code&gt;Array&lt;/code&gt;의 저장 표현은 ABI의 일부라 변경할 수 없어요. &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;RigidArray&lt;/code&gt;/&lt;code&gt;UniqueArray&lt;/code&gt;가 tail-allocated 저장소를 갖는 특정 제네릭 클래스를 중심으로 지어진 그 표현을 그대로 빌려오는 건 부적절할 거예요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;같은 표현을 쓰면 새 low-level 타입에 불필요한 성능 오버헤드가 생겨서 경쟁 시스템 프로그래밍 언어의 비슷한 타입들과 경쟁력이 떨어질 수 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;그래서 &lt;code&gt;Array&lt;/code&gt;와 새 타입 사이의 변환은 새로 할당한 저장소로 원소를 복사/이동하는 선형 시간 연산이 필요하고, 실제로는 큰 문제가 되지 않을 것으로 봅니다&lt;/b&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Array를 noncopyable 원소를 지원하도록 일반화하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;copy-on-write 값 시맨틱스가 Array와 다른 표준 Collection 타입들, 그리고 Swift 자체의 핵심 특징이라고 생각해요.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;Array&lt;/code&gt;를 조건부로 noncopyable하게 만들거나 copy-on-write 동작을 조건화하는 건 Swift Ownership Manifesto의 목표에 오히려 반하고, 실제로도 실용적이지 않다고 봅니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그리고 그런 작업을 하더라도 이 문서가 제안하는 전용 fixed-capacity/guaranteed-noncopyable 배열 variant의 필요성이 사라지진 않아요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt; &lt;code&gt;Element&lt;/code&gt;가 copyable이라는 이유만으로 개발자에게 동적으로 크기가 조정되는 copy-on-write &lt;code&gt;Array&lt;/code&gt;를 강제하는 건 적절하지 않으니까요. &lt;code&gt;Array&lt;/code&gt;가 언젠가 noncopyable 콘텐츠를 지원하게 되든 안 되든, 정수용 &lt;code&gt;RigidArray&lt;/code&gt;나 float용 &lt;code&gt;UniqueArray&lt;/code&gt;에 대한 실질적이고 시급한 수요가 있습니다. 다만 이 제안이 그런 미래 작업을 막는 건 전혀 아니에요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 타입들을 기본 Swift 모듈로 옮기기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 타입들이 Swift 개발자의 기본 네임스페이스에 들어가야 한다고는 생각하지 않아요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Array는 여전히 모두의 첫 번째 선택이어야 하니까요.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 배열 타입들의 추가가 &lt;code&gt;Array&lt;/code&gt;를 대체하는 게 아니라, 더 제약된 환경에서 작업할 때 쓸 수 있는 대안적인 도구일 뿐입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&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;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Conclusion&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;SE-0527은 표준 라이브러리에 &lt;code&gt;RigidArray&lt;/code&gt;와 &lt;code&gt;UniqueArray&lt;/code&gt;라는 두 개의 noncopyable 지원 배열 타입을 가져다줘요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;copy-on-write와 암묵적 resize라는 &lt;code&gt;Array&lt;/code&gt;의 두 특징을 각각 유연하게 켜고 끌 수 있게 설계된 셈인데, &lt;code&gt;RigidArray&lt;/code&gt;는 고정 capacity로 예측 가능한 성능을, &lt;code&gt;UniqueArray&lt;/code&gt;는 기하급수적 성장 곡선으로 편리한 동적 크기 조정을 제공합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;둘 다 noncopyable 원소를 자연스럽게 담을 수 있어서, 그동안 &lt;code&gt;Array&lt;/code&gt;로는 손댈 수 없었던 고성능&amp;middot;저수준 영역에서 Swift가 훨씬 쓸모 있어질 것 같습니다  &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&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;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;References&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1785628327727&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;swift-evolution/proposals/0527-rigidarray-uniquearray.md at main &amp;middot; swiftlang/swift-evolution&quot; data-og-description=&quot;This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0527-rigidarray-uniquearray.md&quot; data-og-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0527-rigidarray-uniquearray.md&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/G0k5v/dJMb8Z3Gcjl/ImgwAeLuLAuBqWxjnx26f1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/yYVuK/dJMb8Yp91PG/A3OoYHm0TqP3UeaOvzLnj0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0527-rigidarray-uniquearray.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0527-rigidarray-uniquearray.md&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/G0k5v/dJMb8Z3Gcjl/ImgwAeLuLAuBqWxjnx26f1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/yYVuK/dJMb8Yp91PG/A3OoYHm0TqP3UeaOvzLnj0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;swift-evolution/proposals/0527-rigidarray-uniquearray.md at main &amp;middot; swiftlang/swift-evolution&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>Swift</category>
      <category>array</category>
      <category>noncopyable</category>
      <category>RigidArray</category>
      <category>SE-0527</category>
      <category>SWIFT</category>
      <category>UniqueArray</category>
      <author>GREEN.1229</author>
      <guid isPermaLink="true">https://green1229.tistory.com/631</guid>
      <comments>https://green1229.tistory.com/631#entry631comment</comments>
      <pubDate>Sun, 2 Aug 2026 08:53:35 +0900</pubDate>
    </item>
    <item>
      <title>[SE-0525] Safe loading API for RawSpan</title>
      <link>https://green1229.tistory.com/630</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;안녕하세요. &lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;그린&lt;/b&gt;&lt;/span&gt;입니다  &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이번 포스팅에서는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;SE-0525 &amp;mdash; RawSpan을 위한 안전한 로딩 API에 대해 정리&lt;/b&gt;&lt;/span&gt;해보겠습니다  &lt;/span&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;sadfs.001.jpeg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AQLht/dJMcafgrfPc/Ca52KdkItevhXPESPYu7xk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AQLht/dJMcafgrfPc/Ca52KdkItevhXPESPYu7xk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AQLht/dJMcafgrfPc/Ca52KdkItevhXPESPYu7xk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAQLht%2FdJMcafgrfPc%2FCa52KdkItevhXPESPYu7xk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;400&quot; data-filename=&quot;sadfs.001.jpeg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Intro&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;div style=&quot;background: #f2f8ee; border-radius: 10px; padding: 16px 20px; margin: 16px 0;&quot;&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Proposal:&lt;/b&gt; SE-0525&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Author:&lt;/b&gt; Guillaume Lessard&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Review Manager:&lt;/b&gt; Xiaodi Wu&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Status:&lt;/b&gt; Implemented (Swift 6.4)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Related Proposals:&lt;/b&gt; SE-0447&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Motivation&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;SE-0447에서 &lt;code&gt;RawSpan&lt;/code&gt;을 도입하면서 임의 타입의 값을 로드할 수 있는 unsafe 함수들도 함께 들어왔어요  &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;네이티브 정수 타입처럼 그중 일부는 로드해도 실제로 안전한데도, &lt;b&gt;&lt;code&gt;unsafe&lt;/code&gt;라는 표시 때문에 사용하는 입장에서는 늘 의심이 생기기 마련입니다  &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이번 제안은 &lt;b&gt;byte-loading 연산 중 안전한 것들을 명확히 구분해주는 게 목표&lt;/b&gt;예요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;그리고 안전한 byte-loading을 정의하려면 안전한 byte-storing도 함께 정리해야 해서, 이 제안은 그 부분도 함께 다룹니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Proposed Solution&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;두 개의 새 프로토콜을 제안합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;초기화된 타입 값과 초기화된 raw 바이트 사이의 변환을 지원하는 프로토콜&lt;/b&gt;이에요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;하나는 항상 안전하게 raw 바이트로 읽을 수 있는 타입이 채택하는 &lt;code&gt;ConvertibleToBytes&lt;/code&gt;, 다른 하나는 raw 바이트에서 항상 안전하게 해석될 수 있는 타입이 채택하는 &lt;code&gt;ConvertibleFromBytes&lt;/code&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;ConvertibleToBytes&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;어떤 타입의 값으로 메모리를 초기화할 때, 그 타입의 stride를 이루는 &lt;b&gt;모든 바이트가 초기화되어야 한다면 &lt;code&gt;ConvertibleToBytes&lt;/code&gt;를 채택할 수 있어요.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;less&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;@_marker protocol ConvertibleToBytes: Copyable {}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;메모리 표현에 패딩이 전혀 없는 타입, 즉 저장 프로퍼티 크기의 합이 stride와 같은 타입이 채택할 수 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;예를 들어 &lt;code&gt;Optional&amp;lt;Int16&amp;gt;&lt;/code&gt;은 stride 4바이트 중 3바이트만 쓰기 때문에 채택할 수 없지만, &lt;code&gt;struct Pair { var a, b: Int16 }&lt;/code&gt;는 크기와 stride가 같아서 채택 가능해요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ConvertibleToBytes를 채택하려면 다음 조건을 만족해야 합니다.&lt;/span&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;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;하나 이상의 저장 프로퍼티를 가질 것&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;모든 저장 프로퍼티가 &lt;code&gt;ConvertibleToBytes&lt;/code&gt;를 채택한 타입일 것&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;저장 프로퍼티들이 패딩 없이 메모리에 연속적으로 저장될 것&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;어떤 값도 자신의 바이트 일부를 무시하지 않을 것 (대부분의 enum이 여기서 제외됩니다)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;표준 라이브러리의 많은 기본 타입은 이 프로토콜을 채택하지만, 표준 라이브러리 바깥의 타입은 처음에는 채택할 수 없어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;ConvertibleToBytes&lt;/code&gt; 채택 선언은 그 타입을 담고 있는 모듈에서만 할 수 있습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;ConvertibleFromBytes&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre class=&quot;less&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;@_marker protocol ConvertibleFromBytes: BitwiseCopyable {}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;저장 프로퍼티를 이루는 모든 바이트의 모든 비트 패턴이 유효한 타입이라면 &lt;code&gt;ConvertibleFromBytes&lt;/code&gt;를 채택할 수 있어요. &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;내부나 trailing 패딩이 있는 타입도 허용되지만, 저장 프로퍼티 값에 의미론적인 제약이 있으면 안 됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;예를 들어 &lt;code&gt;struct Point { var x, y: Int }&lt;/code&gt;는 x, y 사이에 아무 제약이 없어서 채택 가능하지만, &lt;code&gt;Range&amp;lt;Int&amp;gt;&lt;/code&gt;는 &lt;code&gt;lowerBound &amp;lt;= upperBound&lt;/code&gt;라는 의미론적 제약이 있어서 채택할 수 없어요.&lt;/span&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;UnicodeScalar&lt;/code&gt;(일부 비트 패턴이 무효), 가상의 UTF8 &lt;code&gt;SmallString&lt;/code&gt;(바이트 순서가 유효성에 영향), &lt;code&gt;UnsafeRawPointer&lt;/code&gt;(런타임 전까지 값의 유효성을 알 수 없음) 등도 채택할 수 없는 예시예요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;컴파일러가 &lt;code&gt;ConvertibleFromBytes&lt;/code&gt;의 의미론적 요구사항을 강제할 수 없기 때문에, 표준 라이브러리 바깥의 타입은 unchecked conformance로만 채택할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;css&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension MyType: @unchecked ConvertibleFromBytes {}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;FullyInhabited&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre class=&quot;1c&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;typealias FullyInhabited = ConvertibleToBytes &amp;amp; ConvertibleFromBytes&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;ConvertibleToBytes&lt;/code&gt;와 &lt;code&gt;ConvertibleFromBytes&lt;/code&gt;의 교집합이에요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;RawSpan과 MutableRawSpan&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;RawSpan&lt;/code&gt;과 &lt;code&gt;MutableRawSpan&lt;/code&gt;에 제네릭한 &lt;code&gt;load(as:)&lt;/code&gt; 함수가 새로 생겨요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;포인터 정렬 제약 없이 &lt;code&gt;ConvertibleFromBytes&lt;/code&gt; 값을 읽어올 수 있고, bounds-checked라서 이 함수는 안전합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension RawSpan {
  func load(
    fromByteOffset: Int,
    as: T.Type = T.self
  ) -&amp;gt; T
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;추가로, &lt;code&gt;ConvertibleFromBytes&lt;/code&gt;와 &lt;code&gt;FixedWidthInteger&lt;/code&gt;를 동시에 채택한 타입을 위해 byte order를 지정할 수 있는 버전도 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension RawSpan {
  func load(
    fromByteOffset: Int,
    as: T.Type = T.self,
    _ byteOrder: ByteOrder
  ) -&amp;gt; T
}

@frozen
enum ByteOrder: Equatable, Hashable, Sendable {
  case bigEndian, littleEndian
  
  static var native: Self { get }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;ConvertibleFromBytes &amp;amp; FixedWidthInteger&lt;/code&gt;를 채택하는 표준 라이브러리 타입 목록은 &lt;code&gt;UInt8&lt;/code&gt;, &lt;code&gt;Int8&lt;/code&gt;, &lt;code&gt;UInt16&lt;/code&gt;, &lt;code&gt;Int16&lt;/code&gt;, &lt;code&gt;UInt32&lt;/code&gt;, &lt;code&gt;Int32&lt;/code&gt;, &lt;code&gt;UInt64&lt;/code&gt;, &lt;code&gt;Int64&lt;/code&gt;, &lt;code&gt;UInt&lt;/code&gt;, &lt;code&gt;Int&lt;/code&gt;, &lt;code&gt;UInt128&lt;/code&gt;, &lt;code&gt;Int128&lt;/code&gt;이에요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이 &lt;code&gt;load(as:)&lt;/code&gt; 함수들은 atomic 연산이 아니고, unchecked byte offset 버전은 제공되지 않아요 (필요하면 기존 &lt;code&gt;unsafeLoad(fromUncheckedByteOffset:as:)&lt;/code&gt;를 쓰면 됩니다).&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;RawSpan 계열의 subscript&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;UInt8&lt;/code&gt;을 위한 편의 기능으로, 기존 &lt;code&gt;Span&lt;/code&gt;, &lt;code&gt;MutableSpan&lt;/code&gt;, &lt;code&gt;OutputSpan&lt;/code&gt;과 비슷한 subscript를 &lt;code&gt;RawSpan&lt;/code&gt;, &lt;code&gt;MutableRawSpan&lt;/code&gt;, &lt;code&gt;OutputRawSpan&lt;/code&gt;에도 정의합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension RawSpan {
  subscript(_ byteOffset: Int) -&amp;gt; UInt8 { get }
  
  @unsafe
  subscript(unchecked byteOffset: Int) -&amp;gt; UInt8 { get }
}

extension MutableRawSpan {
  subscript(_ byteOffset: Int) -&amp;gt; UInt8 { get set }

  @unsafe
  subscript(unchecked byteOffset: Int) -&amp;gt; UInt8 { get set }
}

extension OutputRawSpan {
  subscript(_ byteOffset: Int) -&amp;gt; UInt8 { get set }

  @unsafe
  subscript(unchecked byteOffset: Int) -&amp;gt; UInt8 { get set }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;MutableRawSpan과 OutputRawSpan&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;MutableRawSpan&lt;/code&gt;에는 &lt;code&gt;storeBytes()&lt;/code&gt;의 새 오버로드가 추가돼요.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension MutableRawSpan {
  mutating func storeBytes(
    of value: T,
    toByteOffset offset: Int,
    as type: T.Type,
    _ byteOrder: ByteOrder
  ) where T: ConvertibleToBytes &amp;amp; BitwiseCopyable &amp;amp; FixedWidthInteger
  
  @unsafe
  mutating func storeBytes(
    repeating repeatedValue: T,
    count: Int,
    as type: T.Type
  ) where T: BitwiseCopyable

  mutating func storeBytes(
    repeating repeatedValue: T,
    count: Int,
    as type: T.Type,
    _ byteOrder: ByteOrder
  ) where T: ConvertibleToBytes &amp;amp; BitwiseCopyable &amp;amp; FixedWidthInteger
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;기존 &lt;code&gt;T: BitwiseCopyable&lt;/code&gt;로 제약된 &lt;code&gt;storeBytes&lt;/code&gt; 함수는 &lt;code&gt;@unsafe&lt;/code&gt;로 표시됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;컴파일러 최적화로 인해 초기화되지 않은 바이트가 생길 수 있기 때문이에요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;반복 저장 variant도 이번에 추가되는데, 이것도 &lt;code&gt;@unsafe&lt;/code&gt;로 표시됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;OutputRawSpan에는 대응하는 append() 함수가 생겨요.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension OutputRawSpan {
  mutating func append(
    _ value: T,
    as type: T.Type
  ) where T: ConvertibleToBytes &amp;amp; BitwiseCopyable

  mutating func append(
    _ value: T,
    as type: T.Type,
    _ byteOrder: ByteOrder
  ) where T: ConvertibleToBytes &amp;amp; BitwiseCopyable &amp;amp; FixedWidthInteger
  
  mutating func append(
    repeating repeatedValue: T,
    count: Int,
    as type: T.Type
  ) where T: ConvertibleToBytes &amp;amp; BitwiseCopyable
  
  mutating func append(
    repeating repeatedValue: T,
    count: Int,
    as type: T.Type,
    _ byteOrder: ByteOrder
  ) where T: ConvertibleToBytes &amp;amp; BitwiseCopyable &amp;amp; FixedWidthInteger
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;기존 &lt;code&gt;T: BitwiseCopyable&lt;/code&gt;만으로 제약된 &lt;code&gt;append&lt;/code&gt; 함수도 &lt;code&gt;@unsafe&lt;/code&gt;로 표시됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;border-left: 4px solid #3a8c28; background: #f2f8ee; padding: 8px 16px; margin: 16px 0;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;여기서 제안하는 타입들의 메모리 레이아웃은 컴파일러/라이브러리 버전에 걸쳐 안정적이라고 보장되진 않아요. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;border-left: 4px solid #3a8c28; background: #f2f8ee; padding: 8px 16px; margin: 16px 0;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;실&lt;/span&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;행 중인 프로세스끼리 데이터를 주고받거나 같은 프로세스에서 나중에 쓰려고 저장하는 용도라면 문제없지만, 네트워크 통신이나 파일 시스템 저장을 위한 직렬화처럼 더 정교한 용도에는 이 API가 building block 정도로만 쓰일 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Span과 MutableSpan&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;Span&lt;/code&gt;에는 &lt;code&gt;init(viewing: RawSpan)&lt;/code&gt; 이니셜라이저가 새로 생겨서, &lt;code&gt;Span.Element&lt;/code&gt;가 &lt;code&gt;ConvertibleFromBytes&lt;/code&gt;를 채택했다면 정렬되지 않은 raw 메모리 범위를 typed &lt;code&gt;Span&lt;/code&gt;으로 볼 수 있어요. 정렬과 bounds를 검사하는데, &lt;code&gt;RawSpan&lt;/code&gt;의 포인터 정렬이 &lt;code&gt;Element&lt;/code&gt;에 맞지 않거나 bounds가 stride의 배수가 아니면 트랩이 발생합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension Span {
  @_lifetime(copy bytes)
  init(viewing bytes: RawSpan) where Element: ConvertibleFromBytes
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;MutableSpan&lt;/code&gt;에도 &lt;code&gt;MutableRawSpan&lt;/code&gt;의 메모리를 typed &lt;code&gt;MutableSpan&lt;/code&gt;처럼 mutate할 수 있는 이니셜라이저가 추가돼요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;마찬가지로 정렬과 bounds를 검사해서 맞지 않으면 트랩합니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;less&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension MutableSpan {
  @_lifetime(&amp;amp;mutableBytes)
  init(mutating mutableBytes: inout MutableRawSpan)
    where Element: ConvertibleToBytes &amp;amp; ConvertibleFromBytes

  @_lifetime(copy mutableBytes)
  init(mutableBytes: consuming MutableRawSpan)
    where Element: ConvertibleToBytes &amp;amp; ConvertibleFromBytes
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;RawSpan&lt;/code&gt;에서 &lt;code&gt;Span&lt;/code&gt;으로의 변환은 정렬이 잘 맞고 네이티브 byte order인 경우만 지원해요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;더 복잡한 파싱이 필요하다면 &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/apple/swift-binary-parsing&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;swift-binary-parsing&lt;/a&gt; 패키지의 &lt;code&gt;ParserSpan&lt;/code&gt; 타입을 참고하면 됩니다. &lt;code&gt;RawSpan&lt;/code&gt;의 메모리 정렬을 확인하는 기능은 추후 별도 제안으로 다뤄질 예정이에요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;기존 &lt;code&gt;bytes&lt;/code&gt;, &lt;code&gt;mutableBytes&lt;/code&gt; accessor도 &lt;code&gt;Element&lt;/code&gt;가 각각 &lt;code&gt;ConvertibleToBytes&lt;/code&gt;, &lt;code&gt;ConvertibleToBytes &amp;amp; ConvertibleFromBytes&lt;/code&gt;를 채택했을 때 안전한 오버로드를 갖게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Detailed Design&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;표준 라이브러리 채택 목록&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;여러 정수/부동소수점 타입, &lt;code&gt;Duration&lt;/code&gt;, &lt;code&gt;InlineArray&lt;/code&gt;, &lt;code&gt;CollectionOfOne&lt;/code&gt;, 여러 &lt;code&gt;SIMD&lt;/code&gt; 타입, 범위 타입 일부, &lt;code&gt;Bool&lt;/code&gt;, &lt;code&gt;ObjectIdentifier&lt;/code&gt;, 각종 포인터 타입 등에 다음과 같이 채택이 추가&lt;/b&gt;됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;puppet&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension UInt8:   ConvertibleToBytes, ConvertibleFromBytes {}
extension Int8:    ConvertibleToBytes, ConvertibleFromBytes {}
extension UInt16:  ConvertibleToBytes, ConvertibleFromBytes {}
extension Int16:   ConvertibleToBytes, ConvertibleFromBytes {}
extension UInt32:  ConvertibleToBytes, ConvertibleFromBytes {}
extension Int32:   ConvertibleToBytes, ConvertibleFromBytes {}
extension UInt64:  ConvertibleToBytes, ConvertibleFromBytes {}
extension Int64:   ConvertibleToBytes, ConvertibleFromBytes {}
extension UInt:    ConvertibleToBytes, ConvertibleFromBytes {}
extension Int:     ConvertibleToBytes, ConvertibleFromBytes {}

extension UInt128: ConvertibleToBytes, ConvertibleFromBytes {}
extension Int128:  ConvertibleToBytes, ConvertibleFromBytes {}

extension Float16: ConvertibleToBytes, ConvertibleFromBytes {}
extension Float32: ConvertibleToBytes, ConvertibleFromBytes {} // 'Float'
extension Float64: ConvertibleToBytes, ConvertibleFromBytes {} // 'Double'

extension Duration: ConvertibleToBytes, ConvertibleFromBytes {}

extension InlineArray: ConvertibleToBytes
  where Element: ConvertibleToBytes {}
extension InlineArray: ConvertibleFromBytes
  where Element: ConvertibleFromBytes {}

extension CollectionOfOne: ConvertibleToBytes
  where Element: ConvertibleToBytes {}
extension CollectionOfOne: ConvertibleFromBytes
  where Element: ConvertibleFromBytes {}

extension SIMD2: ConvertibleToBytes
  where Scalar: ConvertibleToBytes {}
extension SIMD4: ConvertibleToBytes
  where Scalar: ConvertibleToBytes {}
extension SIMD8: ConvertibleToBytes
  where Scalar: ConvertibleToBytes {}
extension SIMD16: ConvertibleToBytes
  where Scalar: ConvertibleToBytes {}
extension SIMD32: ConvertibleToBytes
  where Scalar: ConvertibleToBytes {}
extension SIMD64: ConvertibleToBytes
  where Scalar: ConvertibleToBytes {}

extension SIMD2: ConvertibleFromBytes
  where Scalar: ConvertibleFromBytes {}
extension SIMD3: ConvertibleFromBytes
  where Scalar: ConvertibleFromBytes {}
extension SIMD4: ConvertibleFromBytes
  where Scalar: ConvertibleFromBytes {}
extension SIMD8: ConvertibleFromBytes
  where Scalar: ConvertibleFromBytes {}
extension SIMD16: ConvertibleFromBytes
  where Scalar: ConvertibleFromBytes {}
extension SIMD32: ConvertibleFromBytes
  where Scalar: ConvertibleFromBytes {}
extension SIMD64: ConvertibleFromBytes
  where Scalar: ConvertibleFromBytes {}

extension ClosedRange: ConvertibleToBytes
  where Bound: ConvertibleToBytes {}
extension Range: ConvertibleToBytes
  where Bound: ConvertibleToBytes {}

extension PartialRangeFrom: ConvertibleToBytes
  where Bound: ConvertibleToBytes {}
extension PartialRangeFrom.Iterator: ConvertibleToBytes
  where Bound: ConvertibleToBytes {}
extension PartialRangeThrough: ConvertibleToBytes
  where Bound: ConvertibleToBytes {}
extension PartialRangeUpTo: ConvertibleToBytes
  where Bound: ConvertibleToBytes {}

extension Bool: ConvertibleToBytes {}
extension ObjectIdentifier: ConvertibleToBytes {}

extension UnsafePointer: ConvertibleToBytes {}
extension UnsafeMutablePointer: ConvertibleToBytes {}
extension UnsafeRawPointer: ConvertibleToBytes {}
extension UnsafeMutableRawPointer: ConvertibleToBytes {}
extension OpaquePointer: ConvertibleToBytes {}

extension UnsafeBufferPointer: ConvertibleToBytes {}
extension UnsafeMutableBufferPointer: ConvertibleToBytes {}
extension UnsafeRawBufferPointer: ConvertibleToBytes {}
extension UnsafeMutableRawBufferPointer: ConvertibleToBytes {}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;border-left: 4px solid #3a8c28; background: #f2f8ee; padding: 8px 16px; margin: 16px 0;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;위 목록 중 &lt;code&gt;BitwiseCopyable&lt;/code&gt; 채택이 없던 타입은 이번에 함께 채택하게 됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;border-left: 4px solid #3a8c28; background: #f2f8ee; padding: 8px 16px; margin: 16px 0;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;그리고 &lt;code&gt;SIMD3&lt;/code&gt;는 &lt;code&gt;SIMD4&lt;/code&gt;와 저장 공간이 같지만 한 원소만큼 tail padding이 있어서 &lt;code&gt;ConvertibleToBytes&lt;/code&gt;를 채택하지 못해요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;안전한 최상위 bitCast 함수&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;두 프로토콜 덕분에 타입을 안전하게 재해석하는 함수도 정의할 수 있게 됐어요.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;func bitCast&amp;lt;T, U&amp;gt;(_ original: T, to type: U.Type) -&amp;gt; U
  where T: ConvertibleToBytes, U: ConvertibleFromBytes&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Source Compatibility&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이번 제안은 &lt;b&gt;오직 추가로만 이루어져 있어서 소스 호환성을 유지&lt;/b&gt;합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;다만 오버로드를 추가하는 건 언제나 리스크가 있어서, 기존의 유효한 코드에 영향을 줄 가능성도 있어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;중대한 호환성 이슈가 없는지 확인하려면 테스트가 필요합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;ABI Compatibility&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;이번에 추가되는 함수들은 추가 ABI를 만들지 않는 방식으로 구현될 예정&lt;/b&gt;이에요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이 함수들은 &lt;code&gt;Span&lt;/code&gt;의 존재를 전제로 하기 때문에, Darwin 플랫폼에서는 Swift 표준 라이브러리가 OS와 함께 배포되는 만큼 최소 배포 타깃이 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;ByteOrder&lt;/code&gt;는 새 타입이라 자체 availability를 가지며, &lt;code&gt;ByteOrder&lt;/code&gt; 인자를 쓰는 함수들도 같은 availability를 공유합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Implications on Adoption&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번 제안의 추가 사항들은 새 버전의 Swift 표준 라이브러리를 필요로 합니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Future Directions&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;ConvertibleToBytes 프로토콜에 대한 검증&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;ConvertibleToBytes&lt;/code&gt; 채택은 나중에 컴파일러가 추가로 검증하게 될 거예요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이 프로토콜은 addressable 메모리 상의 레이아웃에만 의존하기 때문에 컴파일 타임에 완전히 검증할 수 있고, &lt;code&gt;BitwiseCopyable&lt;/code&gt;처럼 자동화도 가능할 것으로 보입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;검증과 함께, 패딩 대신 저장된 null 바이트를 자동으로 넣어주는 방식도 고려할 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;ConvertibleFromBytes 프로토콜에 대한 부분적 검증&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;&lt;code&gt;ConvertibleFromBytes&lt;/code&gt; 채택도 나중에 어느 정도 검증될 수 있어요.&lt;/b&gt; 컴&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;파일러는 모든 저장 프로퍼티가 &lt;code&gt;ConvertibleFromBytes&lt;/code&gt;를 채택했는지는 강제할 수 있지만, 의미론적 제약의 부재까지 직접 강제할 순 없습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;다만 모든 저장 프로퍼티가 &lt;code&gt;public&lt;/code&gt;이고 &lt;code&gt;var&lt;/code&gt;인 경우처럼 우회적인 방법을 받아들일 수도 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;C에서 import된 타입 지원&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Clang importer가 어떤 기본 C 타입이 이 프로토콜들을 지원하는지 알도록 만들 수도 있어요. &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;aggregate C 타입에 대해서도 이 프로토콜 채택을 선언할 방법이 있으면 좋겠는데, 이를 위해 &quot;채택 선언은 타입을 담은 모듈에서만 가능하다&quot;는 제약을 import된 C 타입에 한해 완화하는 것도 유용할 것 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;튜플 지원&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;ConvertibleToBytes&lt;/code&gt; 타입으로 구성된 튜플은 그 자체로 &lt;code&gt;ConvertibleToBytes&lt;/code&gt;여야 하고, &lt;code&gt;ConvertibleFromBytes&lt;/code&gt;도 마찬가지예요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;RawSpan의 정렬 상태를 확인하는 유틸리티&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;Span&lt;/code&gt; 이니셜라이저들은 올바르게 정렬된 &lt;code&gt;RawSpan&lt;/code&gt;을 요구하는데, 특정 타입에 대해 잘 정렬된 오프셋을 확인하는 유틸리티가 있으면 좋을 것 같다고 제안하고 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;@unsafe 함수/프로퍼티 이름 재정비&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이전 제안에서 도입된 일부 함수/프로퍼티는 나중에 unsafe로 표시됐지만, 이름 자체에는 그 사실이 드러나지 않아요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;strict memory safety 모드가 꺼져 있어도 unsafe함을 드러내는 이름들을 식별해서, 별도 제안을 통해 최소한의 혼란으로 이름을 바꾸는 계획이 필요합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;OutputSpan과 OutputRawSpan 사이의 append 지원&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;원래 이 제안에는 &lt;code&gt;Element&lt;/code&gt;가 &lt;code&gt;ConvertibleFromBytes&lt;/code&gt;일 때 &lt;code&gt;OutputRawSpan&lt;/code&gt;으로 &lt;code&gt;OutputSpan&lt;/code&gt;의 일부에 append하는 함수도 포함되어 있었어요.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;stata&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;span.append(upTo: capacity) { for _ in 0..&amp;lt;$0.capacity { $0.append(UInt8.zero) } }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;capacity를 위한 인자 레이블(여기선 &quot;upTo&quot;)을 정하는 게 까다로운 주제라, &lt;code&gt;UniqueArray&lt;/code&gt;의 &lt;code&gt;insert&lt;/code&gt;, &lt;code&gt;replace&lt;/code&gt;, &lt;code&gt;append&lt;/code&gt;에도 같은 형태의 API가 필요하다는 점을 짚었어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이 네이밍은 &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0527-rigidarray-uniquearray.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SE-0527&lt;/a&gt;(UniqueArray와 RigidArray) 쪽에서 충분히 논의된 뒤, &lt;code&gt;OutputSpan&lt;/code&gt;과 &lt;code&gt;OutputRawSpan&lt;/code&gt;에 적절한 variant와 함께 추가하자는 방향으로 정리됐습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Alternatives Considered&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;함수 이름에 로드할 타입 이름을 인코딩하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;loadInt32(fromByteOffset:_:)&lt;/code&gt;, &lt;code&gt;storeBytes(int32:toByteOffset:_:)&lt;/code&gt;처럼 구체적인 함수들을 따로 만들면 오버로드 문제를 피할 수 있어서 타입 체커 입장에서는 더 편할 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;컴파일러가 검증하는 ConvertibleToBytes 레이아웃 제약을 기다리기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이 제안이 다루는 기능은 시급하고, 표준 라이브러리 추가만으로도 달성할 수 있어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;ConvertibleToBytes&lt;/code&gt; 레이아웃 제약의 검증에는 상당한 컴파일러 작업이 필요한데, 이 문서가 제안하는 API만으로도 충분히 가치가 있다고 판단했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;FixedWidthInteger &amp;amp; BitwiseCopyable, BinaryFloatingPoint &amp;amp; BitwiseCopyable로 제네릭화하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이 프로토콜들은 채택자가 완전히 inhabited되어야 한다는 걸 보장하지 않아서 충분한 제약이 아니에요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;FullyInhabited 프로토콜 하나만 추가하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이 제안의 두 번째 pitch에서는 &lt;code&gt;FullyInhabited&lt;/code&gt; 하나만 제안했었어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;논의 결과 결국 두 프로토콜 쌍이 필요하다는 게 드러났고, 구현 부담도 비슷했기 때문에 두 프로토콜을 각각 구현하는 쪽이 더 나은 선택으로 정리됐습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;ByteOrder 파라미터 생략하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;표준 라이브러리의 &lt;code&gt;FixedWidthInteger&lt;/code&gt;에는 &lt;code&gt;.bigEndian&lt;/code&gt;, &lt;code&gt;.littleEndian&lt;/code&gt; 계산 프로퍼티가 있어서 이를 활용할 수도 있었어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;하지만 이 프로퍼티들은 &lt;code&gt;Self&lt;/code&gt;를 반환해서 byte ordering과 유효한 값 자체를 혼동시키기 때문에 명확하지 않아요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이 제안은 byte ordering을 직렬화라는, 원래 있어야 할 자리에 적용합니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;안전한 load() 함수를 정렬된 연산으로 기본 설정하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;UnsafeRawPointer&lt;/code&gt;의 원래 &lt;code&gt;load()&lt;/code&gt;는 올바른 정렬을 요구했고, 나중에야 덜 제한적인 &lt;code&gt;loadUnaligned()&lt;/code&gt;가 추가됐어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이건 오랫동안 아쉬운 부분으로 여겨져 왔고, 이번 제안은 새 안전한 &lt;code&gt;load()&lt;/code&gt; 함수들이 정렬되지 않은 연산을 수행하도록 만들어서 이를 개선하려 하고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;toByteOffset, fromByteOffset 파라미터를 0으로 기본값 설정하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;원래는 이 파라미터들에 기본값을 두려고 했는데, 그러면 &lt;code&gt;RawSpan&lt;/code&gt;이나 &lt;code&gt;MutableRawSpan&lt;/code&gt;의 전체 길이를 반드시 써야 한다는 인상을 줄 수 있다는 지적이 있었어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;비슷한 기존 unsafe API에는 이미 기본값이 있다는 점을 감안해서, 이 결정은 나중에 조율이 필요할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Conclusion&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;ConvertibleToBytes&lt;/code&gt;와 &lt;code&gt;ConvertibleFromBytes&lt;/code&gt; 프로토콜 덕분에 그동안 &lt;code&gt;unsafe&lt;/code&gt; 딱지가 붙어 있던 &lt;code&gt;RawSpan&lt;/code&gt; byte-loading이 명확하게 안전한 영역과 그렇지 않은 영역으로 나뉘게 됐어요. &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;정수, 부동소수점, SIMD, 포인터 타입 등 표준 라이브러리의 많은 타입이 바로 이 프로토콜들을 채택하고, 안전한 &lt;code&gt;bitCast&lt;/code&gt;까지 함께 따라오면서 프로세스 간 데이터 전달이나 파싱 유틸리티를 만들 때 훨씬 믿음직한 building block이 생긴 셈입니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;References&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1785026198048&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;swift-evolution/proposals/0525-rawspan-safe-loading-api.md at main &amp;middot; swiftlang/swift-evolution&quot; data-og-description=&quot;This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0525-rawspan-safe-loading-api.md&quot; data-og-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0525-rawspan-safe-loading-api.md&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/d72kXJ/dJMb8RkfOpK/yKKBP6NU9Fy5j8GEglADA1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/GsVnz/dJMb9g5or29/BGBkCE5R8dUNpI5VE5m5BK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0525-rawspan-safe-loading-api.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0525-rawspan-safe-loading-api.md&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/d72kXJ/dJMb8RkfOpK/yKKBP6NU9Fy5j8GEglADA1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/GsVnz/dJMb9g5or29/BGBkCE5R8dUNpI5VE5m5BK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;swift-evolution/proposals/0525-rawspan-safe-loading-api.md at main &amp;middot; swiftlang/swift-evolution&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>Swift</category>
      <category>rawspan</category>
      <category>safe loading</category>
      <category>SE-0525</category>
      <category>SWIFT</category>
      <author>GREEN.1229</author>
      <guid isPermaLink="true">https://green1229.tistory.com/630</guid>
      <comments>https://green1229.tistory.com/630#entry630comment</comments>
      <pubDate>Sun, 26 Jul 2026 09:25:47 +0900</pubDate>
    </item>
    <item>
      <title>[SE-0532] Optional noncopyable improvements and generalizations</title>
      <link>https://green1229.tistory.com/629</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;안녕하세요. &lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;그린&lt;/b&gt;&lt;/span&gt;입니다  &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이번 포스팅에서는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;SE-0532 &amp;mdash; Optional noncopyable 개선 및 일반화&lt;/b&gt;&lt;/span&gt;에 대해 정리해보겠습니다  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;12313.001.jpeg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beTn2H/dJMcaccNloH/VWFh2ipFVLu7KUxK67ZMzk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beTn2H/dJMcaccNloH/VWFh2ipFVLu7KUxK67ZMzk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beTn2H/dJMcaccNloH/VWFh2ipFVLu7KUxK67ZMzk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeTn2H%2FdJMcaccNloH%2FVWFh2ipFVLu7KUxK67ZMzk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;400&quot; data-filename=&quot;12313.001.jpeg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Intro&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;div style=&quot;background: #f2f8ee; border-radius: 10px; padding: 16px 20px; margin: 16px 0;&quot;&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Proposal:&lt;/b&gt; SE-0532&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Author:&lt;/b&gt; Alejandro Alonso&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Review Manager:&lt;/b&gt; John McCall&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Status:&lt;/b&gt; Accepted&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 4px 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Implementation:&lt;/b&gt; swiftlang/swift#88505&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Motivation&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Swift 6.0에서 표준 라이브러리 일부가 noncopyable 값을 저장할 수 있도록 일반화된 이후&lt;/b&gt;(SE-0437), &lt;b&gt;noncopyable optional을 다루는 일은 꽤 번거로웠습니다.&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;optional 내부 값을 살짝 들여다보고 싶은 것뿐인데, borrow만 하고 싶을 때도 마땅한 방법이 없었거든요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아래 코드를 볼까요?&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre class=&quot;stylus&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;if let payload = optional {
  
}

foo(optional) // error: use after consume!&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;다행히 &lt;a href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0432-noncopyable-switch.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;noncopyable switch&lt;/a&gt;를 쓰면 optional의 내용을 borrow하도록 제어 흐름을 만들 수 있습니다.&lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;switch optional {
case .some(let wrapped):
  // wrapped는 borrow된 상태

default:
  break
}

foo(optional) // ok&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;하지만 &lt;code&gt;if let&lt;/code&gt;이나 &lt;code&gt;guard let&lt;/code&gt;에 익숙한 사람이라면 이 switch 문이 그리 직관적이진 않죠  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;값을 consume하지 않고 mutate만 하고 싶은 경우도 마찬가지예요. &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;단순한 프로퍼티 변경이나 mutating 메서드 호출 정도는 &lt;code&gt;?.&lt;/code&gt; 체이닝으로 충분하지만, payload를 조건부로 &lt;code&gt;inout&lt;/code&gt; 함수에 넘기고 싶다면 이렇게 써야 합니다.&lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;isbl&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;if someStruct.x != nil {
  foo(&amp;amp;someStruct.x!)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;혹은 switch로 consume한 뒤 다시 초기화하는, 더 장황하고 직관적이지 않은 방식을 써야 하죠.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;func foo(_: inout NoncopyableString) {}

func bar(_ x: inout NoncopyableString?) {
  switch consume x {
  case .some(var string):
    foo(&amp;amp;string)
    x = consume string

  default:
    x = nil
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;여기에 더해 &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;flatMap&lt;/code&gt;, &lt;code&gt;unsafelyUnwrapped&lt;/code&gt; 같은 &lt;code&gt;Optional&lt;/code&gt; API들도 noncopyable 래핑 타입에는 지원되지 않아서, 이런 코드를 매번 switch 문으로 직접 풀어써야 했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Proposed Solution&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;Optional&lt;/code&gt;에 새로운 프로퍼티 두 개, &lt;code&gt;ref&lt;/code&gt;와 &lt;code&gt;mutableRef&lt;/code&gt;를 추가합니다. &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 프로퍼티들은 내부 payload가 있으면 그 참조를, 없으면 &lt;code&gt;nil&lt;/code&gt;을 돌려줍니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;func bar(_ x: borrowing SomeNoncopyable) {
  ...
}

if let payload = optional.ref {
  bar(payload.value) // 'bar'는 'borrowing Wrapped'를 전달받음
}

foo(optional) // ok&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;func baz(_ x: inout SomeNoncopyable) {
  ...
}

if var payload = optional.mutableRef {
  baz(&amp;amp;payload.value) // 'baz'가 payload를 그 자리에서 mutate 가능!
}

foo(optional) // ok&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 두 프로퍼티 덕분에 &lt;b&gt;optional의 소유권을 가져오지 않고도 내부 값에 조건부로 접근하는 관용적인 방법&lt;/b&gt;이 생겼습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;더불어 아래 세 메서드도 noncopyable / nonescapable 래핑 타입을 지원하도록 일반화됩니다.&lt;/span&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;map&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;flatMap&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;unsafelyUnwrapped&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;vim&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;let optAtomicInt: Optional&amp;lt;Atomic&amp;gt; = ...
let optInt: Optional = optAtomicInt.map {
  $0.load(ordering: .relaxed)
}

let optInlineArray: Optional&amp;lt;[0 of Atomic]&amp;gt; = []
let optInt2: Optional = optInlineArray.flatMap {
  $0.isEmpty ? nil : $0[0].load(ordering: .relaxed)
}

let optMutex: Optional&amp;lt;Mutex&amp;gt; = ...
let mutex: Mutex = optMutex.unsafelyUnwrapped
optMutex?.withLock { ... } // error: use of 'optMutex' after consume&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;마지막으로 &lt;code&gt;Optional.put()&lt;/code&gt;이라는 편의 API도 추가돼요!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;아래처럼 &lt;code&gt;!&lt;/code&gt;로 강제 언래핑하던 패턴을 생각해볼게요.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;lasso&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;struct Cache: ~Copyable {
  var opt: UniqueArray?
}

var cache = Cache()
var items: UniqueArray = fooBar()
cache.opt = items

let newItem = await retrieveNewItem()
cache.opt!.append(newItem)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;border-left: 4px solid #3a8c28; background: #f2f8ee; padding: 8px 16px; margin: 16px 0;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이미 값이 있다는 걸 알고 있는 상황이라 &lt;code&gt;!&lt;/code&gt;가 사실 불필요하고, inline되지 않는 함수를 거치는 경우엔 컴파일러가 최적화해서 없애주지도 못해요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;put()&lt;/code&gt;은 새 값을 넣어주면서 그 payload에 대한 direct mutable reference를 바로 돌려줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;lasso&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;struct Cache: ~Copyable {
  var opt: UniqueArray?
}

var cache = Cache()
let items: UniqueArray = fooBar()
var itemsRef = cache.opt.put(items)

let newItem = await retrieveNewItem()
itemsRef.value.append(newItem)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Detailed Design&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ref와 mutableRef&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension Optional where Wrapped: ~Copyable &amp;amp; ~Escapable {
  /// optional 안에 payload가 있으면 그에 대한 borrow된 참조를 반환합니다.
  public var ref: Ref? {
    @lifetime(borrow self)
    get
  }
}

extension Optional where Wrapped: ~Copyable {
  /// optional 안에 payload가 있으면 그에 대한 mutable 참조를 반환합니다.
  public var mutableRef: MutableRef? {
    @lifetime(&amp;amp;self)
    mutating get
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;개념적으로 &lt;b&gt;이 프로퍼티들은 optional과 그 payload의 소유권을 옮기는 역할을 해요. &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;ref&lt;/code&gt;를 호출하려면 최소한 &lt;code&gt;borrowing Optional&amp;lt;T&amp;gt;&lt;/code&gt;, 즉 &lt;code&gt;Ref&amp;lt;Optional&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt;가 있어야 하는데, 이 &lt;code&gt;ref&lt;/code&gt;는 그 &lt;code&gt;Ref&amp;lt;Optional&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt;를 받아 &lt;code&gt;Optional&amp;lt;Ref&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt;로 만들어줍니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;참조를 optional 내부로 옮겨서, 우리가 mutate하거나 consume하거나 독점적으로 접근할 수 있는 owned 값을 돌려받는 셈이죠. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;mutableRef&lt;/code&gt;도 마찬가지로 최소 &lt;code&gt;inout Optional&amp;lt;T&amp;gt;&lt;/code&gt;를 받아 owned &lt;code&gt;Optional&amp;lt;MutableRef&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt; 값으로 바꿔줍니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;put()&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension Optional where Wrapped: ~Copyable {
  /// optional의 값을 새 값으로 설정하면서, optional 안에 새로 들어간
  /// payload에 대한 mutable 참조를 반환합니다.
  ///
  /// 이미 값이 있었다면 그 값은 destroy됩니다.
  @lifetime(&amp;amp;self)
  public mutating func put(_ new: consuming Wrapped) -&amp;gt; MutableRef
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;unsafelyUnwrapped 일반화&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension Optional where Wrapped: ~Copyable &amp;amp; ~Escapable {
  public var unsafelyUnwrapped: Wrapped {
    consuming get
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;map(), flatMap() 일반화&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;extension Optional where Wrapped: ~Copyable &amp;amp; ~Escapable {
  @lifetime(copy self)
  public consuming func map(
    _ transform: (consuming Wrapped) throws(E) -&amp;gt; Result
  ) throws(E) -&amp;gt; Result?

  @lifetime(copy self)
  public consuming func flatMap(
    _ transform: (consuming Wrapped) throws(E) -&amp;gt; Result?
  ) throws(E) -&amp;gt; Result?
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;사실 &lt;a href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0437-noncopyable-stdlib-primitives.md#enum-optional&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SE-0437&lt;/a&gt; 당시에는 이 일반화를 급하게 적용 하고 싶지 않았다고해요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;noncopyable 값을 다루는 &lt;code&gt;map&lt;/code&gt; / &lt;code&gt;flatMap&lt;/code&gt;에는 사실 세 가지 형태가 있을 수 있거든요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;optional 전체를 consume해서 owned 값을 클로저에 넘기거나, borrow해서 참조를 넘기거나, mutate해서 &lt;code&gt;inout&lt;/code&gt; 참조를 넘기거나. 셋 다 유용하지만, 전부 &lt;code&gt;map&lt;/code&gt;이라는 이름으로 오버로드하기엔 규칙상 구분할 방법이 없었죠. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그래서 이번 제안은 &lt;b&gt;이 일반화를 기본적으로 항상 consuming으로 동작하게 만들고, 대신 &lt;code&gt;ref()&lt;/code&gt; / &lt;code&gt;mutableRef()&lt;/code&gt;로 owned optional 값을 먼저 만들어서 나머지 두 형태를 구현&lt;/b&gt;할 수 있게 했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;func foo(x: consuming Optional&amp;lt;UniqueArray&amp;gt;) -&amp;gt; Optional {
  x.map {
    $0[0]
  }
}

func bar(x: borrowing Optional&amp;lt;Atomic&amp;gt;) -&amp;gt; Optional {
  x.ref.map { // ok!
    $0.value.load(ordering: .relaxed) &amp;amp;+ 1
  }
}

func baz(x: inout Optional&amp;lt;UniqueArray&amp;gt;) -&amp;gt; Optional {
  x.mutableRef.map {
    // map 하면서 array를 그 자리에서 업데이트
    $0.value.append(123)
    return $0.value.count
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Source Compatibility&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;Optional.ref&lt;/code&gt;, &lt;code&gt;Optional.mutableRef&lt;/code&gt;, &lt;code&gt;Optional.put()&lt;/code&gt;은 새로 추가되는 메서드라 소스 호환성 문제가 없습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;map&lt;/code&gt; / &lt;code&gt;flatMap&lt;/code&gt;의 새 오버로드는 기존 함수보다 덜 특수화된 오버로드예요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;기존에 &lt;code&gt;Optional.map&lt;/code&gt;을 쓰던 코드는 모두 &lt;code&gt;Copyable&lt;/code&gt; wrapped 값을 다루고 있었을 테니, 더 특수화된 기존 &lt;code&gt;Wrapped: Copyable&lt;/code&gt; 오버로드로 그대로 resolve됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt; &lt;code&gt;flatMap&lt;/code&gt;도 마찬가지고요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그래서 이 일반화된 함수들로 인한 소스 호환성 문제는 없을 것으로 예상합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;unsafelyUnwrapped&lt;/code&gt;는 순수한 일반화라 소스 호환성 문제를 일으키지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;ABI Compatibility&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;Optional&lt;/code&gt;에 추가되는 새 메서드들은 표준 라이브러리의 새 API지만 별도 ABI를 필요로 하지 않아요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;map&lt;/code&gt;, &lt;code&gt;flatMap&lt;/code&gt;, &lt;code&gt;unsafelyUnwrapped&lt;/code&gt;의 일반화 역시 새로운 ABI를 추가하거나 기존 ABI를 깨뜨리지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Implications on Adoption&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;Optional.ref&lt;/code&gt;, &lt;code&gt;Optional.mutableRef&lt;/code&gt;, &lt;code&gt;Optional.put()&lt;/code&gt;은 &lt;code&gt;Ref&lt;/code&gt;와 &lt;code&gt;MutableRef&lt;/code&gt;와 동일한 availability를 가집니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;나머지 일반화 부분들은 항상 사용 가능한 것으로 표시됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Future Directions&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Borrow와 inout 바인딩&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;앞으로 borrow/inout 바인딩을 지원하기로 한다면, 컴파일러가 optional에 대해 &lt;code&gt;if borrow&lt;/code&gt; / &lt;code&gt;if inout&lt;/code&gt; 패턴을 인식해서 조건부로 scope된 접근을 제공하게 할 수도 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;stylus&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;if borrow x = optional {
  
}

foo(optional) // ok&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;만약 이 방향이 &lt;code&gt;ref&lt;/code&gt; / &lt;code&gt;mutableRef&lt;/code&gt; 방식보다 낫다고 판단되면, &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;flatMap&lt;/code&gt;, &lt;code&gt;unsafelyUnwrapped&lt;/code&gt;를 일반화하는 방식도 다시 고민해야 해요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;더 이상 항상 consuming일 수 없으니까요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;consumingMap&lt;/code&gt;, &lt;code&gt;borrowingMap&lt;/code&gt;, &lt;code&gt;mutatingMap&lt;/code&gt; 등을 따로 만드는 방법도 있지만, API가 계속 늘어나는 건 그리 썩 괜찮은 해법은 아니라고 하네요  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Optional: Equatable / Hashable 일반화&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;SE-0499가 &lt;code&gt;Equatable&lt;/code&gt;, &lt;code&gt;Hashable&lt;/code&gt; 같은 프로토콜을 noncopyable / nonescapable conformer까지 지원하도록 일반화한 만큼, &lt;code&gt;Optional&lt;/code&gt;의 이 conformance들도 suppressed wrapped 타입을 지원하도록 일반화하는 게 당연해 보입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;다만 특정 conformance가 어느 시점에 일반화됐는지 표현할 방법이 없어서, 오래된 ABI 안정 OS에서 실수로 제네릭 &lt;code&gt;==&lt;/code&gt;나 &lt;code&gt;hash(into:)&lt;/code&gt;를 호출해 payload를 copy해버리는 상황은 막아야 해요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Ref / MutableRef 자동 역참조&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;제안된 예시들에서 &lt;code&gt;ref&lt;/code&gt; / &lt;code&gt;mutableRef&lt;/code&gt;로 &lt;code&gt;map&lt;/code&gt;을 쓸 때 &lt;code&gt;.value&lt;/code&gt; 프로퍼티를 명시적으로 접근해야 했죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt; 앞으로 &lt;code&gt;Ref&lt;/code&gt;와 &lt;code&gt;MutableRef&lt;/code&gt;에 자동 역참조 기능을 추가해서, 아래처럼 더 편하게 쓸 수 있게 할 수도 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; style=&quot;background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; overflow: auto;&quot;&gt;&lt;code&gt;func bar(x: borrowing Optional&amp;lt;Atomic&amp;gt;) -&amp;gt; Optional {
  x.ref.map { // ok!
    // '.value.'가 더 이상 필요 없음
    $0.load(ordering: .relaxed) &amp;amp;+ 1
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Alternatives Considered&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Optional 바인딩의 기본 소유권 방식 변경&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 제안의 동기에서는 &lt;code&gt;ref&lt;/code&gt;, &lt;code&gt;mutableRef&lt;/code&gt; 같은 프로퍼티가 borrowing 버전의 제어 흐름을 위해 필요하다고 설명했어요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;대신 &lt;code&gt;if let&lt;/code&gt; 같은 optional 바인딩의 기본 소유권 방식을 borrowing으로 바꾸는 방법도 있었습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;하지만 이건 optional 바인딩이 consuming이라고 가정하는 기존 코드에 대해 source-breaking 변경이 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Optional.borrow()와 Optional.mutate() 메서드&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이전 리비전에서는 &lt;code&gt;ref&lt;/code&gt;, &lt;code&gt;mutableRef&lt;/code&gt; 대신 &lt;code&gt;borrow()&lt;/code&gt;, &lt;code&gt;mutate()&lt;/code&gt;라는 메서드 이름을 제안했었어요. 하지만 &lt;code&gt;InlineArray&lt;/code&gt;나 &lt;code&gt;UniqueArray&lt;/code&gt; 같은 타입의 &lt;code&gt;span&lt;/code&gt;, &lt;code&gt;mutableSpan&lt;/code&gt; 프로퍼티와 결을 맞추고 싶어서 최종적으로는 프로퍼티 형태가 더 선호됐습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Conclusion&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;noncopyable optional을 다루는 게 이번 제안으로 한결 편해질 것 같아요  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;지금까지는 내부 값을 살짝 들여다보기만 해도 consume 에러를 피하려고 switch 문을 직접 작성해야 했는데, &lt;code&gt;ref&lt;/code&gt; / &lt;code&gt;mutableRef&lt;/code&gt; 덕분에 &lt;code&gt;if let&lt;/code&gt;처럼 자연스럽게 접근할 수 있게 됐습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;put()&lt;/code&gt;도 강제 언래핑을 줄여주는 실용적인 추가고요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;map&lt;/code&gt;, &lt;code&gt;flatMap&lt;/code&gt;, &lt;code&gt;unsafelyUnwrapped&lt;/code&gt;까지 일반화되면서, noncopyable 타입을 다루는 코드가 Copyable 타입을 다룰 때와 비슷한 느낌으로 작성할 수 있을 것 같습니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 4px solid #3a8c28; padding-left: 12px; margin-top: 32px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;References&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1784377874630&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;swift-evolution/proposals/0532-optional-noncopyable-improvements.md at main &amp;middot; swiftlang/swift-evolution&quot; data-og-description=&quot;This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0532-optional-noncopyable-improvements.md&quot; data-og-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0532-optional-noncopyable-improvements.md&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/QejmU/dJMb9c9KuFW/Zuc9qRuObCGBRVnm80VTe0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bssUwH/dJMb8Z3Eglv/iRJuxZnP2VNw5CbC9PJJGk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0532-optional-noncopyable-improvements.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0532-optional-noncopyable-improvements.md&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/QejmU/dJMb9c9KuFW/Zuc9qRuObCGBRVnm80VTe0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bssUwH/dJMb8Z3Eglv/iRJuxZnP2VNw5CbC9PJJGk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;swift-evolution/proposals/0532-optional-noncopyable-improvements.md at main &amp;middot; swiftlang/swift-evolution&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>Swift</category>
      <category>noncopyable</category>
      <category>SE-0532</category>
      <category>SWIFT</category>
      <author>GREEN.1229</author>
      <guid isPermaLink="true">https://green1229.tistory.com/629</guid>
      <comments>https://green1229.tistory.com/629#entry629comment</comments>
      <pubDate>Sat, 18 Jul 2026 21:33:05 +0900</pubDate>
    </item>
    <item>
      <title>What's new in SwiftData (feat. WWDC 2026)</title>
      <link>https://green1229.tistory.com/628</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;안녕하세요. &lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;그린&lt;/b&gt;&lt;/span&gt;입니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이번 포스팅에서는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;WWDC 2026에서 나온 SwiftData 부분에서 업데이트 사항들에 대해 살펴보고 정리&lt;/b&gt;&lt;/span&gt;해보겠습니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Sectioning your fetches&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;먼저 SwiftData에서 섹션별로 데이터를 가져오는 방법을 보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-07-12 오후 6.14.41.png&quot; data-origin-width=&quot;827&quot; data-origin-height=&quot;428&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhimzf/dJMcacX6ugh/K04KMnaVySXZgzEKWjOKP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhimzf/dJMcacX6ugh/K04KMnaVySXZgzEKWjOKP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhimzf/dJMcacX6ugh/K04KMnaVySXZgzEKWjOKP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbhimzf%2FdJMcacX6ugh%2FK04KMnaVySXZgzEKWjOKP0%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;827&quot; height=&quot;428&quot; data-filename=&quot;스크린샷 2026-07-12 오후 6.14.41.png&quot; data-origin-width=&quot;827&quot; data-origin-height=&quot;428&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이제는 이렇게 쿼리에서 옵션을 주어 그룹별로 묶을 수 있어요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;각 섹션에선 ID 속성이 있고 이걸 활용하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Using custom types&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;모델에 커스텀 타입을 저장하는 기능 향상을 살펴볼께요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;SwiftData는 로드될 때 모델에 대한 스키마를 자동으로 생성합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;스키마는 모델 클래스와 엔티티간 매핑을 정의하죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;대부분의 타입에선 이게 자동으로 작동해요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그렇지만 모델 매크로로 어노테이션 되지 않은 클래스는 자동으로 검사할 수 없기에 SwiftData는 스키마 생성에 실패합니다  &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;만약 그렇다고 구현체에 접근할 수 없을 수 있잖아요?&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-07-12 오후 6.18.23.png&quot; data-origin-width=&quot;643&quot; data-origin-height=&quot;389&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ttsoG/dJMcafAxHil/BOSilGDEXAsPPEHw16zjek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ttsoG/dJMcafAxHil/BOSilGDEXAsPPEHw16zjek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ttsoG/dJMcafAxHil/BOSilGDEXAsPPEHw16zjek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FttsoG%2FdJMcafAxHil%2FBOSilGDEXAsPPEHw16zjek%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;643&quot; height=&quot;389&quot; data-filename=&quot;스크린샷 2026-07-12 오후 6.18.23.png&quot; data-origin-width=&quot;643&quot; data-origin-height=&quot;389&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그런 경우 이렇게 어트리뷰트 codable을 사용하여 주면 해결됩니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 속성은 SwiftData에 타입의 인코딩된 표현을 저장하도록 알려주는 역할을 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;타입에 대한 스키마를 추론하는 대신에요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;다만 염두해둬야할게 있는데, codable 속성의 내용은 SwiftData에 불투명합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이는 Predicate에서 결과를 필터링하는데 사용할 수 없음을 나타내요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;또는 정렬도 사용할 수 없어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;또한 codable 형태가 변경되면 속성을 추가하거나 제거하는 경우 마이그레이션이 트리거되지 않아요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 점을 주의해야 합니다!&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Codable 속성 사용은 SwiftData가 기본적으로 지원하지 않는 타입을 저장하는 탈출구라고 생각하면 좋습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;직접 정의했다면 왠만해선 Codable 사용을 금해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Observing data stores&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스토어를 모니터링하고 데이터 변경 시 알림 받는 방법을 살펴볼께요.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-07-12 오후 6.22.41.png&quot; data-origin-width=&quot;475&quot; data-origin-height=&quot;347&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTvIGj/dJMcaalCTfH/lzBtKCSoBE76r8uRfKaVIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTvIGj/dJMcaalCTfH/lzBtKCSoBE76r8uRfKaVIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTvIGj/dJMcaalCTfH/lzBtKCSoBE76r8uRfKaVIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTvIGj%2FdJMcaalCTfH%2FlzBtKCSoBE76r8uRfKaVIK%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;475&quot; height=&quot;347&quot; data-filename=&quot;스크린샷 2026-07-12 오후 6.22.41.png&quot; data-origin-width=&quot;475&quot; data-origin-height=&quot;347&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;SwiftUI에서는 이렇게 데이터가 변경되면 뷰가 쿼리의 새로운 결과를 반영해 다시 렌더링합니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;만약 SwiftUI가 아닌 부분은 어떨까요?&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이걸 위해 이번 2027 릴리즈에선 ResultsObserver를 도입했습니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-07-12 오후 6.24.50.png&quot; data-origin-width=&quot;335&quot; data-origin-height=&quot;338&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BkiZg/dJMb991pUis/lOGVAUVqMUgQPB8k33gHz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BkiZg/dJMb991pUis/lOGVAUVqMUgQPB8k33gHz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BkiZg/dJMb991pUis/lOGVAUVqMUgQPB8k33gHz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBkiZg%2FdJMb991pUis%2FlOGVAUVqMUgQPB8k33gHz0%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;335&quot; height=&quot;338&quot; data-filename=&quot;스크린샷 2026-07-12 오후 6.24.50.png&quot; data-origin-width=&quot;335&quot; data-origin-height=&quot;338&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;SwiftUI 쿼리처럼 데이터 가져오고 관찰하고 반영시키는 Swift Observation을 사용해요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-07-12 오후 6.25.59.png&quot; data-origin-width=&quot;760&quot; data-origin-height=&quot;346&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2yfnH/dJMcaiKJjnj/mkFHPOGWflAZKsNGSfDMK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2yfnH/dJMcaiKJjnj/mkFHPOGWflAZKsNGSfDMK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2yfnH/dJMcaiKJjnj/mkFHPOGWflAZKsNGSfDMK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2yfnH%2FdJMcaiKJjnj%2FmkFHPOGWflAZKsNGSfDMK1%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;760&quot; height=&quot;346&quot; data-filename=&quot;스크린샷 2026-07-12 오후 6.25.59.png&quot; data-origin-width=&quot;760&quot; data-origin-height=&quot;346&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이런식으로 사용될 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;withContinuousObservation은 ObservationTracking 토큰을 반환&lt;/b&gt;합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 &lt;b&gt;토큰이 관찰의 수명을 정의&lt;/b&gt;하죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기서 더 나아가 이번 업데이트에서는 히스토리 관찰도 지원해줍니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-07-12 오후 6.30.26.png&quot; data-origin-width=&quot;394&quot; data-origin-height=&quot;305&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dfHSrK/dJMcahymdti/kXjRP0UithYrkaAwFRRAsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dfHSrK/dJMcahymdti/kXjRP0UithYrkaAwFRRAsk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dfHSrK/dJMcahymdti/kXjRP0UithYrkaAwFRRAsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdfHSrK%2FdJMcahymdti%2FkXjRP0UithYrkaAwFRRAsk%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;394&quot; height=&quot;305&quot; data-filename=&quot;스크린샷 2026-07-12 오후 6.30.26.png&quot; data-origin-width=&quot;394&quot; data-origin-height=&quot;305&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;데이터 스토어가 저장될 때마다 SwiftData는 히스토리 트랜잭션을 기록합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;여기에는 변경된 내용에 대한 정보가 포함됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그리고 변경이 어디서 왔는지 조차도 포함되죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;히스토리에서 트랜잭션을 고유하게 식별하는 토큰도 있습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;ModelContext.fetchHistory() 이 API와 토큰을 함께 사용할 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-07-12 오후 6.32.27.png&quot; data-origin-width=&quot;887&quot; data-origin-height=&quot;282&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XR4c2/dJMcagzpXq5/HWOKwsRkZ6kpSXKFhfVf6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XR4c2/dJMcagzpXq5/HWOKwsRkZ6kpSXKFhfVf6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XR4c2/dJMcagzpXq5/HWOKwsRkZ6kpSXKFhfVf6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXR4c2%2FdJMcagzpXq5%2FHWOKwsRkZ6kpSXKFhfVf6k%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;887&quot; height=&quot;282&quot; data-filename=&quot;스크린샷 2026-07-12 오후 6.32.27.png&quot; data-origin-width=&quot;887&quot; data-origin-height=&quot;282&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;HistoryObserver는 스토어의 변경 사항에 쉽게 반응할 수 있게 해줍니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;지속적 히스토리 관찰과 새로운 트랜잭션 추가 시 코드가 반응하도록 해주죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;특정 종류의 변경만 관찰하고 대응하고 싶다면 물론 HistoryObserver를 사용해 모델 타입과 트랜잭션 작성자로 필터링할 수 있어요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;외부 서버와 같은 다른 시스템과 연동 시 효과적이죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;외부와 연동하는 예시를 볼까요?&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-07-12 오후 6.33.27.png&quot; data-origin-width=&quot;833&quot; data-origin-height=&quot;425&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UNBRA/dJMcacX6usv/iFX1WrACfWzECbaNqu62Gk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UNBRA/dJMcacX6usv/iFX1WrACfWzECbaNqu62Gk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UNBRA/dJMcacX6usv/iFX1WrACfWzECbaNqu62Gk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUNBRA%2FdJMcacX6usv%2FiFX1WrACfWzECbaNqu62Gk%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;833&quot; height=&quot;425&quot; data-filename=&quot;스크린샷 2026-07-12 오후 6.33.27.png&quot; data-origin-width=&quot;833&quot; data-origin-height=&quot;425&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 간단히 코드로 나타내서 사용할 수 있습니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1783848834990&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;SwiftData의 새로운 기능 - WWDC26 - 비디오 - Apple Developer&quot; data-og-description=&quot;SwiftData의 최신 개선 사항을 확인하세요. Codable을 사용하여 맞춤형 및 타사 유형을 유지하는 방법과 가져온 데이터를 SwiftUI 앱의 섹션으로 그룹화하는 방법을 안내합니다. 또한 ModelResultsObserver와&quot; data-og-host=&quot;developer.apple.com&quot; data-og-source-url=&quot;https://developer.apple.com/kr/videos/play/wwdc2026/274/&quot; data-og-url=&quot;https://developer.apple.com/kr/videos/play/wwdc2026/274/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/c55bAO/dJMb8RR33zg/erWRND5znnmRHJeEdxsxaK/img.jpg?width=500&amp;amp;height=282&amp;amp;face=0_0_500_282,https://scrap.kakaocdn.net/dn/HJkIe/dJMb8WeLUTG/t1q0uDdC6kJJcb5kKQPkh0/img.jpg?width=1800&amp;amp;height=1012&amp;amp;face=0_0_1800_1012&quot;&gt;&lt;a href=&quot;https://developer.apple.com/kr/videos/play/wwdc2026/274/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.apple.com/kr/videos/play/wwdc2026/274/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/c55bAO/dJMb8RR33zg/erWRND5znnmRHJeEdxsxaK/img.jpg?width=500&amp;amp;height=282&amp;amp;face=0_0_500_282,https://scrap.kakaocdn.net/dn/HJkIe/dJMb8WeLUTG/t1q0uDdC6kJJcb5kKQPkh0/img.jpg?width=1800&amp;amp;height=1012&amp;amp;face=0_0_1800_1012');&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;SwiftData의 새로운 기능 - WWDC26 - 비디오 - Apple Developer&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;SwiftData의 최신 개선 사항을 확인하세요. Codable을 사용하여 맞춤형 및 타사 유형을 유지하는 방법과 가져온 데이터를 SwiftUI 앱의 섹션으로 그룹화하는 방법을 안내합니다. 또한 ModelResultsObserver와&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.apple.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>SwiftData</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>SwiftData</category>
      <category>WWDC 2026</category>
      <author>GREEN.1229</author>
      <guid isPermaLink="true">https://green1229.tistory.com/628</guid>
      <comments>https://green1229.tistory.com/628#entry628comment</comments>
      <pubDate>Sun, 12 Jul 2026 18:36:37 +0900</pubDate>
    </item>
    <item>
      <title>느즈막히 올려보는 쿠팡에서의 회고 (feat. 또다른 시작)</title>
      <link>https://green1229.tistory.com/627</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;안녕하세요. &lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;그린&lt;/b&gt;&lt;/span&gt;입니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 포스팅에서는 &lt;b&gt;사실 기술적인 부분보다 회고를&lt;/b&gt; 하나 해볼까 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제가 근 1년 6개월 정도 근무했던 쿠팡을 떠나게 되었는데, 사실 쿠팡 입사 직후와 3개월쯤 되었을때 각각 쿠팡 이직기라던지 쿠팡에서의 일상 회고를 해보려 했는데, 일과 개인적인 바쁨에 치여 결국 쿠팡을 나올때 이렇게 회고를 올려보네요  &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서, 이번 회고는 역시나 무근본 무형식으로 그냥 두서없이 한번 적어보려고 합니다  &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1066&quot; data-origin-height=&quot;1448&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/W5hQx/dJMcacwYj5X/JYRjfnXGirwek85iJeDvE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/W5hQx/dJMcacwYj5X/JYRjfnXGirwek85iJeDvE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/W5hQx/dJMcacwYj5X/JYRjfnXGirwek85iJeDvE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FW5hQx%2FdJMcacwYj5X%2FJYRjfnXGirwek85iJeDvE1%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;440&quot; height=&quot;598&quot; data-origin-width=&quot;1066&quot; data-origin-height=&quot;1448&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;쿠팡 입사&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;25년 2월에 쿠팡으로 이직을 하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;왜 이직했는지 그냥 지금와서 간단히 정리해보면, 정말 글로벌 서비스를 하는것과 글로벌 회사에서 일하는것을 경험해보고 싶었어요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이전까지는 iOS 개발자 1인으로 내 할일을 다하는것에 초점이였다면 앞으로의 성장을 생각했을때 그걸 넘어서 정말 일을 잘하는 사람이 되고 싶었어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;개발에 국한된게 아니라 일을 잘하는 사람이요.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그랬을때 좀 더 큰 대규모의 서비스를 경험해보면서 다국가 인종과 일하는 경험 이 두가지가 쿠팡을 지원하고 입사를 하게된 가장 큰 이유였습니다  &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 쿠팡에서 쿠팡이츠라는 O2O 배달 앱 서비스의 시니어 iOS 엔지니어로 근무를 하게 됩니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 쿠팡에서의 1년 6개월을 돌이켜봤을때 어떤것을 해왔고 어떤걸 배웠는지 한번 정리해볼까해요.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Life in Coupang&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우선 일은 굉장히 굉장히 하드워킹이긴 했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그렇다고 밤낮이 없는 삶, 원양어선 그런건 아니였어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그냥 주어진 시간에 정말 1초도 쉬지 않고 일하면 다 끝날 수 있는 그런 정도..?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제가 맡은 TF는 주로 Ads TF였습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배달 앱의 특성 상 배달이나 플랫폼 수수료 같은걸로는 정부 규제도 있고 단가가 그렇게 크지 않아 사실상 사업적인 부분에서 큰 이익이 되지 않는다고 생각해요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그렇기에 또 다른 비지니스적인 부분을 고려할때 광고를 무시할 수 없습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;점포나 메뉴 광고가 주인데 어떤 부분에 배치하거나 어떤 시간대에 어떤걸 배치하면 이 점포를 가장 극대화되어서 CPC나 CPS를 올릴 수 있을지 같이 고민하고 여러 실험을 해보는 그런 TF입니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;광고라는 도메인이 익숙치도 않고 처음 해보는거였지만 그만큼 재밌었어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;직접적으로 주간으로 광고를 통해 얼마나 많은 매출에 기여했는지 확연하게 눈에 보일 수 있었기에 더 동기부여가 되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;또한, 광고 TF말고도 두루 경험해봤던것도 큰 기억으로 남아요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심인 음식 배달과 요즘 밀고 있는 쇼핑(마트나 편의점, 꽃집 등등 - 푸드가 아닌 모든것) 그리고 고객들의 VOC나 편의성을 개선하기 위한 CRM TF 등 한 팀에 정말 다양한 TF가 로테이션으로 돌아가며 일을 하게 되는데 이 모든것의 비지니스 태스크를 한번씩은 해본것 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그러다보니 자연스레 다양한 코드들을 보게되고 깊게 이해하게 되었어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size18&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이렇게 거시적으로 볼 수 있는 비지니스적인 일은 어떻게 했는지에 대해 간단히 회고를 해본다면 이제는 팀에 대한 회고를 해볼까해요.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사실상 가장 많이 짧다면 짧은 시간에 성장할 수 있게 된 원동력이 바로 소속된 iOS 팀이였습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;솔직하게 지금까지 나름 다양한 회사도 다녀보고 여러 동아리도 해보고 컨퍼런스도 다녀보면서 교류해봤지만 개발자 개개인의 역량으로는 쿠팡이 가장 월등하다고 느꼈어요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;쿠팡의 채용 과정이 정말 복잡하고 난이도가 큰 편이라 더 그런지는 몰라도 개발자의 능력은 어느 회사보다도 뛰어나다고 확신할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그렇기에 같이 부딪히며 토론하고 때론 설전도 벌이면서 일을 하면서 성장한것 같아요  &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;쿠팡에서 일하기 전까지의 저를 돌이켜보면 iOS 개발 맡은거 능히 해낼 수 있는 개발자라고 말할 수 있다면, 여기서 배운건 그건 당연히 해야되는거고 그거 말고도 너가 더 뭘할 수 있는데?에 대한 푸시가 많고 그걸 잘 끌어올려줄 매니저와 팀원들이 존재했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;너가 1인분 하는건 당연히 시니어 개발자가 아니라 주니어 개발자여도 당연히 해야되는거고, 그걸 넘어서 시니어 개발자라면 팀에 어떤 영향을 미칠 수 있는지 고민하고 iOS 뿐만 아니라 더 스펙트럼을 넓혀서 안드로이드, 웹을 포함한 프론트 그리고 백엔드까지 비지니스 스펙을 받으면 고려해서 테크적인 리드를 할 줄 알아야 하며 그런 부분을 하드 트레이닝을 많이 했던것 같아요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 일감이 주어지면 항상 어떻게 개발해야하지? 라는 생각보다 이게 정말 괜찮은 실험인지 이 실험을 성공시키기 위해서 각 파트에서 어떤 노력을 기울이면 좋을지 그리고 그게 제일 효과적인 방법일지를 고민하게 저의 일을 접근하는 방식 자체가 많이 변화한것 같아요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그전에는 iOS 앱 개발 부분에서만 고민했다면 이제는 백엔드와의 트레이드오프도 생각해보고 좀 더 크로스 플랫폼에서 일하기 적절한 방법과 그리고 기능 개발 대비 어느정도 인력 코스트가 들어가는지 그런것들까지 고민하고 제안을 하게 되는 개발자로 성장했어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그리고 그건 제가 원하지 않아도 쿠팡에서 일을 하면 자연스럽게 요구되는 역량이고 그렇게 변하게 만들어주더라구요  &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그리고 팀적으로도 &lt;b&gt;매주 테크 미팅을 통해 서로 기술을 공유하고 새로 맡은 비지니스 일감이 있다면 항상 먼저 테크 디자인을 한 후 공유해서 더 나은 방향이 있는지를 모바일 팀 자체적으로 더 체크&lt;/b&gt;를 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이렇게 꼼꼼하고 다양한 의견을 듣다보면 자연스럽게 시야도 넓어지게 되더라구요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;쿠팡에서는 이렇게 정말 많은 미팅과 룰과 일이 존재해요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그러다보니 눈코 뜰 새가 없는건 사실이지만 어떻게 보면 가장 이상적인 시스템이라곤 생각이 되더라구요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그 시스템에서 번아웃이 안오고 버티는게 힘든것 뿐이지만 회사적인 측면으로만 보면 합리적이고 비지니스가 성장할 수 있는 시스템이란 생각이 많이 듭니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그리고 또 많이 성장했던 부분은 바로 영어일것 같아요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사실 영어를 잘하지 못했고 지금도 그렇지만 하나 달라진건 자신감인것 같아요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;회사에선 공식적으로 한국어로 일하는것 자체가 없어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;공용 언어가 영어이기에 슬랙, 위키 등등 모든것이 영어죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그리고 미팅도 통역이 제공되는 경우도 있지만 기본이 영어입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그러다보니 사실 살려면 해야됐었어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;저도 처음에 입사해서 &quot;아 이거 일보다 커뮤니케이션이 영어라 따라갈 수 있나?&quot; 싶었어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 슬랙도 그렇고 번역기에 번역하고 하고 싶은 말도 번역해서 떠듬떠듬 치고 그랬죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그런데 이게 일상에 녹아드니 별다른 영어 공부를 하지 않아도 자연스럽게 익숙해지기 마련이더라구요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그 전에는 예를 들어 &quot;이거 확인해주실 수 있나요?&quot; 라는걸 영어로 말해야된다 생각하면 머릿속에서 문법부터 생각하고 완성한 다음 이게 진짜 맞나 고민하고 그런것들때문에 영어가 입 밖으로 더 안나왔던것 같아요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그런데 이제는 일단 문법이 다 맞지 않고 그렇더라도 이 바쁜 일상에서 우선 커뮤니케이션이 우선이고 먼저 말해야된다는 압박이 있다보니 자연스레 &quot;Could you check this?&quot;와 같이 나오게 되더라구요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;물론 더 좋은 표현도 있고 하겠지만 배운 한가지가 자신감이라 했잖아요?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 자신감은 확실히 익힌것 같아요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이제 말로 표현하고 문장으로 쓰는게 내가 틀렸다 하더라도 두렵지가 않게 되었습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그리고 앞서 계속 말했지만 팀원들 정말 훌륭하고 귀중한 팀원들 그리고 타 팀의 교류하는 사람들 모두 좋은 인프라를 쌓을 수 있어 감사했어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일이 빡센만큼 전우애가 더 많이 생기게 되는 쿠팡이였어요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;나간다니 이런 것까지 해주는 팀원들인데 어떻게 잊을 수 있을까 싶어요.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_9900.JPG&quot; data-origin-width=&quot;2252&quot; data-origin-height=&quot;4000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdbwwc/dJMcadbtC6A/PhGnBgVv7EdPn1DY5EqCVk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdbwwc/dJMcadbtC6A/PhGnBgVv7EdPn1DY5EqCVk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdbwwc/dJMcadbtC6A/PhGnBgVv7EdPn1DY5EqCVk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcdbwwc%2FdJMcadbtC6A%2FPhGnBgVv7EdPn1DY5EqCVk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;321&quot; height=&quot;570&quot; data-filename=&quot;IMG_9900.JPG&quot; data-origin-width=&quot;2252&quot; data-origin-height=&quot;4000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 정리해보면 쿠팡에서 생활하면서 성장한 부분은 이렇습니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1️⃣ 기술적인 견고함과 더 넓게 바라볼 수 있는 시야&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2️⃣ 개인 혼자만이 아니라 팀 전체에 영향을 미칠 수 있는 사고&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3️⃣ 영어 의사소통&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4️⃣ 정말 비지니스적으로 어떤것들이 도움되는지에 대한 고민&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 외에도 서버 드리븐적인 설계, 대쉬보드들을 구축해서 모니터링을 강화하는 방법, 장애 대응, AI 오너로써 팀을 이끌어본 경험 등등 기술적으로나 팀에 영향을 주는 부분으로나 정말 다양한 포인트들이 있지만 그거까지 쓰면 한도 끝도 없을것 같아 우선 쿠팡에서의 라이프는 간략하게 이정도로 마칠까 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 가장 중요한 포인트인데 왜 쿠팡을 떠나는지에 대해 간단히 정리하고 마쳐보려고 해요.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Why am I leaving Coupang?&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;당연히 이직이 쉬운 선택도 아니고 또 새로운 도전을 하는것은 더더욱 쉬운 선택이 아닙니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그리고 그런 결정을 하기까지에는 정말 큰것부터 정말 사소한것까지 많은 복합적인 부분이 상호작용 할거에요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여기선 몇가지 핵심적인 이유를 전해볼까해요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우선, 쿠팡이 다니기에 좋지 않은 회사다 라는것은 전혀 아닙니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일이 힘들 순 있지만 그거때문에 이직하는건 도피라고 생각해요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;어딜가나 힘든건 있기 마련이고 일이 바쁘다고 나가는건 근로자의 덕목이 아니라 생각하기 때문이죠.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1️⃣ 더 넓은 글로벌 서비스&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가장 큰것중 하나는 바로 이 항목이에요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;쿠팡이츠를 개발하면서 현재는 한국과 일본을 타겟으로 서비스하고 있는데, 일본을 고려해서 글로벌한 서비스를 구축하고 운영하다 보니 정말 더 많은 나라들 나아가서 대륙들을 타겟으로 하는 더 큰 글로벌 서비스들이 궁금해졌어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그리고 글로벌 서비스를 해보니 재미가 있더라구요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;같은 앱이지만 각 문화 환경에 따라 원하는 화면과 폰트 배치들이 다르다는것도 세삼 느끼게 되면서 뭔가 리전을 바꿀때마다 여행하는 느낌이 들었어요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;직간접적으로 그 나라를 체험해보는거죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 이를 충족하는 서비스를 해보고 싶다는 생각이 컸습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2️⃣ 컨텐츠 플랫폼에 대한 니즈&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그리고 저는 사실 개발자를 처음 해올때부터 사용자들이 몰두할 수 있는 컨텐츠 플랫폼을 해보고 싶었어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지금까지는 주로 커머스, O2O와 같은 사용자들이 앱에 들어와서 빠르게 확인하고 구매하고 나가는 그런 동선으로 비지니스를 이끄는 서비스였어요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그러다보니 한 화면에서 애니메이션이나 더 심미적인 부분보다는 탐색 플로우나 결제 플로우에서 로직과 빠른 구매가 더 중요해지더라구요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 한편으로는 그런 부분들을 많이 다룰 수 없었어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여담이지만 저는 KWDC 2023에서 SwiftUI 애니메이션 관련 세션을 발표할 정도로 심&lt;b&gt;미적인것과 사용자의 더 아름다운 경험을 구현하는걸 원하고 좋아하는 개발자&lt;/b&gt;에요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 그런 부분을 채울 수 있는 컨텐츠 플랫폼 서비스를 꼭 해보고 싶었어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그럼 왜 여태까지 그런거 안했냐? 라고 한다면 안한게 아니라 못했던거라고 할 수 있어요  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사실 알려진 컨텐츠 플랫폼 앱이 몇개 되지도 않지만 제가 원한다고 내일부터 그 회사에 들어가서 해볼 수 있는건 아니잖아요..?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;무튼 그래서 컨텐츠 플랫폼을 향한 저의 개발자로서의 니즈가 이직의 큰 몫을 했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3️⃣ 거리&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마지막으로 누군가한테 사소할 수도 있지만 저한테 큰 부분이였던건 회사와의 거리였어요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사실 쿠팡에 입사한것도 처음엔 하이브리드로 재택이 존재했기에 공고나 계약도 그렇게 진행되었어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 선릉까지 출퇴근하는게 매일이 아니니 부담스럽지 않고 현실적으로 가능했죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그런데 작년부터 풀출근으로 근무제도가 변경되면서 이는 적지 않은 부담으로 다가왔어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(물론 모든 쿠팡 부서가 그런건 아니고 근무제도는 조직장에 따라 모두 부바부입니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그러다보니 출퇴근 하는데 드는 시간, 체력소모, 비용 그런것들까지 트레이드 오프 되는것을 생각해볼때 쿠팡이 큰 메리트가 되지 않는단 생각이 문득 들더라구요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 사소할 수 있지만 저한텐 어떻게 보면 심리적으로 가장 큰 부분이였어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이런 대표적인 이유 + 말하진 않았지만 더 많은 이유들이 상호작용하여 이직을 결심하게 되었습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(혹시 말하지 않았지만 더 많인 이유들이 궁금하시다면 연락주세요 ㅋㅋㅋ)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 이번엔 어딜 가는데?&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번에는 1과 2그리고 3번의 이직 이유들을 충족할 수 있는 곳으로 가게되었어요.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crY72j/dJMcadvLNul/U9CuFDvM4fKZeLkjCwtvKK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crY72j/dJMcadvLNul/U9CuFDvM4fKZeLkjCwtvKK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crY72j/dJMcadvLNul/U9CuFDvM4fKZeLkjCwtvKK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrY72j%2FdJMcadvLNul%2FU9CuFDvM4fKZeLkjCwtvKK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;291&quot; height=&quot;291&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네이버웹툰에서 글로벌 웹툰 iOS 앱 개발에 기여하게 되었습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아직 출근전이고 이 글이 나가는 시점에서 한 주 후 첫출근을 하게 될 예정이라 떨리네요 ☺️&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인터뷰들을 진행하며 제가 더 다른 성장하고 싶은 포인트와 해소하고 싶은 포인트들을 네이버 웹툰에서 더 다양하게 해볼 수 있을것 같아 많은 기대가 됩니다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아 그리고 현재 쿠팡에서 해당 제 포지션의 채용이 열려있어요!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;관심 있으시거나 궁금한 부분이 있으신 분은 언제든 편하게 연락주시면 제가 아는선에서 알려드리고 도와드릴께요  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제가 장담하건데 꼭 다녀봐야할 회사라고 생각합니다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1783315930824&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;Sr Mobile Engineer (Eats iOS)&quot; data-og-description=&quot;쿠팡이츠(Coupang Eats)는 쿠팡의 음식 배달 서비스이자,대한민국에서 빠르게 성장하고 있는 배달 서비스입니다. 2019년 국내 배달 업계에 혜성처럼 등장한 쿠팡이츠는 2024년 &amp;lsquo;무제한 무료배달&amp;rsquo;로&quot; data-og-host=&quot;www.coupang.jobs&quot; data-og-source-url=&quot;https://www.coupang.jobs/kr/jobs/7991999/sr-mobile-engineer-eats-ios/?gh_jid=7991999&quot; data-og-url=&quot;https://www.coupang.jobs/kr/jobs/7991999/sr-mobile-engineer-eats-ios/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cyqOMW/dJMb8UH0H9e/RHjnMaYoA85KVEBn3iQ4CK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://www.coupang.jobs/kr/jobs/7991999/sr-mobile-engineer-eats-ios/?gh_jid=7991999&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.coupang.jobs/kr/jobs/7991999/sr-mobile-engineer-eats-ios/?gh_jid=7991999&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cyqOMW/dJMb8UH0H9e/RHjnMaYoA85KVEBn3iQ4CK/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;Sr Mobile Engineer (Eats iOS)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;쿠팡이츠(Coupang Eats)는 쿠팡의 음식 배달 서비스이자,대한민국에서 빠르게 성장하고 있는 배달 서비스입니다. 2019년 국내 배달 업계에 혜성처럼 등장한 쿠팡이츠는 2024년 &amp;lsquo;무제한 무료배달&amp;rsquo;로&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.coupang.jobs&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;또 어떤 재밌는 일들이 벌어지고 경험하게 될지 모르겠지만, 언젠가 또 좋은 회고로 찾아오도록 하겠습니다  &lt;/span&gt;&lt;/blockquote&gt;</description>
      <category>회고</category>
      <author>GREEN.1229</author>
      <guid isPermaLink="true">https://green1229.tistory.com/627</guid>
      <comments>https://green1229.tistory.com/627#entry627comment</comments>
      <pubDate>Mon, 6 Jul 2026 13:39:50 +0900</pubDate>
    </item>
    <item>
      <title>What's new in SwiftUI (feat. WWDC 2026)</title>
      <link>https://green1229.tistory.com/626</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;안녕하세요. &lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;그린&lt;/b&gt;&lt;/span&gt;입니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이번 포스팅에서는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;WWDC 2026에서 소개된 What's new in SwiftUI 세션을 정리&lt;/b&gt;&lt;/span&gt;해보겠습니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;뭔가 오랜만에 SwiftUI를 공부하고 정리하는것 같아 재밌을것 같아요  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Refreshed look and feel&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;리퀴드 글래스 기능이 나온건 벌써 좀 되었지만, 여전히 강조하고 개선시키고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.04.12.png&quot; data-origin-width=&quot;1476&quot; data-origin-height=&quot;686&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CQflN/dJMcajo7PHo/nt4t2B5oET8rQbjWx6q4y1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CQflN/dJMcajo7PHo/nt4t2B5oET8rQbjWx6q4y1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CQflN/dJMcajo7PHo/nt4t2B5oET8rQbjWx6q4y1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCQflN%2FdJMcajo7PHo%2Fnt4t2B5oET8rQbjWx6q4y1%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;727&quot; height=&quot;338&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.04.12.png&quot; data-origin-width=&quot;1476&quot; data-origin-height=&quot;686&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;appearsActive 환경값을 통해 창이 비활성화 일때 불투명도를 조절할 수 있어요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;또한, 이제 macOS나 iPadOS에서 메뉴바가 정말 심플해졌는데요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;원한다면 labelStyle을 통해 타이틀과 아이콘이 같이 나오도록도 설정할 수 있죠.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.05.19.png&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;696&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/U1DMK/dJMcabktX8a/JLDWrlIWehmokV3fxbwFYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/U1DMK/dJMcabktX8a/JLDWrlIWehmokV3fxbwFYK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/U1DMK/dJMcabktX8a/JLDWrlIWehmokV3fxbwFYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FU1DMK%2FdJMcabktX8a%2FJLDWrlIWehmokV3fxbwFYK%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;470&quot; height=&quot;321&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.05.19.png&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;696&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;그리고 어쩌면 폴더블을 예상케하는 기능도 생겨났어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;iOS 27에서는 프리뷰를 통해 앱이 대화형 크기 조정에 어떻게 반응하는지 볼 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이렇게 늘리고 줄여서 이상이 없는지 바로 확인할 수 있죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이는 추후 출시된다는 소문이 많은 폴더블에 대한 대응을 미리 해놔라 라는 의미로도 들려지네요  &lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.06.42.png&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y39rD/dJMcajbBzeN/CEVQoDtqh7w0NHOGcJYK3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y39rD/dJMcajbBzeN/CEVQoDtqh7w0NHOGcJYK3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y39rD/dJMcajbBzeN/CEVQoDtqh7w0NHOGcJYK3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy39rD%2FdJMcajbBzeN%2FCEVQoDtqh7w0NHOGcJYK3K%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;1430&quot; height=&quot;560&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.06.42.png&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;560&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 반응형은 SwiftUI로 앱을 구성하면 자동으로 따라오지만 만약 UIKit과 SwiftUI 모두 사용한다면 고려해야할 몇가지가 있습니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.09.31.png&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bB9crk/dJMcaiRnU3h/jjUiJYBNuxkMTGfAUsgLx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bB9crk/dJMcaiRnU3h/jjUiJYBNuxkMTGfAUsgLx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bB9crk/dJMcaiRnU3h/jjUiJYBNuxkMTGfAUsgLx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbB9crk%2FdJMcaiRnU3h%2FjjUiJYBNuxkMTGfAUsgLx0%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;445&quot; height=&quot;323&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.09.31.png&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;544&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;1️⃣ 스크린 지오메트리 확인&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;2️⃣ 디바이스 대신 사이즈 클래스 이용하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;3️⃣ 화면 회전과 같은 방향에 대해 체크&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이에 대해 더 자세히 알아보려면, 아래 세션을 참고하세요!&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1782695449888&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;Modernize your UIKit app - WWDC26 - Videos - Apple Developer&quot; data-og-description=&quot;Discover the latest updates to UIKit. Learn how to update your iPhone app layouts to work great when resized with iPhone Mirroring and on...&quot; data-og-host=&quot;developer.apple.com&quot; data-og-source-url=&quot;https://developer.apple.com/videos/play/wwdc2026/278/&quot; data-og-url=&quot;https://developer.apple.com/videos/play/wwdc2026/278/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ftKZA/dJMb9b32t8M/tyrPDUQpmpJJeT2SSyZ961/img.jpg?width=500&amp;amp;height=282&amp;amp;face=219_37_264_86,https://scrap.kakaocdn.net/dn/Q7PTG/dJMb9cBSsTE/qUKXYgvoe2YZ0gBW1MPtIk/img.jpg?width=1800&amp;amp;height=1012&amp;amp;face=793_143_936_297&quot;&gt;&lt;a href=&quot;https://developer.apple.com/videos/play/wwdc2026/278/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.apple.com/videos/play/wwdc2026/278/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ftKZA/dJMb9b32t8M/tyrPDUQpmpJJeT2SSyZ961/img.jpg?width=500&amp;amp;height=282&amp;amp;face=219_37_264_86,https://scrap.kakaocdn.net/dn/Q7PTG/dJMb9cBSsTE/qUKXYgvoe2YZ0gBW1MPtIk/img.jpg?width=1800&amp;amp;height=1012&amp;amp;face=793_143_936_297');&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;Modernize your UIKit app - WWDC26 - Videos - Apple Developer&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Discover the latest updates to UIKit. Learn how to update your iPhone app layouts to work great when resized with iPhone Mirroring and on...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.apple.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;탭뷰에서도 새로운 기능이 생겼습니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.11.47.png&quot; data-origin-width=&quot;2478&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cywT32/dJMcabrc06D/lyr1pzhhxD8PvUDXSDZeUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cywT32/dJMcabrc06D/lyr1pzhhxD8PvUDXSDZeUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cywT32/dJMcabrc06D/lyr1pzhhxD8PvUDXSDZeUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcywT32%2FdJMcabrc06D%2Flyr1pzhhxD8PvUDXSDZeUk%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;2478&quot; height=&quot;1260&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.11.47.png&quot; data-origin-width=&quot;2478&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이렇게 우측에 특별한 탭 배치를 하고 싶다면 prominent role 속성을 주어 그걸 표현해낼 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이 탭 메뉴는 아래처럼 디바이스 사이즈에 따라 자동으로 크기가 변하거나, 항목의 갯수가 줄어들거나 늘어나게 표현될 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.12.56.png&quot; data-origin-width=&quot;1114&quot; data-origin-height=&quot;658&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BigG2/dJMcafmSjye/fn9buPo2NHnDQWiHK0uohk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BigG2/dJMcafmSjye/fn9buPo2NHnDQWiHK0uohk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BigG2/dJMcafmSjye/fn9buPo2NHnDQWiHK0uohk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBigG2%2FdJMcafmSjye%2Ffn9buPo2NHnDQWiHK0uohk%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;743&quot; height=&quot;439&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.12.56.png&quot; data-origin-width=&quot;1114&quot; data-origin-height=&quot;658&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이때 줄어들어서 숨겨진 메뉴들은 더보기 버튼을 통해 오버플로우 메뉴로 확인할 수 있죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.15.28.png&quot; data-origin-width=&quot;1586&quot; data-origin-height=&quot;476&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DTIeF/dJMcajo7PW7/s6bWGT4zZJc8Y1VvBWUOkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DTIeF/dJMcajo7PW7/s6bWGT4zZJc8Y1VvBWUOkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DTIeF/dJMcajo7PW7/s6bWGT4zZJc8Y1VvBWUOkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDTIeF%2FdJMcajo7PW7%2Fs6bWGT4zZJc8Y1VvBWUOkk%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;1586&quot; height=&quot;476&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.15.28.png&quot; data-origin-width=&quot;1586&quot; data-origin-height=&quot;476&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;또한, 이렇게 ToolbarItemGroup에서 undo, redo가 기본적으로 숨겨져있는데 만약 가시성있게 주고 싶다면 visibilityPriority를 high로 속성을 지정해주면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;물론 이것도 이번 iOS 27에서 나온 기능이죠.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.17.12.png&quot; data-origin-width=&quot;1612&quot; data-origin-height=&quot;530&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pBOmT/dJMcaf78X31/sDjyYhapalrhKCCJL76dH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pBOmT/dJMcaf78X31/sDjyYhapalrhKCCJL76dH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pBOmT/dJMcaf78X31/sDjyYhapalrhKCCJL76dH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpBOmT%2FdJMcaf78X31%2FsDjyYhapalrhKCCJL76dH0%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;1612&quot; height=&quot;530&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.17.12.png&quot; data-origin-width=&quot;1612&quot; data-origin-height=&quot;530&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;반대로, 오버플로우 메뉴로 숨기려면 ToolbarOverFlowMenu로 지정하면 됩니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.17.49.png&quot; data-origin-width=&quot;1590&quot; data-origin-height=&quot;508&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QAqLn/dJMcac4Gt28/k1diPt47TR8oG3Nrsud0ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QAqLn/dJMcac4Gt28/k1diPt47TR8oG3Nrsud0ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QAqLn/dJMcac4Gt28/k1diPt47TR8oG3Nrsud0ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQAqLn%2FdJMcac4Gt28%2Fk1diPt47TR8oG3Nrsud0ck%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;1590&quot; height=&quot;508&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.17.49.png&quot; data-origin-width=&quot;1590&quot; data-origin-height=&quot;508&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;마지막으로, 절대 숨기지 않고 항상 표현해주고 싶은 메뉴가 있다면 이렇게 placement 속성에 tobBarPinned를 사용하면 되죠.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.19.24.png&quot; data-origin-width=&quot;1756&quot; data-origin-height=&quot;484&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dC413I/dJMcadbogga/Mz9PbZzAOLeDiDMnoGX470/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dC413I/dJMcadbogga/Mz9PbZzAOLeDiDMnoGX470/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dC413I/dJMcadbogga/Mz9PbZzAOLeDiDMnoGX470/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdC413I%2FdJMcadbogga%2FMz9PbZzAOLeDiDMnoGX470%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;1756&quot; height=&quot;484&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.19.24.png&quot; data-origin-width=&quot;1756&quot; data-origin-height=&quot;484&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;컨텐츠가 많아서 스크롤 시 네비게이션 바를 숨기고 싶다면 toolbarMinimizeBehavior 뷰 모디파이어를 이제는 사용하여 원하는것을 구현할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Document-based apps&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;지금까지 &lt;b&gt;SwiftUI는 문서 기반 앱을 지원&lt;/b&gt;해왔습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이번 릴리즈에선 이걸 기반으로 더 확장된 새로운 API를 가져왔어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Document creation context&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.24.08.png&quot; data-origin-width=&quot;1104&quot; data-origin-height=&quot;696&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/raQYd/dJMcacjhPMF/XUksstkvif5Ms6HNHvkHH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/raQYd/dJMcacjhPMF/XUksstkvif5Ms6HNHvkHH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/raQYd/dJMcacjhPMF/XUksstkvif5Ms6HNHvkHH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FraQYd%2FdJMcacjhPMF%2FXUksstkvif5Ms6HNHvkHH0%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;557&quot; height=&quot;351&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.24.08.png&quot; data-origin-width=&quot;1104&quot; data-origin-height=&quot;696&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이제 이렇게 &lt;b&gt;문서를 생성할때 빈 문서 혹은 사진으로 바로 문서를 만들 수 있어요.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이걸 가능하게 하는 코드들이 들어가서 구성할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.25.21.png&quot; data-origin-width=&quot;1370&quot; data-origin-height=&quot;804&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blHZSJ/dJMcaff6zaJ/lGYoUuNugpZ47kkxHKV1ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blHZSJ/dJMcaff6zaJ/lGYoUuNugpZ47kkxHKV1ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blHZSJ/dJMcaff6zaJ/lGYoUuNugpZ47kkxHKV1ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblHZSJ%2FdJMcaff6zaJ%2FlGYoUuNugpZ47kkxHKV1ck%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;1370&quot; height=&quot;804&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.25.21.png&quot; data-origin-width=&quot;1370&quot; data-origin-height=&quot;804&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이렇게 DocumentGroupLaunchScene에서 버튼을 두개 blank, photo로 구성합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.25.28.png&quot; data-origin-width=&quot;1434&quot; data-origin-height=&quot;690&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/McJhU/dJMcadoWstS/nEjtykFSfOKzts6Q69lwSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/McJhU/dJMcadoWstS/nEjtykFSfOKzts6Q69lwSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/McJhU/dJMcadoWstS/nEjtykFSfOKzts6Q69lwSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMcJhU%2FdJMcadoWstS%2FnEjtykFSfOKzts6Q69lwSk%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;1434&quot; height=&quot;690&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.25.28.png&quot; data-origin-width=&quot;1434&quot; data-origin-height=&quot;690&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;그 후 DocumentGroup 구성으로 context를 넘겨주는것이죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;그러면 blank, photo 컨텍스트가 넘어가 만약 photo라면 자동으로 바로 사진 선택창을 띄우게 되는것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Performance&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;문서 기반 앱은 잦은 업데이트가 있고 또한 그에 따라 UI 업데이트도 잦을 수 있죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;성능은 어떻게 최적화 시켰을까요?&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.28.44.png&quot; data-origin-width=&quot;586&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B7XMw/dJMcaiRnVBy/ygXhodgcD2uZQnMqpRTWY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B7XMw/dJMcaiRnVBy/ygXhodgcD2uZQnMqpRTWY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B7XMw/dJMcaiRnVBy/ygXhodgcD2uZQnMqpRTWY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB7XMw%2FdJMcaiRnVBy%2FygXhodgcD2uZQnMqpRTWY0%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;469&quot; height=&quot;176&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.28.44.png&quot; data-origin-width=&quot;586&quot; data-origin-height=&quot;220&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;우선은 가장 기본적으로 Obervable 매크로를 이용합니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이를 통해 업데이트 되어야 할 친구들만 업데이트 쳐서 성능을 어느정도 보장해주죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그치만, 가장 중요한건 읽기/쓰기 성능이죠.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.31.08.png&quot; data-origin-width=&quot;1434&quot; data-origin-height=&quot;634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwRa5N/dJMcafAnkFZ/xB9Co9EZfAuoICe3RcNWV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwRa5N/dJMcafAnkFZ/xB9Co9EZfAuoICe3RcNWV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwRa5N/dJMcafAnkFZ/xB9Co9EZfAuoICe3RcNWV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcwRa5N%2FdJMcafAnkFZ%2FxB9Co9EZfAuoICe3RcNWV0%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;1434&quot; height=&quot;634&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.31.08.png&quot; data-origin-width=&quot;1434&quot; data-origin-height=&quot;634&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;여기서 새로운 API가 등장합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;성능 향상을 위해 우선 WritableDocument 프로토콜을 채택합니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이는 세가지의 준수사항을 가지고 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;1️⃣ writableContentTypes: 문서의 타입을 나타냅니다. 여기서는 커스텀한 스티커문서 타입을 지정해줬어요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;2️⃣ snapshot: 쓰기 스냅샷을 지원해줍니다. 커스텀한 PageSnapshot 객체를 만들어 사용할 수 있죠.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;3️⃣ writer: DocumentWriter 프로토콜을 준수하며 지정된 형식으로 문서를 디스크에 쓰는 방법입니다. 요청된 컨텐츠 형식을 지정해요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;DocumentWriter 프로토콜에는 snapshot의 개념이 존재합니다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.34.33.png&quot; data-origin-width=&quot;1308&quot; data-origin-height=&quot;622&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xNrEp/dJMb99UqUjH/pXTW8O73RfvK2SbibokEeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xNrEp/dJMb99UqUjH/pXTW8O73RfvK2SbibokEeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xNrEp/dJMb99UqUjH/pXTW8O73RfvK2SbibokEeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxNrEp%2FdJMb99UqUjH%2FpXTW8O73RfvK2SbibokEeK%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;1308&quot; height=&quot;622&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.34.33.png&quot; data-origin-width=&quot;1308&quot; data-origin-height=&quot;622&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;여기서 준수할 사항은 write죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;write 메서드는 nonisolated이자 비동기입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;즉, 비용이 많이 드는 쓰기 작업 자체를 백그라운드에서 수행하게 하죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;그리고, snapshot을 통해 업데이트가 필요한 부분만을 쓰죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이런 최적화에도 불구하고 당연히 쓰기 작업은 오래걸릴 수도 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이때 progress인자로 주어지는 Subprogress API를 사용해 진행 사항을 알 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그 다음 ReadableDocument도 있어요.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.38.17.png&quot; data-origin-width=&quot;1750&quot; data-origin-height=&quot;934&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ldf5Z/dJMcaiRnV8R/ckO9ZJSWJCbmIFcaIfA1N1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ldf5Z/dJMcaiRnV8R/ckO9ZJSWJCbmIFcaIfA1N1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ldf5Z/dJMcaiRnV8R/ckO9ZJSWJCbmIFcaIfA1N1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fldf5Z%2FdJMcaiRnV8R%2FckO9ZJSWJCbmIFcaIfA1N1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1750&quot; height=&quot;934&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.38.17.png&quot; data-origin-width=&quot;1750&quot; data-origin-height=&quot;934&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;둘은 쌍둥이라고 볼 수 있을 정도로 완벽하게 대칭됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;당연하겠죠?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 두가지를 활용하여 문서 읽기/쓰기 성능을 향상시켰습니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;First-class support for URL access&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;페이지를 이미지로 저장할 수도 있어야겠죠?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;앱이 없는 사람도 충분히 있으니까요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Document API writer를 활용하면 충분히 다른 형식으로도 저장이 가능합니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.40.28.png&quot; data-origin-width=&quot;1404&quot; data-origin-height=&quot;260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfy2hF/dJMcabSdQyK/TlIhYmMlWbuxgW4nvFKSX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfy2hF/dJMcabSdQyK/TlIhYmMlWbuxgW4nvFKSX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfy2hF/dJMcabSdQyK/TlIhYmMlWbuxgW4nvFKSX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcfy2hF%2FdJMcabSdQyK%2FTlIhYmMlWbuxgW4nvFKSX1%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;1404&quot; height=&quot;260&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.40.28.png&quot; data-origin-width=&quot;1404&quot; data-origin-height=&quot;260&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;우선,&lt;b&gt; writableContentTypes에 png도 넣어줍니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이미지로 저장을 위해서요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.41.08.png&quot; data-origin-width=&quot;1298&quot; data-origin-height=&quot;748&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLtu5z/dJMcadoWsMM/nCPdKtNvy940lYgb3lvrn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLtu5z/dJMcadoWsMM/nCPdKtNvy940lYgb3lvrn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLtu5z/dJMcadoWsMM/nCPdKtNvy940lYgb3lvrn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLtu5z%2FdJMcadoWsMM%2FnCPdKtNvy940lYgb3lvrn1%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;1298&quot; height=&quot;748&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.41.08.png&quot; data-origin-width=&quot;1298&quot; data-origin-height=&quot;748&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;그리고 Writer 구현체에서 contentType이 png일때 하나의 이미지로 합쳐지도록 코드를 추가해줘요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 해주면 손쉽게 이미지로 문서를 저장할 수 있습니다  &lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Presentation and interaction&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;화면에 보이는 요소와 인터랙션에 대한 개선들이 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.43.09.png&quot; data-origin-width=&quot;996&quot; data-origin-height=&quot;440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIBs3C/dJMcacDHcmE/Wss5NQD5u082LdaaIADMvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIBs3C/dJMcacDHcmE/Wss5NQD5u082LdaaIADMvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIBs3C/dJMcacDHcmE/Wss5NQD5u082LdaaIADMvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIBs3C%2FdJMcacDHcmE%2FWss5NQD5u082LdaaIADMvK%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;996&quot; height=&quot;440&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.43.09.png&quot; data-origin-width=&quot;996&quot; data-origin-height=&quot;440&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;reorderable과 reorderContainer를 이용한다면 리스트에 있는 요소들의 순서를 내 마음대로 변경&lt;/b&gt;할 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이 Reorderable API는 List만이 아니라 모든 컨테이너에서도 동일하게 적용하고 동작할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 SwiftUI는 List뿐만 아니라 모든 뷰에서 스와이프 동작을 지원합니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.48.03.png&quot; data-origin-width=&quot;1596&quot; data-origin-height=&quot;554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bs9FIR/dJMcaiw6pX5/kYNz5Aguoim1dV7UkajZB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bs9FIR/dJMcaiw6pX5/kYNz5Aguoim1dV7UkajZB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bs9FIR/dJMcaiw6pX5/kYNz5Aguoim1dV7UkajZB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbs9FIR%2FdJMcaiw6pX5%2FkYNz5Aguoim1dV7UkajZB1%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;1596&quot; height=&quot;554&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.48.03.png&quot; data-origin-width=&quot;1596&quot; data-origin-height=&quot;554&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;swipeActionsContatiner를 붙이고 그 안에서 아이템 섹션에는 원하는 swipeActions를 구성해주면 됩니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;또한 만약 항목을 제거하고싶다, 이 예시에서는 스티커를 제거하고 싶다? 라면 이렇게 할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.51.12.png&quot; data-origin-width=&quot;1504&quot; data-origin-height=&quot;792&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0T83o/dJMcageX3su/FQE9S4ngqSAE5AyKrW85GK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0T83o/dJMcageX3su/FQE9S4ngqSAE5AyKrW85GK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0T83o/dJMcageX3su/FQE9S4ngqSAE5AyKrW85GK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0T83o%2FdJMcageX3su%2FFQE9S4ngqSAE5AyKrW85GK%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;1504&quot; height=&quot;792&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.51.12.png&quot; data-origin-width=&quot;1504&quot; data-origin-height=&quot;792&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;우선 요렇게 contextMenu를 통해 삭제 버튼을 배치하고 stickerToDelete 변수에 저장되도록 해줍니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.52.04.png&quot; data-origin-width=&quot;1510&quot; data-origin-height=&quot;912&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnZcIc/dJMcadvGqJy/LqO2798NSEpBOrEP3uuNnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnZcIc/dJMcadvGqJy/LqO2798NSEpBOrEP3uuNnK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnZcIc/dJMcadvGqJy/LqO2798NSEpBOrEP3uuNnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnZcIc%2FdJMcadvGqJy%2FLqO2798NSEpBOrEP3uuNnK%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;1510&quot; height=&quot;912&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.52.04.png&quot; data-origin-width=&quot;1510&quot; data-origin-height=&quot;912&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;그리고 이렇게 이번 API에서 업데이트된 confirmationDiaglog를 통해 삭제 다이얼로그를 구성하고 삭제나 다른 동작을 할 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이건 alert 모디파이어로도 대체할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 밖에도 무수한 업데이트 사항들이 있어요ㅎㅎ&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Data flow and performance&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 데이터 흐름과 성능 주요 개선 사항들에 대해 살펴볼께요.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;잘 알고 있는, AsyncImage는 온라인의 이미지를 나타내는데 용이하고 나타날때 그려줬죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;그리고, 지금까지는 이미지를 메모리에 유지하지 않았어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;즉, 캐싱이 없었죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;그렇기에 다시 위로 스크롤하면 다시 그려줬습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이제 iOS 27부터는 AsyncImage가 표준 HTTP 캐싱을 지원해줍니다  &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;즉, 기본적으로 이미지 캐싱이 되는거죠!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;별다른 코드 변경없이도 자동으로 적용됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.57.43.png&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baw7t5/dJMcahLHUgt/OF7ycDLnKEkfSwu9m7Q1mK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baw7t5/dJMcahLHUgt/OF7ycDLnKEkfSwu9m7Q1mK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baw7t5/dJMcahLHUgt/OF7ycDLnKEkfSwu9m7Q1mK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbaw7t5%2FdJMcahLHUgt%2FOF7ycDLnKEkfSwu9m7Q1mK%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;703&quot; height=&quot;215&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.57.43.png&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;270&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;물론, cachePolicy 파라미터가 생겨 원하는 캐시 정책을 설정할 수도 있습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.58.40.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;828&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dDDgvZ/dJMcac4GvBd/IjakI1UIg57HhEaTsc1Auk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dDDgvZ/dJMcac4GvBd/IjakI1UIg57HhEaTsc1Auk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dDDgvZ/dJMcac4GvBd/IjakI1UIg57HhEaTsc1Auk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdDDgvZ%2FdJMcac4GvBd%2FIjakI1UIg57HhEaTsc1Auk%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;540&quot; height=&quot;437&quot; data-filename=&quot;스크린샷 2026-06-29 오전 10.58.40.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;828&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;아니면, 이렇게 아예 커스텀한 캐시 정책을 추가할 수도 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;앱 데이터를 저장하는 좋은 방법은 Observable 클래스를 이용하는것이죠.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 11.00.18.png&quot; data-origin-width=&quot;1456&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbgKRj/dJMcacKsNT5/XOfLRt7cuPAzImQ7JMqOE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbgKRj/dJMcacKsNT5/XOfLRt7cuPAzImQ7JMqOE0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbgKRj/dJMcacKsNT5/XOfLRt7cuPAzImQ7JMqOE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbgKRj%2FdJMcacKsNT5%2FXOfLRt7cuPAzImQ7JMqOE0%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;1456&quot; height=&quot;500&quot; data-filename=&quot;스크린샷 2026-06-29 오전 11.00.18.png&quot; data-origin-width=&quot;1456&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이전까지는 &lt;b&gt;이 코드에서 만약 상위 뷰가 업데이트되어서 StickerStoreView가 초기화되면 StickerStore의 새 인스턴스가 만들어졌어요.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;하지만 원래 인스턴스가 여전히 State 변수에 저장되어 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;그렇기에, 새 인스턴스는 그냥 버려졌죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이 기존 방식은 매번 초기화될때마다 새 인스턴스를 버리고 낭비하는 아주 안좋은 성능이였습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이제는 State 프로퍼티를 사용하여 초기화되고 저장되는 클래스가 lazy하게 되었습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;즉, 한번만 초기화된다는 소리죠  &lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이를 가능하게 하는건, @State Dynamic Property에서 @State Macro로 변환되었기에 가능합니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 11.03.38.png&quot; data-origin-width=&quot;870&quot; data-origin-height=&quot;160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBN1D7/dJMcabdAKtn/o0kEkkZEN2TrnImqWpgPM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBN1D7/dJMcabdAKtn/o0kEkkZEN2TrnImqWpgPM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBN1D7/dJMcabdAKtn/o0kEkkZEN2TrnImqWpgPM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBN1D7%2FdJMcabdAKtn%2Fo0kEkkZEN2TrnImqWpgPM1%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;870&quot; height=&quot;160&quot; data-filename=&quot;스크린샷 2026-06-29 오전 11.03.38.png&quot; data-origin-width=&quot;870&quot; data-origin-height=&quot;160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이제는 이후 초기화에서는 새 클래스 인스턴스를 만들지 않게 됩니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;더 좋은 소식은, 이 변환은 하위 호환도 백포팅 되어서 iOS 17도 적용이 자연스레 되었다는 점입니다!&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 11.06.02.png&quot; data-origin-width=&quot;1472&quot; data-origin-height=&quot;590&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tjZhn/dJMcaftz03L/I2rZF5K6xRHYzXlDiweuQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tjZhn/dJMcaftz03L/I2rZF5K6xRHYzXlDiweuQ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tjZhn/dJMcaftz03L/I2rZF5K6xRHYzXlDiweuQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtjZhn%2FdJMcaftz03L%2FI2rZF5K6xRHYzXlDiweuQ1%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;1472&quot; height=&quot;590&quot; data-filename=&quot;스크린샷 2026-06-29 오전 11.06.02.png&quot; data-origin-width=&quot;1472&quot; data-origin-height=&quot;590&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;다만 이제는 이 변경으로 인해 이전 버전에서 이렇게 사용하고 있던 코드들이 초기화 관련 에러를 뱉을 수 있게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;즉, 선언 시 할당하지 않아야 합니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 11.09.07.png&quot; data-origin-width=&quot;1706&quot; data-origin-height=&quot;498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ml1ht/dJMcaaTmhBZ/c3hvLwSH4Z7tn9F4RP88a1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ml1ht/dJMcaaTmhBZ/c3hvLwSH4Z7tn9F4RP88a1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ml1ht/dJMcaaTmhBZ/c3hvLwSH4Z7tn9F4RP88a1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fml1ht%2FdJMcaaTmhBZ%2Fc3hvLwSH4Z7tn9F4RP88a1%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;1706&quot; height=&quot;498&quot; data-filename=&quot;스크린샷 2026-06-29 오전 11.09.07.png&quot; data-origin-width=&quot;1706&quot; data-origin-height=&quot;498&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;그리고 어쩌면 가장 많이 개발자들을 괴롭히고 마주칠 수 있는 부분인데요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;뷰에 많은 중첩된 표현이 있다면 이렇게 컴파일러가 오류를 냅니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;즉, 주어진 해당 시간안에 컴파일러가 타입 체킹을 하기 어렵다는 투정이죠.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 11.11.53.png&quot; data-origin-width=&quot;1792&quot; data-origin-height=&quot;716&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6PT8r/dJMcaiw6rBp/4kAmz6P7ETSA0DlBzMBCvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6PT8r/dJMcaiw6rBp/4kAmz6P7ETSA0DlBzMBCvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6PT8r/dJMcaiw6rBp/4kAmz6P7ETSA0DlBzMBCvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6PT8r%2FdJMcaiw6rBp%2F4kAmz6P7ETSA0DlBzMBCvK%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;1792&quot; height=&quot;716&quot; data-filename=&quot;스크린샷 2026-06-29 오전 11.11.53.png&quot; data-origin-width=&quot;1792&quot; data-origin-height=&quot;716&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이런일이 발생하는 &lt;b&gt;근본적인 원인은 컴파일러가 해당 컴포넌트를 그릴때 어떤 조건으로 그릴지 모르기에 다 시도해봐야되는거죠.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이렇게 선택지가 많고 중첩되면 더 복잡해질 수 밖에 없죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 복잡한걸 생성 유형에 제약을 받지 않고 컨텐츠를 그저 조합하기만 한다면 얼마나 좋을까요?&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이게 바로 이번 릴리즈에서 이룬것입니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 11.13.40.png&quot; data-origin-width=&quot;396&quot; data-origin-height=&quot;790&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUCiuF/dJMcaglH9bc/BlMN4l3ykBVG1CGSwN5fL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUCiuF/dJMcaglH9bc/BlMN4l3ykBVG1CGSwN5fL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUCiuF/dJMcaglH9bc/BlMN4l3ykBVG1CGSwN5fL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUCiuF%2FdJMcaglH9bc%2FBlMN4l3ykBVG1CGSwN5fL1%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;285&quot; height=&quot;569&quot; data-filename=&quot;스크린샷 2026-06-29 오전 11.13.40.png&quot; data-origin-width=&quot;396&quot; data-origin-height=&quot;790&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;가장 일반적인 빌더 집합이 이제 단일 이니셜라이저를 공유해 단 하나의 명확한 경로만 남깁니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 11.14.30.png&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;290&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cagujx/dJMcaiX4ZU0/H24972jGxVHBgYDzeQ9SAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cagujx/dJMcaiX4ZU0/H24972jGxVHBgYDzeQ9SAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cagujx/dJMcaiX4ZU0/H24972jGxVHBgYDzeQ9SAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcagujx%2FdJMcaiX4ZU0%2FH24972jGxVHBgYDzeQ9SAK%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;800&quot; height=&quot;290&quot; data-filename=&quot;스크린샷 2026-06-29 오전 11.14.30.png&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;290&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;ContentBuilder가 나타났기에 가능한 일입니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;여러 다른 빌더 유형이 하나로 통합되었어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;단일 빌더를 위해서요!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이는 기존 ViewBuilder의 진화로 모든 타겟 버전에서 사용할 수 있습니다  &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 이제는 AI 시대니까..&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이 명령어 한줄로 Swift나 SwiftUI 관한 애플의 스킬을 익스포트 받을 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-29 오전 11.19.06.png&quot; data-origin-width=&quot;1420&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0ncIm/dJMcaaeMCki/tdSzcZlzutCCXmbqvMJeW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0ncIm/dJMcaaeMCki/tdSzcZlzutCCXmbqvMJeW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0ncIm/dJMcaaeMCki/tdSzcZlzutCCXmbqvMJeW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0ncIm%2FdJMcaaeMCki%2FtdSzcZlzutCCXmbqvMJeW0%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;1420&quot; height=&quot;168&quot; data-filename=&quot;스크린샷 2026-06-29 오전 11.19.06.png&quot; data-origin-width=&quot;1420&quot; data-origin-height=&quot;168&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;Conclusion&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;개인적으로 엄청 많은 변화는 없다고 느껴지는데 알짜인 변화들이 있어 보여요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;AsyncImage도 이미지 캐싱이 되지 않아 쓰는 선택지에서 배제되었었는데 이제는 지원&lt;/b&gt;해준다니 감개무량하네요!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;또한, &lt;b&gt;SwiftUI View 성능이 정말 항상 불만이였는데, 특히 컴파일러 뷰 타입 체크 성능 관련&lt;/b&gt;해서...&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이것 또한 개선되었다니 큰 업데이트라고 생각됩니다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이게 다 소개처럼 잘 작동하고 정말 체감이 되는거라면 Xcode 27로 업데이트 하지 않을 이유가 없네요ㅎㅎ&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1782699594963&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;SwiftUI의 새로운 기능 - WWDC26 - 비디오 - Apple Developer&quot; data-og-description=&quot;SwiftUI에 추가된 최신 기능을 살펴보고, 이러한 기능이 앱을 어떻게 향상할 수 있는지 알아보세요. 고성능 앱 빌드를 위한 직접 디스크 접근과 스냅샷 기반 비교 기능을 갖춘 새로운 Document 프로&quot; data-og-host=&quot;developer.apple.com&quot; data-og-source-url=&quot;https://developer.apple.com/kr/videos/play/wwdc2026/269/&quot; data-og-url=&quot;https://developer.apple.com/kr/videos/play/wwdc2026/269/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/uBX4p/dJMb85vZCfE/pIKIn5JSYecFBsTll1ehSk/img.jpg?width=500&amp;amp;height=282&amp;amp;face=123_51_397_99,https://scrap.kakaocdn.net/dn/xUIbm/dJMb9eTZ0mr/Htj7lRpvtkJKSI9xGztYmk/img.jpg?width=1800&amp;amp;height=1012&amp;amp;face=447_182_1419_348&quot;&gt;&lt;a href=&quot;https://developer.apple.com/kr/videos/play/wwdc2026/269/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.apple.com/kr/videos/play/wwdc2026/269/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/uBX4p/dJMb85vZCfE/pIKIn5JSYecFBsTll1ehSk/img.jpg?width=500&amp;amp;height=282&amp;amp;face=123_51_397_99,https://scrap.kakaocdn.net/dn/xUIbm/dJMb9eTZ0mr/Htj7lRpvtkJKSI9xGztYmk/img.jpg?width=1800&amp;amp;height=1012&amp;amp;face=447_182_1419_348');&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;SwiftUI의 새로운 기능 - WWDC26 - 비디오 - Apple Developer&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;SwiftUI에 추가된 최신 기능을 살펴보고, 이러한 기능이 앱을 어떻게 향상할 수 있는지 알아보세요. 고성능 앱 빌드를 위한 직접 디스크 접근과 스냅샷 기반 비교 기능을 갖춘 새로운 Document 프로&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.apple.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>SwiftUI</category>
      <category>Apple</category>
      <category>ios</category>
      <category>swiftUI</category>
      <category>What's new in SwiftUI</category>
      <category>WWDC 2026</category>
      <author>GREEN.1229</author>
      <guid isPermaLink="true">https://green1229.tistory.com/626</guid>
      <comments>https://green1229.tistory.com/626#entry626comment</comments>
      <pubDate>Mon, 29 Jun 2026 11:29:03 +0900</pubDate>
    </item>
    <item>
      <title>What's new in Swift (feat. WWDC 2026)</title>
      <link>https://green1229.tistory.com/625</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;안녕하세요. &lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;그린&lt;/b&gt;&lt;/span&gt;입니다 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이번 포스팅에서는 얼마전 진행되었던 WWDC 2026에 대해 이제 하나씩 정리해보고자 합니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;첫번째 시작은 What's new in Swift에요.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;WWDC 2026에서 소개된 Swift 변화에 대한 핵심적인 것들을 세션을 보며 정리해보겠습니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;특히 Swift 6.3과 Swift 6.4 기반에서 변화된 정리 내용이 주입니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1782096052728&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;Swift의 새로운 기능 - WWDC26 - 비디오 - Apple Developer&quot; data-og-description=&quot;Swift 관련 업데이트를 확인해 보세요. 일상적인 인체공학, 향상된 동시성, 더 안전한 고성능 코드를 위한 업데이트 등 언어 관련 최신 혁신 기술을 알아보세요. Embedded Swift의 워크플로와 언어 상&quot; data-og-host=&quot;developer.apple.com&quot; data-og-source-url=&quot;https://developer.apple.com/kr/videos/play/wwdc2026/262/&quot; data-og-url=&quot;https://developer.apple.com/kr/videos/play/wwdc2026/262/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/kyB4C/dJMb87gf74E/PnnNbXmn7DY52TZS9kKRQk/img.jpg?width=500&amp;amp;height=282&amp;amp;face=0_0_500_282,https://scrap.kakaocdn.net/dn/gDaX7/dJMb8XSfvrL/9HOMkuuKFhUyKMYAzPlGc1/img.jpg?width=1800&amp;amp;height=1012&amp;amp;face=0_0_1800_1012&quot;&gt;&lt;a href=&quot;https://developer.apple.com/kr/videos/play/wwdc2026/262/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.apple.com/kr/videos/play/wwdc2026/262/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/kyB4C/dJMb87gf74E/PnnNbXmn7DY52TZS9kKRQk/img.jpg?width=500&amp;amp;height=282&amp;amp;face=0_0_500_282,https://scrap.kakaocdn.net/dn/gDaX7/dJMb8XSfvrL/9HOMkuuKFhUyKMYAzPlGc1/img.jpg?width=1800&amp;amp;height=1012&amp;amp;face=0_0_1800_1012');&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;Swift의 새로운 기능 - WWDC26 - 비디오 - Apple Developer&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Swift 관련 업데이트를 확인해 보세요. 일상적인 인체공학, 향상된 동시성, 더 안전한 고성능 코드를 위한 업데이트 등 언어 관련 최신 혁신 기술을 알아보세요. Embedded Swift의 워크플로와 언어 상&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.apple.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;우선 개선사항들부터 살펴볼까요?&lt;/span&gt;&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Improvements&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;옵셔널 타입&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.43.11.png&quot; data-origin-width=&quot;1098&quot; data-origin-height=&quot;296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eD2JtW/dJMcag60azq/icKDSYYXCVBpbDNBzY5H0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eD2JtW/dJMcag60azq/icKDSYYXCVBpbDNBzY5H0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eD2JtW/dJMcag60azq/icKDSYYXCVBpbDNBzY5H0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeD2JtW%2FdJMcag60azq%2FicKDSYYXCVBpbDNBzY5H0k%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;337&quot; height=&quot;296&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.43.11.png&quot; data-origin-width=&quot;1098&quot; data-origin-height=&quot;296&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이전에는 some이나 any와 옵셔널을 같이 사용할때는 이렇게 괄호로 묶어야 됐어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이는 연산자 우선순위 규칙 관련해서 필수였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이제는 아래와 같이 컴파일러가 똑디하게 판단해주기에 묶지 않아도 되게 되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Swift 6.4부터요.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.44.28.png&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;302&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt5Eg5/dJMcag60aCj/ldwJ7OHPEYYsfB5rccp1Uk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt5Eg5/dJMcag60aCj/ldwJ7OHPEYYsfB5rccp1Uk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt5Eg5/dJMcag60aCj/ldwJ7OHPEYYsfB5rccp1Uk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbt5Eg5%2FdJMcag60aCj%2FldwJ7OHPEYYsfB5rccp1Uk%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;348&quot; height=&quot;302&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.44.28.png&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;302&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Concurrency&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.47.54.png&quot; data-origin-width=&quot;1758&quot; data-origin-height=&quot;170&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rpuWZ/dJMcaijs2Ul/RXSReAeFyk7hrkeUkMNdF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rpuWZ/dJMcaijs2Ul/RXSReAeFyk7hrkeUkMNdF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rpuWZ/dJMcaijs2Ul/RXSReAeFyk7hrkeUkMNdF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrpuWZ%2FdJMcaijs2Ul%2FRXSReAeFyk7hrkeUkMNdF1%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;1758&quot; height=&quot;170&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.47.54.png&quot; data-origin-width=&quot;1758&quot; data-origin-height=&quot;170&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이제 이 컨커런시 관련하여 오류를 무시하면 경고가 나타납니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.48.45.png&quot; data-origin-width=&quot;614&quot; data-origin-height=&quot;380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Gehbj/dJMcagTvgRW/4z4RLRLWRJnkoZYDJKHmi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Gehbj/dJMcagTvgRW/4z4RLRLWRJnkoZYDJKHmi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Gehbj/dJMcagTvgRW/4z4RLRLWRJnkoZYDJKHmi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGehbj%2FdJMcagTvgRW%2F4z4RLRLWRJnkoZYDJKHmi1%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;515&quot; height=&quot;380&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.48.45.png&quot; data-origin-width=&quot;614&quot; data-origin-height=&quot;380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그래서 이제는 이렇게 작업 내 오류를 처리하거나,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.49.32.png&quot; data-origin-width=&quot;1084&quot; data-origin-height=&quot;432&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QpXE4/dJMcaf73TMZ/bJcvJ19kR0p7ufmUVRp451/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QpXE4/dJMcaf73TMZ/bJcvJ19kR0p7ufmUVRp451/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QpXE4/dJMcaf73TMZ/bJcvJ19kR0p7ufmUVRp451/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQpXE4%2FdJMcaf73TMZ%2FbJcvJ19kR0p7ufmUVRp451%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;512&quot; height=&quot;204&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.49.32.png&quot; data-origin-width=&quot;1084&quot; data-origin-height=&quot;432&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이렇게 작업을 저장해두었다가 나중에 처리하던가 해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.51.03.png&quot; data-origin-width=&quot;1388&quot; data-origin-height=&quot;428&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dUe132/dJMb991ajEG/3OkR6DFNs0sih0B4AAZgK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dUe132/dJMb991ajEG/3OkR6DFNs0sih0B4AAZgK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dUe132/dJMb991ajEG/3OkR6DFNs0sih0B4AAZgK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdUe132%2FdJMb991ajEG%2F3OkR6DFNs0sih0B4AAZgK1%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;630&quot; height=&quot;194&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.51.03.png&quot; data-origin-width=&quot;1388&quot; data-origin-height=&quot;428&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이제 defer block에서 async 함수를 호출하던 제한도 사라졌습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.51.59.png&quot; data-origin-width=&quot;670&quot; data-origin-height=&quot;256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u7pHc/dJMcajbv6zJ/yAWKLrA5kAPjcrT7iptK5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u7pHc/dJMcajbv6zJ/yAWKLrA5kAPjcrT7iptK5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u7pHc/dJMcajbv6zJ/yAWKLrA5kAPjcrT7iptK5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu7pHc%2FdJMcajbv6zJ%2FyAWKLrA5kAPjcrT7iptK5k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;552&quot; height=&quot;211&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.51.59.png&quot; data-origin-width=&quot;670&quot; data-origin-height=&quot;256&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;@Unchecked Sendable을 사용하던 클래스는 weak var 프로퍼티 때문이였을텐데요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이제 weak let으로 설정한다면 @Unchecked를 붙이지 않아도 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그리고 만약 타입이 Sendable일 필요가 없다면, 새로운 tilde Sendable 구문으로 명시적으로 나타낼 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;서브 클래스가 Sendable이 되는것도 막지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.54.28.png&quot; data-origin-width=&quot;1072&quot; data-origin-height=&quot;148&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dIWXmL/dJMcahSloo4/7lmmK0yC5eHl9BuESVzzQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dIWXmL/dJMcahSloo4/7lmmK0yC5eHl9BuESVzzQ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dIWXmL/dJMcahSloo4/7lmmK0yC5eHl9BuESVzzQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdIWXmL%2FdJMcahSloo4%2F7lmmK0yC5eHl9BuESVzzQ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;593&quot; height=&quot;82&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.54.28.png&quot; data-origin-width=&quot;1072&quot; data-origin-height=&quot;148&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Access level&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.55.21.png&quot; data-origin-width=&quot;1574&quot; data-origin-height=&quot;556&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/quLmk/dJMcagzapVj/CADZu7tUTYQ1TS4kAtR5CK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/quLmk/dJMcagzapVj/CADZu7tUTYQ1TS4kAtR5CK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/quLmk/dJMcagzapVj/CADZu7tUTYQ1TS4kAtR5CK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FquLmk%2FdJMcagzapVj%2FCADZu7tUTYQ1TS4kAtR5CK%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;1574&quot; height=&quot;556&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.55.21.png&quot; data-origin-width=&quot;1574&quot; data-origin-height=&quot;556&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;internal과 private을 같는 등의 서로 다른 접근 레벨 프로퍼티를 가진 구조체는 이제 두번째 멤버와이즈 이니셜라이저를 가지게 되어 다른 프로젝트에서도 사용이 가능하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;anyAppleOS&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.57.25.png&quot; data-origin-width=&quot;1602&quot; data-origin-height=&quot;188&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dxYeMw/dJMb997SSNj/QmBNKkjeqJB9Fc2S4BWYEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dxYeMw/dJMb997SSNj/QmBNKkjeqJB9Fc2S4BWYEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dxYeMw/dJMb997SSNj/QmBNKkjeqJB9Fc2S4BWYEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdxYeMw%2FdJMb997SSNj%2FQmBNKkjeqJB9Fc2S4BWYEk%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;630&quot; height=&quot;188&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.57.25.png&quot; data-origin-width=&quot;1602&quot; data-origin-height=&quot;188&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이제 각 macOS, iOS 이렇게 다 나열할 필요없이 27 버전부터는 통일되었기에 이렇게 anyAppleOS로 통합해서 사용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;가용성을 한번에 통합해서 주기에 편리하죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.58.37.png&quot; data-origin-width=&quot;1678&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c7iLK0/dJMcajo2IVa/saQNPGprXvzJwaf8j8WzKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c7iLK0/dJMcajo2IVa/saQNPGprXvzJwaf8j8WzKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7iLK0/dJMcajo2IVa/saQNPGprXvzJwaf8j8WzKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7iLK0%2FdJMcajo2IVa%2FsaQNPGprXvzJwaf8j8WzKk%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;609&quot; height=&quot;80&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.58.37.png&quot; data-origin-width=&quot;1678&quot; data-origin-height=&quot;220&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;물론 이렇게 통합하고 하나를 예외로 두는 설정도 가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;@diagnose&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.59.45.png&quot; data-origin-width=&quot;1656&quot; data-origin-height=&quot;366&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dyhgto/dJMcacXQI0O/SZKAhjTf0qqwVnjAKood80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dyhgto/dJMcacXQI0O/SZKAhjTf0qqwVnjAKood80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dyhgto/dJMcacXQI0O/SZKAhjTf0qqwVnjAKood80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdyhgto%2FdJMcacXQI0O%2FSZKAhjTf0qqwVnjAKood80%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;1656&quot; height=&quot;366&quot; data-filename=&quot;스크린샷 2026-06-22 오전 9.59.45.png&quot; data-origin-width=&quot;1656&quot; data-origin-height=&quot;366&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이렇게 디프리케이트된 API들은 경고가 뜨기 마련이죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이제는 이 경고를 나타나지 않게 할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 10.00.28.png&quot; data-origin-width=&quot;1556&quot; data-origin-height=&quot;370&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/R1nIu/dJMcai4LxKS/a9ratFAPULLhtOhtfhdnKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/R1nIu/dJMcai4LxKS/a9ratFAPULLhtOhtfhdnKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/R1nIu/dJMcai4LxKS/a9ratFAPULLhtOhtfhdnKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FR1nIu%2FdJMcai4LxKS%2Fa9ratFAPULLhtOhtfhdnKk%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;809&quot; height=&quot;192&quot; data-filename=&quot;스크린샷 2026-06-22 오전 10.00.28.png&quot; data-origin-width=&quot;1556&quot; data-origin-height=&quot;370&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;요런식으로요!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;다른 부분에선 영향을 주지 않고 해당 선언된 부분에서만 경고를 끌 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;추가로 인자로, StrictMemorySafety를 주어 보안이 중요한 메서드에서 unsafe API를 사용했는지 감시할 수도 있고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;ErrorInFutureSwiftVersion을 주어 특정 경고를 에러로 처리하는것도 가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Module Selectors&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Swift 6.3에서는 두 모듈에 동일한 이름의 API 있을때도 더 잘 처리하도록 해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 10.06.44.png&quot; data-origin-width=&quot;1062&quot; data-origin-height=&quot;642&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/738ji/dJMcadPVJHU/2jEAJiMFQbOqEnpZJnbeLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/738ji/dJMcadPVJHU/2jEAJiMFQbOqEnpZJnbeLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/738ji/dJMcadPVJHU/2jEAJiMFQbOqEnpZJnbeLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F738ji%2FdJMcadPVJHU%2F2jEAJiMFQbOqEnpZJnbeLk%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;589&quot; height=&quot;356&quot; data-filename=&quot;스크린샷 2026-06-22 오전 10.06.44.png&quot; data-origin-width=&quot;1062&quot; data-origin-height=&quot;642&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;같은 파일에 이렇게 두 모듈을 모두 임포트했다고 가정합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Swift는 원래 어떤걸 원하는지 몰라 에러를 내뱉어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그래서 우리는 Rocket.SaturnV 이렇게 더 명확한 경로를 주어 사용했죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 10.08.25.png&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;690&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bj33Co/dJMcaiKt0dM/4y7ozpUlHTH4a0P7kBsbAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bj33Co/dJMcaiKt0dM/4y7ozpUlHTH4a0P7kBsbAk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bj33Co/dJMcaiKt0dM/4y7ozpUlHTH4a0P7kBsbAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbj33Co%2FdJMcaiKt0dM%2F4y7ozpUlHTH4a0P7kBsbAk%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;523&quot; height=&quot;289&quot; data-filename=&quot;스크린샷 2026-06-22 오전 10.08.25.png&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;690&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그런데 만약 이렇게 Rocket 모듈안에 Rocket 타입이 있다면?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Swift는 모듈 이름보다 타입 이름을 더 우선시합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그래서 protocol에서 SaturnV를 찾게 되는것이죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;없으면 당연히 에러가 나겠죠?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그래서 Swift 6.3에서는 더블 콜론 문법을 도입했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 10.09.53.png&quot; data-origin-width=&quot;1354&quot; data-origin-height=&quot;710&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NCWbF/dJMcajbv65q/G9OSs05Wxr07bo2zHjexH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NCWbF/dJMcajbv65q/G9OSs05Wxr07bo2zHjexH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NCWbF/dJMcajbv65q/G9OSs05Wxr07bo2zHjexH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNCWbF%2FdJMcajbv65q%2FG9OSs05Wxr07bo2zHjexH1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;576&quot; height=&quot;302&quot; data-filename=&quot;스크린샷 2026-06-22 오전 10.09.53.png&quot; data-origin-width=&quot;1354&quot; data-origin-height=&quot;710&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이렇게 ::으로 경로를 지정하게 되면 모듈을 보게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;모듈 셀렉터라고 불러요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 10.10.57.png&quot; data-origin-width=&quot;1640&quot; data-origin-height=&quot;688&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bamS75/dJMcabxQsbO/Tk1yHpDblwVsfYtZm5FCWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bamS75/dJMcabxQsbO/Tk1yHpDblwVsfYtZm5FCWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bamS75/dJMcabxQsbO/Tk1yHpDblwVsfYtZm5FCWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbamS75%2FdJMcabxQsbO%2FTk1yHpDblwVsfYtZm5FCWK%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;691&quot; height=&quot;290&quot; data-filename=&quot;스크린샷 2026-06-22 오전 10.10.57.png&quot; data-origin-width=&quot;1640&quot; data-origin-height=&quot;688&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이건 이렇게 메서드나 프로퍼티에서도 사용이 가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;많이 유용할것 같아요  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;예를들어 SwiftUI에서 View 타입이 있는데, 모듈 이름도 View로 짓거나 하고 싶을 수도 있기에 이럴때 선택지가 없었는데 매우 도움이 될것 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제는 Swift 언어에 대한 개선 혹은 신규 사항들을 살펴봤으니, 다음으로 라이브러리에 대한 새로운 사항들을 살펴볼까요?  &lt;/span&gt;&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Libraries&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Standard Library&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 10.59.23.png&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;674&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJgnBR/dJMcabxQte5/ja3hGlHyyZxv0yX3KmhtUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJgnBR/dJMcabxQte5/ja3hGlHyyZxv0yX3KmhtUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJgnBR/dJMcabxQte5/ja3hGlHyyZxv0yX3KmhtUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJgnBR%2FdJMcabxQte5%2Fja3hGlHyyZxv0yX3KmhtUK%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;391&quot; height=&quot;343&quot; data-filename=&quot;스크린샷 2026-06-22 오전 10.59.23.png&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;674&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이제 Task 취소 쉴드 기능을 사용할 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;쉴드 내부에선 작업 취소 확인이 항상 false로 반환됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이미 시작한 작업을 완료하거나 롤백하는데 중요시 생각해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.01.11.png&quot; data-origin-width=&quot;1682&quot; data-origin-height=&quot;268&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bslw4S/dJMcajbv8FI/bROlw0x9f2JHvViS1tdxRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bslw4S/dJMcajbv8FI/bROlw0x9f2JHvViS1tdxRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bslw4S/dJMcajbv8FI/bROlw0x9f2JHvViS1tdxRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbslw4S%2FdJMcajbv8FI%2FbROlw0x9f2JHvViS1tdxRk%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;753&quot; height=&quot;120&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.01.11.png&quot; data-origin-width=&quot;1682&quot; data-origin-height=&quot;268&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;해당 mapKeyedValues가 생겼어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이걸 활용하면 키와 이전 값 모두 매핑 클로저에 전달해 새 값을 계산할 수 있죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.02.49.png&quot; data-origin-width=&quot;1088&quot; data-origin-height=&quot;384&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ba9a1g/dJMcadPVLiK/ltDK2iRQ3PNJup7O89t5T1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ba9a1g/dJMcadPVLiK/ltDK2iRQ3PNJup7O89t5T1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ba9a1g/dJMcadPVLiK/ltDK2iRQ3PNJup7O89t5T1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fba9a1g%2FdJMcadPVLiK%2FltDK2iRQ3PNJup7O89t5T1%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;653&quot; height=&quot;230&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.02.49.png&quot; data-origin-width=&quot;1088&quot; data-origin-height=&quot;384&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;플랫폼 마다 파일 경로를 나타내는것이 다를 수 있죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;올바르게 처리하기 까다로울 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이제는 Swift System의 타입을 기반으로 표준 라이브러리에 새로운 filepath 타입을 추가해 더욱 적절히 사용할 수 있게 되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Testing&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Swift 6.4의 테스팅은 테스트 동작에 대한 더 많은 제어권을 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.05.02.png&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;670&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ll1UB/dJMcajimTaj/wGiXorjF8Uwu8w76uHK6D0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ll1UB/dJMcajimTaj/wGiXorjF8Uwu8w76uHK6D0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ll1UB/dJMcajimTaj/wGiXorjF8Uwu8w76uHK6D0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLl1UB%2FdJMcajimTaj%2FwGiXorjF8Uwu8w76uHK6D0%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;686&quot; height=&quot;299&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.05.02.png&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;670&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Issue.record를 통해 치명적이지 않은 이슈들은 그냥 워닝으로만으로 설정할 수 도 있죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;CI 워크플로우를 방해하지 않게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그리고 Test.cancel API가 생겨서 테스트를 동적으로 취소할 수도 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.06.47.png&quot; data-origin-width=&quot;1454&quot; data-origin-height=&quot;906&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6kHJH/dJMcaglCXwE/qjlt1WibdnAXQLRKT80UwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6kHJH/dJMcaglCXwE/qjlt1WibdnAXQLRKT80UwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6kHJH/dJMcaglCXwE/qjlt1WibdnAXQLRKT80UwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6kHJH%2FdJMcaglCXwE%2Fqjlt1WibdnAXQLRKT80UwK%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;581&quot; height=&quot;362&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.06.47.png&quot; data-origin-width=&quot;1454&quot; data-origin-height=&quot;906&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Swift test 명령어에 테스트를 반복하는 새로운 기능도 생겼습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.08.39.png&quot; data-origin-width=&quot;1362&quot; data-origin-height=&quot;492&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/deChNa/dJMcahkCC7F/YqYl4X6j5YNcX8gMyIkRK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/deChNa/dJMcahkCC7F/YqYl4X6j5YNcX8gMyIkRK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/deChNa/dJMcahkCC7F/YqYl4X6j5YNcX8gMyIkRK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdeChNa%2FdJMcahkCC7F%2FYqYl4X6j5YNcX8gMyIkRK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;680&quot; height=&quot;246&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.08.39.png&quot; data-origin-width=&quot;1362&quot; data-origin-height=&quot;492&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Swift Test로 사용되는것들도 상호운용성 덕에 XCTest에서도 동일하게 사용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Subprocess&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;지난해 Subprocess 패키지를 애플이 발표했어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;쉽게 서브프로세스를 실행 시키기 위한 API를 포함한 패키지죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;올해 Subprocess 1.0을 출시합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.10.38.png&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;598&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciKBBt/dJMcaf1i7Wo/Czzs3hMiRM8KOy1sQcwDAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciKBBt/dJMcaf1i7Wo/Czzs3hMiRM8KOy1sQcwDAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciKBBt/dJMcaf1i7Wo/Czzs3hMiRM8KOy1sQcwDAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciKBBt%2FdJMcaf1i7Wo%2FCzzs3hMiRM8KOy1sQcwDAK%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;620&quot; height=&quot;410&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.10.38.png&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;598&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;피드백을 중점으로 여러 사항들이 개선되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;특히 크로스 플랫폼 지원도 강력해졌어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.11.46.png&quot; data-origin-width=&quot;1510&quot; data-origin-height=&quot;556&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3hcd8/dJMcaff1mz2/YSE8spXosK6YHsYvZn3fH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3hcd8/dJMcaff1mz2/YSE8spXosK6YHsYvZn3fH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3hcd8/dJMcaff1mz2/YSE8spXosK6YHsYvZn3fH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3hcd8%2FdJMcaff1mz2%2FYSE8spXosK6YHsYvZn3fH0%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;1510&quot; height=&quot;556&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.11.46.png&quot; data-origin-width=&quot;1510&quot; data-origin-height=&quot;556&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;예시로, 서브프로세스를 실행하기 위해 run 메서드를 호출할 때 표준 출력과 표준 오류 스트림을 AsyncBufferSequence로 실행 객체에 포함할 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이 모델은 각 스트림이 단 한번만 생성됨을 보장합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;strings() 메서드로 서브 프로세스를 라인 바이 라인으로 쉽게 읽을 수 있도록 보장해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Foundation&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.14.19.png&quot; data-origin-width=&quot;1348&quot; data-origin-height=&quot;584&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbG5Oq/dJMcag0cGCi/FG8cPtakdmEVNINkKAQv9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbG5Oq/dJMcag0cGCi/FG8cPtakdmEVNINkKAQv9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbG5Oq/dJMcag0cGCi/FG8cPtakdmEVNINkKAQv9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdbG5Oq%2FdJMcag0cGCi%2FFG8cPtakdmEVNINkKAQv9k%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;1348&quot; height=&quot;584&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.14.19.png&quot; data-origin-width=&quot;1348&quot; data-origin-height=&quot;584&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;ProgressManager라는게 Foundation 라이브러리 내에 생겼습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;진행 상황 보고를 위한 새 타입이죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Swift Concurrency로 설계되고 구조화되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.17.06.png&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;530&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6i0VW/dJMcahx6JmP/QzVgg4PVted1VkSSMqr9O1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6i0VW/dJMcahx6JmP/QzVgg4PVted1VkSSMqr9O1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6i0VW/dJMcahx6JmP/QzVgg4PVted1VkSSMqr9O1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6i0VW%2FdJMcahx6JmP%2FQzVgg4PVted1VkSSMqr9O1%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;916&quot; height=&quot;530&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.17.06.png&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;530&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;또한, Foundation에서 Data 부분도 더 개선되어 빨라졌습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Data와 NSData의 브릿징도 감소되었고 NSURL과 CFURL도 Swift에서 통합되었어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이런 큰 Foundation을 개선할 수 있는건 Swift의 언어 상호운용성 덕분에 가능하죠.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.19.15.png&quot; data-origin-width=&quot;1798&quot; data-origin-height=&quot;432&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIEC7e/dJMcadoRbc2/4qm5qjmsgctS7hCi17W5B1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIEC7e/dJMcadoRbc2/4qm5qjmsgctS7hCi17W5B1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIEC7e/dJMcadoRbc2/4qm5qjmsgctS7hCi17W5B1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIEC7e%2FdJMcadoRbc2%2F4qm5qjmsgctS7hCi17W5B1%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;1798&quot; height=&quot;432&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.19.15.png&quot; data-origin-width=&quot;1798&quot; data-origin-height=&quot;432&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;언어의 경계를 넘어 의미있는 크로스 플랫폼의 언어로 진화하고 있죠.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Full-stack Swift&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Interoperability&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Swift는 정말 어떤 분야도 막힐게 없는 풀스택 언어가 되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;특히 Swift 6.4에서는 언어 상호 운용성을 더 극대화 했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;크로스 플랫폼 IDE 지원을 개선하고 더 쉽고 안전하게 웹이나 임베디드 기기와 같은 다른 환경에 Swift 코드를 가져갈 수 있게 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Swift 6.4는 Swift로 작성된걸 C에 노출할 수 있게 합니다. (반대는 이미 가능했어요.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.22.22.png&quot; data-origin-width=&quot;510&quot; data-origin-height=&quot;314&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwEasK/dJMcag60dno/FeK77ZK22Ukj2jke1HStX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwEasK/dJMcag60dno/FeK77ZK22Ukj2jke1HStX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwEasK/dJMcag60dno/FeK77ZK22Ukj2jke1HStX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwEasK%2FdJMcag60dno%2FFeK77ZK22Ukj2jke1HStX1%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;510&quot; height=&quot;314&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.22.22.png&quot; data-origin-width=&quot;510&quot; data-origin-height=&quot;314&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이렇게 @c를 통해 사용할 수 있죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.23.56.png&quot; data-origin-width=&quot;1724&quot; data-origin-height=&quot;920&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VrXTO/dJMcabECGX0/dyKCSaGshQkbbmKTbuAjg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VrXTO/dJMcabECGX0/dyKCSaGshQkbbmKTbuAjg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VrXTO/dJMcabECGX0/dyKCSaGshQkbbmKTbuAjg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVrXTO%2FdJMcabECGX0%2FdyKCSaGshQkbbmKTbuAjg0%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;1724&quot; height=&quot;920&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.23.56.png&quot; data-origin-width=&quot;1724&quot; data-origin-height=&quot;920&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;@c와 @implementation 어노테이션을 사용하면 별도 C 선언 없이도 C 함수 구현이 가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;원래 헤더 파일에 이미 선언되어 있었으니까요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;만약 원래 C 헤더에 선언되어 있지 않았던거라면 @c만으로 충분하고 @implementation을 사용하지 않아야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이렇듯 Swift의 상호 운용성은 다른 언어로 작성된 코드 베이스에 Swift를 도입하는데 핵심입니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.26.52.png&quot; data-origin-width=&quot;1704&quot; data-origin-height=&quot;846&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSIqwl/dJMb991amSD/tkMKb4HaB16V38jgh6p0hk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSIqwl/dJMb991amSD/tkMKb4HaB16V38jgh6p0hk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSIqwl/dJMb991amSD/tkMKb4HaB16V38jgh6p0hk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSIqwl%2FdJMb991amSD%2FtkMKb4HaB16V38jgh6p0hk%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;1704&quot; height=&quot;846&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.26.52.png&quot; data-origin-width=&quot;1704&quot; data-origin-height=&quot;846&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Swift-Java는 Swift와 Java 사이 상호 운용성을 가능케 하는 패키지입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Java에서 async와 throwing Swift 함수 호출을 할 수 있게 지원해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그 외 Java 클래스를 Swift 프로토콜에 적합하게 만드는것도 가능하고요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;즉 이제, Java, Kotlin 환경에서 Swift 함수를 호출하는것이 자연스러워진것입니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Editor Support&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;VSCode용 Swift 익스텐션 최신 버전이 Swiftly와 새로운 통합을 추가합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;에디터에서 바로 swift.org의 툴체인을 쉽게 받아볼 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이제 어떤 에디터든 정확한 툴체인을 받아 볼 수 있죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Wasm&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;오픈 소스 툴체인으로 Web Assembly로 컴파일 할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Swift의 Wasm 지원은 동일한 언어로 네이티브 앱을 작성하고 BE, FE 모두 작성할 수 있는것이죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Embedded&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;더 제한된 환경에서도 Swift의 편의성을 활용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.37.10.png&quot; data-origin-width=&quot;756&quot; data-origin-height=&quot;604&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFzYH2/dJMcaaeHjkg/MWCiIRabAb6jDUuGJq6Sjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFzYH2/dJMcaaeHjkg/MWCiIRabAb6jDUuGJq6Sjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFzYH2/dJMcaaeHjkg/MWCiIRabAb6jDUuGJq6Sjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFzYH2%2FdJMcaaeHjkg%2FMWCiIRabAb6jDUuGJq6Sjk%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;595&quot; height=&quot;475&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.37.10.png&quot; data-origin-width=&quot;756&quot; data-origin-height=&quot;604&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;임베디드 Swift는 이제 existential 타입을 지원합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;프로토콜을 준수하는 여러 타입을 사용할 수 있게 된거죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Swift 6.4는 필요한 모든 메타 데이터를 DWARF 디버그 정보에 저장합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;임베디드 Swift 코어 덤프 디버깅 경험에 도움을 주죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 Swift 성능을 극대화하는 방법들을 들어볼까요?&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Performance ergonomics&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Optimizer controls&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Swift 컴파일러의 optimizer는 코드를 더 빠르게 만들기 위해 수십 가지 기법을 적용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그치만 잘못 적용하면 오히려 역효과가 날 수도 있죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.45.42.png&quot; data-origin-width=&quot;1652&quot; data-origin-height=&quot;918&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBAyLP/dJMcaiDMggr/e7ndq7hSCvdgkvd2aCdDxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBAyLP/dJMcaiDMggr/e7ndq7hSCvdgkvd2aCdDxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBAyLP/dJMcaiDMggr/e7ndq7hSCvdgkvd2aCdDxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBAyLP%2FdJMcaiDMggr%2Fe7ndq7hSCvdgkvd2aCdDxk%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;1652&quot; height=&quot;918&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.45.42.png&quot; data-origin-width=&quot;1652&quot; data-origin-height=&quot;918&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;예를들어, 컴파일러가 수행하는 가장 최적화중 하나는 인라이닝입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;함수 호출 코드 위치를 대체하고 특정 위치에 맞게 최적화하는거죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;만약 역효과가 난다면 더 빨라지진 않고 바이너리만 크게 만들 수 있죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그래서 이게 효과적일지를 판단하기 위해 함수와 호출 위치를 분석해요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;때론 잘못 판단할 수도 있기에 강제로 적용하는게 필요할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.48.08.png&quot; data-origin-width=&quot;1134&quot; data-origin-height=&quot;518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWQSVL/dJMcafG5rsu/e3hKXmd8Nb2ZYTZy1Ba0Ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWQSVL/dJMcafG5rsu/e3hKXmd8Nb2ZYTZy1Ba0Ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWQSVL/dJMcafG5rsu/e3hKXmd8Nb2ZYTZy1Ba0Ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWQSVL%2FdJMcafG5rsu%2Fe3hKXmd8Nb2ZYTZy1Ba0Ck%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;1134&quot; height=&quot;518&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.48.08.png&quot; data-origin-width=&quot;1134&quot; data-origin-height=&quot;518&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Swift 6.4에서 @inline(always) 기능이 생겼습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;기존에는 @inline(never) 속성만 있었고 대부분 이게 권장되었었는데 이제는 명시적으로 필요할 수 있다는걸 의미하는거죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그래서 이걸 사용할 때 웬만하면 final 키워드와 같이 사용하는걸 권장합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.50.36.png&quot; data-origin-width=&quot;1666&quot; data-origin-height=&quot;806&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbDPrF/dJMcabxQu0u/R7Rhx9XLT1NctRx62kG2y1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbDPrF/dJMcabxQu0u/R7Rhx9XLT1NctRx62kG2y1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbDPrF/dJMcabxQu0u/R7Rhx9XLT1NctRx62kG2y1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbDPrF%2FdJMcabxQu0u%2FR7Rhx9XLT1NctRx62kG2y1%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;1666&quot; height=&quot;806&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.50.36.png&quot; data-origin-width=&quot;1666&quot; data-origin-height=&quot;806&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;또 다른 최적화는 특수화입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이렇게 제네릭 오버헤드를 없애고 추가 최적화를 가능하게 해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.51.36.png&quot; data-origin-width=&quot;1654&quot; data-origin-height=&quot;732&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rx2Bl/dJMcafNSt10/396IOKB95dkDXPquVVIX8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rx2Bl/dJMcafNSt10/396IOKB95dkDXPquVVIX8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rx2Bl/dJMcafNSt10/396IOKB95dkDXPquVVIX8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Frx2Bl%2FdJMcafNSt10%2F396IOKB95dkDXPquVVIX8K%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;1654&quot; height=&quot;732&quot; data-filename=&quot;스크린샷 2026-06-22 오전 11.51.36.png&quot; data-origin-width=&quot;1654&quot; data-origin-height=&quot;732&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;하지만 때론 라이브러리에서 컴파일러가 함수를 어떻게 사용할 지 모를 수 있기에, 이를 직접 제어하기 위해 @specialized 어노테이션을 붙여 사용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Ownership enhancements&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;가장 큰 성능 향상을 이룬 개선을 살펴보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;바로 소유권 시스템입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Swift의 성능 문제는 대부분 복사 때문에 코스트가 발생하죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.30.59.png&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;670&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwqLpV/dJMcaf736iU/zgAJdGRHyerRxNfQFCpbD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwqLpV/dJMcaf736iU/zgAJdGRHyerRxNfQFCpbD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwqLpV/dJMcaf736iU/zgAJdGRHyerRxNfQFCpbD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwqLpV%2FdJMcaf736iU%2FzgAJdGRHyerRxNfQFCpbD1%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;1240&quot; height=&quot;670&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.30.59.png&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;670&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이런식은 다들 너무 잘 알거기에 긴 설명이 필요 없습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;복사로 인해 성능 저하를 해결하는 방법은 특정 상황에서 복사가 필요없다는걸 인식해야 해요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.34.27.png&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;666&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0wDr5/dJMcaaFNxL8/E4kZZVQW1BFFLBGKS8ZSuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0wDr5/dJMcaaFNxL8/E4kZZVQW1BFFLBGKS8ZSuK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0wDr5/dJMcaaFNxL8/E4kZZVQW1BFFLBGKS8ZSuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0wDr5%2FdJMcaaFNxL8%2FE4kZZVQW1BFFLBGKS8ZSuK%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;1032&quot; height=&quot;666&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.34.27.png&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;666&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;figure data-ke-type=&quot;image&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; data-ke-style=&quot;alignCenter&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot; class=&quot;bar_progress&quot;&gt;&lt;/span&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이렇게 복사를 피해 데이터를 객체에 넣어 그 객체를 다른 컴포넌트에 전달하는 방식으로도 할 수 있죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;대부분의 경우는 해결할 수 있지만 모든 경우는 아니에요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;객체에 참조 카운트가 있어 전달하면 참조 카운트가 변경되기에 그렇죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.36.19.png&quot; data-origin-width=&quot;1262&quot; data-origin-height=&quot;672&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MUjNS/dJMcag0cRqD/QytoXuaaiehPi0HaH4PzG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MUjNS/dJMcag0cRqD/QytoXuaaiehPi0HaH4PzG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MUjNS/dJMcag0cRqD/QytoXuaaiehPi0HaH4PzG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMUjNS%2FdJMcag0cRqD%2FQytoXuaaiehPi0HaH4PzG0%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;1262&quot; height=&quot;672&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.36.19.png&quot; data-origin-width=&quot;1262&quot; data-origin-height=&quot;672&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그래서 요즘 방식은 Borrow를 이용하는 겁니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;컴포넌트 2가 저장소 자체를 빌리는 동안은 컴포넌트 모두 읽기만 가능하고 쓸 순 없어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;컴포넌트 2가 먼저 끝내야 컴포넌트 1이 제어권을 가지게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.37.32.png&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;660&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bT8Ja2/dJMcacp3F6u/xmX6MQ5uxpXbtdjSTLKIa1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bT8Ja2/dJMcacp3F6u/xmX6MQ5uxpXbtdjSTLKIa1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bT8Ja2/dJMcacp3F6u/xmX6MQ5uxpXbtdjSTLKIa1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbT8Ja2%2FdJMcacp3F6u%2FxmX6MQ5uxpXbtdjSTLKIa1%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;1198&quot; height=&quot;660&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.37.32.png&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;660&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Mutate도 있는데, 다른 컴포넌트가 저장소에 접근하는것 자체도 완전 차단됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.39.09.png&quot; data-origin-width=&quot;1458&quot; data-origin-height=&quot;388&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b25F3m/dJMcaaeHuyR/GVAvk37YFTLH6jNgQ228p0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b25F3m/dJMcaaeHuyR/GVAvk37YFTLH6jNgQ228p0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b25F3m/dJMcaaeHuyR/GVAvk37YFTLH6jNgQ228p0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb25F3m%2FdJMcaaeHuyR%2FGVAvk37YFTLH6jNgQ228p0%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;1458&quot; height=&quot;388&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.39.09.png&quot; data-origin-width=&quot;1458&quot; data-origin-height=&quot;388&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이렇게 연관 타입도 이제 복사 불가능, 이스케피이 불가능 등을 지정할 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.41.05.png&quot; data-origin-width=&quot;1296&quot; data-origin-height=&quot;766&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bN2MoB/dJMcaaloxcJ/wVkpGjIdSzwRRQLvX9KGvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bN2MoB/dJMcaaloxcJ/wVkpGjIdSzwRRQLvX9KGvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bN2MoB/dJMcaaloxcJ/wVkpGjIdSzwRRQLvX9KGvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbN2MoB%2FdJMcaaloxcJ%2FwVkpGjIdSzwRRQLvX9KGvk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1296&quot; height=&quot;766&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.41.05.png&quot; data-origin-width=&quot;1296&quot; data-origin-height=&quot;766&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;복사 없이 for문 안에서 반복이 가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Sequence처럼 Iterable은 이터레이터를 생성해 for문이 요소를 가져오도록 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;하지만, 시퀀스하곤 달리 요소들을 배치로 가져옵니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.43.36.png&quot; data-origin-width=&quot;680&quot; data-origin-height=&quot;194&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d2DIxm/dJMcaiqd59j/67k5kK265KX2r4SZeVOTf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d2DIxm/dJMcaiqd59j/67k5kK265KX2r4SZeVOTf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d2DIxm/dJMcaiqd59j/67k5kK265KX2r4SZeVOTf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd2DIxm%2FdJMcaiqd59j%2F67k5kK265KX2r4SZeVOTf1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;680&quot; height=&quot;194&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.43.36.png&quot; data-origin-width=&quot;680&quot; data-origin-height=&quot;194&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;또한, borrow, mutate라는 새로운 접근제어자가 생겼어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;borrow는 공유 저장소에 대한 읽기 전용으로 동작합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;복사 없이요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;mutate는 수정도 가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;위에 우리가 살펴봤던것과 동일해요  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.48.44.png&quot; data-origin-width=&quot;1570&quot; data-origin-height=&quot;796&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GeSZ4/dJMcaay0f3T/v2vwLWc6AtW1P7Q8pkM7m1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GeSZ4/dJMcaay0f3T/v2vwLWc6AtW1P7Q8pkM7m1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GeSZ4/dJMcaay0f3T/v2vwLWc6AtW1P7Q8pkM7m1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGeSZ4%2FdJMcaay0f3T%2Fv2vwLWc6AtW1P7Q8pkM7m1%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;796&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.48.44.png&quot; data-origin-width=&quot;1570&quot; data-origin-height=&quot;796&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;또한 성능을 위한 대체 API들도 나왔으니 적극 활용해보면 좋을것 같아요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.50.36.png&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;606&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FeIVM/dJMcaf739gx/qPE3lCqGOi3wMnfJQKEVS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FeIVM/dJMcaf739gx/qPE3lCqGOi3wMnfJQKEVS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FeIVM/dJMcaf739gx/qPE3lCqGOi3wMnfJQKEVS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFeIVM%2FdJMcaf739gx%2FqPE3lCqGOi3wMnfJQKEVS0%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;1200&quot; height=&quot;606&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.50.36.png&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;606&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Ref와 MutableRef 타입을 통해 저장소에 접근도 제어할 수 있어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이전에는 이런식으로 활용되었죠.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.51.46.png&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;674&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cT8GGq/dJMb997S8CF/Qsq0nZwKHMZGoXrwkA71Tk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cT8GGq/dJMb997S8CF/Qsq0nZwKHMZGoXrwkA71Tk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cT8GGq/dJMb997S8CF/Qsq0nZwKHMZGoXrwkA71Tk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcT8GGq%2FdJMb997S8CF%2FQsq0nZwKHMZGoXrwkA71Tk%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;978&quot; height=&quot;674&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.51.46.png&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;674&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;inout을 통해서 말이죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.52.52.png&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;614&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d3dfnB/dJMcacp3Ik5/dPi36Nv8PKNd046RXFlOHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d3dfnB/dJMcacp3Ik5/dPi36Nv8PKNd046RXFlOHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d3dfnB/dJMcacp3Ik5/dPi36Nv8PKNd046RXFlOHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd3dfnB%2FdJMcacp3Ik5%2FdPi36Nv8PKNd046RXFlOHK%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;1032&quot; height=&quot;614&quot; data-filename=&quot;스크린샷 2026-06-22 오후 1.52.52.png&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;614&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이제는 MutableRef를 사용하여 보다 간단하게 표현할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Conclustion&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;이렇게 이번 WWDC 2026에서 소개된 Swift 파트를 살펴봤습니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그렇게 큰 변경이나 그런건 없어보여요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;틈틈히 Swift 6.3, Swift 6.4 릴리즈에 대한것들을 정리하고 살펴본적이 있어서 그런지 리캡 느낌이였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그래도 성능 부분에서 어떻게 언어적으로 잘 쓸 수 있는지에 대해 고민해보게 되고, 크로스 플랫폼 언어로 진화됨에 따라 앞으로는 더욱 포지션 별, 플랫폼 별 구분이 사라지는데 제약이 없을것 같다고 느껴지네요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1782104140244&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;Swift의 새로운 기능 - WWDC26 - 비디오 - Apple Developer&quot; data-og-description=&quot;Swift 관련 업데이트를 확인해 보세요. 일상적인 인체공학, 향상된 동시성, 더 안전한 고성능 코드를 위한 업데이트 등 언어 관련 최신 혁신 기술을 알아보세요. Embedded Swift의 워크플로와 언어 상&quot; data-og-host=&quot;developer.apple.com&quot; data-og-source-url=&quot;https://developer.apple.com/kr/videos/play/wwdc2026/262/&quot; data-og-url=&quot;https://developer.apple.com/kr/videos/play/wwdc2026/262/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/kyB4C/dJMb87gf74E/PnnNbXmn7DY52TZS9kKRQk/img.jpg?width=500&amp;amp;height=282&amp;amp;face=0_0_500_282,https://scrap.kakaocdn.net/dn/gDaX7/dJMb8XSfvrL/9HOMkuuKFhUyKMYAzPlGc1/img.jpg?width=1800&amp;amp;height=1012&amp;amp;face=0_0_1800_1012&quot;&gt;&lt;a href=&quot;https://developer.apple.com/kr/videos/play/wwdc2026/262/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.apple.com/kr/videos/play/wwdc2026/262/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/kyB4C/dJMb87gf74E/PnnNbXmn7DY52TZS9kKRQk/img.jpg?width=500&amp;amp;height=282&amp;amp;face=0_0_500_282,https://scrap.kakaocdn.net/dn/gDaX7/dJMb8XSfvrL/9HOMkuuKFhUyKMYAzPlGc1/img.jpg?width=1800&amp;amp;height=1012&amp;amp;face=0_0_1800_1012');&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;Swift의 새로운 기능 - WWDC26 - 비디오 - Apple Developer&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Swift 관련 업데이트를 확인해 보세요. 일상적인 인체공학, 향상된 동시성, 더 안전한 고성능 코드를 위한 업데이트 등 언어 관련 최신 혁신 기술을 알아보세요. Embedded Swift의 워크플로와 언어 상&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.apple.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>Swift</category>
      <category>Apple</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>Swift6.3</category>
      <category>Swift6.4</category>
      <category>what's new in swift</category>
      <category>WWDC 2026</category>
      <author>GREEN.1229</author>
      <guid isPermaLink="true">https://green1229.tistory.com/625</guid>
      <comments>https://green1229.tistory.com/625#entry625comment</comments>
      <pubDate>Mon, 22 Jun 2026 14:00:01 +0900</pubDate>
    </item>
  </channel>
</rss>