<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>ELLO의 개발일지</title>
    <link>https://minny27.tistory.com/</link>
    <description>⭐️ 방문해주셔서 감사합니다 ⭐️</description>
    <language>ko</language>
    <pubDate>Thu, 16 Apr 2026 15:51:46 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Minny27</managingEditor>
    <image>
      <title>ELLO의 개발일지</title>
      <url>https://tistory1.daumcdn.net/tistory/4667589/attach/6e24c72f32964b2291889daa5d81eb1c</url>
      <link>https://minny27.tistory.com</link>
    </image>
    <item>
      <title>깃으로 협업하기 - 실습편</title>
      <link>https://minny27.tistory.com/119</link>
      <description>&lt;p&gt;준비물: Xcode, Terminal&lt;/p&gt;
&lt;p&gt;Git Clone은 생략하겠습니다.&lt;/p&gt;
&lt;h3&gt;※ 우리팀 룰:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;develop&lt;/code&gt; 브랜치에 작업을 최신화한다(쌓는다)&lt;/li&gt;
&lt;li&gt;배포(스토어에 버전 업데이트)할 때 &lt;code&gt;main&lt;/code&gt;에 쌓아서 배포한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;(편의상 develop을 dev라고 하겠습니다.)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;항상 현재 브랜치를 &lt;code&gt;dev&lt;/code&gt;로 최신화(pull, merge)를 하고 작업을 시작합니다.&lt;/strong&gt;(다른 개발자의 작업이 &lt;code&gt;dev&lt;/code&gt;에 merge됐을 수 있음)&lt;/p&gt;
&lt;p&gt;터미널에서 작업 할 때, 항상 .git 파일이 포함되어 있는 경로로 이동해서 깃 명령어를 수행합니다.&lt;/p&gt;
&lt;p&gt;전체 과정은 다음과 같습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# develop으로 head 옮기기
git checkout develop

# devlop에서 will이라는 브랜치 생성
git checkout -b will

# 완료된 작업 임시저장
git stash

# develop으로 head 옮기기
git checkout develop

# develop 최신화
git pull

# will로 head 옮기기
git checkout will

# will을 develop으로 최신화하기(merge)
git merge develop

# 임시저장한 작업 불러오기
git stash apply stash@\{0\}

# 충돌 수정 후, add commit push&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(각각의 명령어는 추후에 순서대로 설명하겠습니다.)&lt;/p&gt;
&lt;h3&gt;1. 브랜치 생성하기&lt;/h3&gt;
&lt;p&gt;항상 브랜치를 생성할 때는 현재 &lt;code&gt;head&lt;/code&gt;가 어느 브랜치에 위치하고 있는지 확인합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 깃 생성
git branch will

# 깃 체크아웃
git checkout will

# 깃 생성 후 체크아웃
git checkout -b will&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;dev&lt;/code&gt;에서 &lt;code&gt;will&lt;/code&gt;이라는 브랜치를 생성 후 체크아웃&lt;/p&gt;
&lt;img src=&quot;https://github.com/Minny27/GitExample/assets/68800789/c82acb5a-e191-4cad-96d8-e34ae02b7c61&quot; width=40%&gt;

&lt;p&gt;이러면 &lt;code&gt;dev&lt;/code&gt;의 코드기반으로 분기가 나눠집니다.&lt;/p&gt;
&lt;p&gt;현재 &lt;code&gt;dev&lt;/code&gt; 브랜치의 코드가 다음과 같다고 가정하겠습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;class ViewController: UIViewController {

    let textLabel: UILabel = {
        let label = UILabel()
        label.text = &amp;quot;Hello World!&amp;quot;
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        setupUI()
    }

    private func setupUI() {
        view.addSubview(textLabel)

        NSLayoutConstraint.activate([
            textLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            textLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        ])
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;그런데 다른 개발자가 textLabel에 텍스트를 “plus person gogo”로 변경하고 텍스트 색깔을 blue로 변경했고, 이를 &lt;code&gt;develop&lt;/code&gt;에 머지했다고 가정하겠습니다.&lt;/p&gt;
&lt;p&gt;그리고 나(&lt;code&gt;will&lt;/code&gt;)은 textLabel의 텍스트를 “Will Nice!”로 수정했다고 가정하겠습니다.&lt;/p&gt;
&lt;p&gt;현재 &lt;code&gt;dev&lt;/code&gt; 브랜치&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;class ViewController: UIViewController {

    let textLabel: UILabel = {
        let label = UILabel()
        **label.text = &amp;quot;plus person gogo&amp;quot;**
        **label.textColor = .blue**
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()

        { ... }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;현재 &lt;code&gt;will&lt;/code&gt; 브랜치&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;class ViewController: UIViewController {

    let textLabel: UILabel = {
        let label = UILabel()
        **label.text = &amp;quot;Will Nice!&amp;quot;**
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()

        { ... }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 모든 작업이 완료되면, 자신의 작업을 임시저장(stash)합니다.&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git stash&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;git stash list 를 입력하면 다음과 같은 리스트가 생깁니다.&lt;br&gt;&lt;img src=&quot;https://github.com/Minny27/GitExample/assets/68800789/cab82ebe-8cbb-4039-93ee-18f7880962a0&quot; width=40%&gt;&lt;/p&gt;
&lt;h3&gt;3. &lt;code&gt;dev&lt;/code&gt; 브랜치 최신화&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git checkout develop
git pull&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;하지만 다음과 같이 git pull을 수행했을 때, 에러가 발생할 수 있음&lt;br&gt;&lt;img src=&quot;https://github.com/Minny27/GitExample/assets/68800789/4622653a-5cc6-461a-bb93-e80c33fb8663&quot; width=40%&gt;&lt;/p&gt;
&lt;p&gt;기본적으로 우리가 merge하는 방식으로 merge를 하고 싶을 때는&lt;/p&gt;
&lt;p&gt;git config pull.rebase false 로 pull받으면 됩니다.&lt;/p&gt;
&lt;h3&gt;4. &lt;code&gt;will&lt;/code&gt; 브랜치를 &lt;code&gt;dev&lt;/code&gt; 브랜치로 최신화(merge)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git checkout will
git merge develop&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;만약 stash하는 것을 까먹었다면 충돌 수정 후, add commit push&lt;/p&gt;
&lt;h3&gt;5. 임시 저장한 작업 불러오기&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git stash apply stash@\{0\}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;git stash list 로 먼저 검색 후, 해당 인덱스를 넣어 주면 됨.&lt;br&gt;&lt;img src=&quot;https://github.com/Minny27/GitExample/assets/68800789/ec251abf-bc5d-4452-a478-1bd90347d91a&quot; width=40%&gt;&lt;/p&gt;
&lt;h3&gt;6. 충돌 수정&lt;/h3&gt;
&lt;p&gt;임시 저장한 작업을 불러오면, 프로젝트에서 다음과 같은 에러가 발생함&lt;br&gt;&lt;img src=&quot;https://github.com/Minny27/GitExample/assets/68800789/367b511b-2e7a-4337-990b-10ef5e8f4440&quot; width=40%&gt;&lt;/p&gt;
&lt;p&gt;여기서 Updated upstream으로 감싸져 있는 코드는 최신화된 &lt;code&gt;dev&lt;/code&gt;의 코드이고&lt;/p&gt;
&lt;p&gt;Stashed changes로 감싸져 있는 코드는 임시 저장한 작업(&lt;code&gt;will&lt;/code&gt;)을 불러온 코드입니다.&lt;/p&gt;
&lt;p&gt;이 때, 자신이 수정한 코드로 바로 수정을 할 수도 있지만, 만약 정해진 게 없다면 팀원들과 상의 후, 수정 사항을 add commit push하면 됩니다.&lt;/p&gt;
&lt;p&gt;제가(&lt;code&gt;will&lt;/code&gt;) 수정한 파일을 적용해서 push하겠습니다.&lt;br&gt;&lt;img src=&quot;https://github.com/Minny27/GitExample/assets/68800789/6bfe50b7-a6e8-42f1-95d9-b025a181f24b&quot; width=40%&gt;&lt;/p&gt;
&lt;h3&gt;7. 수정 사항 반영&lt;/h3&gt;
&lt;img src=&quot;https://github.com/Minny27/GitExample/assets/68800789/c4affb31-e66e-4366-9d5e-fc120c0e43cc&quot; width=40%&gt;

&lt;p&gt;만약 push를 했는데 다음과 같은 에러가 발생할 수 있습니다.&lt;br&gt;&lt;img src=&quot;https://github.com/Minny27/GitExample/assets/68800789/3b36303a-6966-4de2-9f89-c62b077cc81a&quot; width=40%&gt;&lt;/p&gt;
&lt;p&gt;이 경우는 원격 저장소에 해당 브랜치가 없다는 의미이므로 위의 내용에서 사용하라는 명령어를 그대로 입력합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git push --set-upstream origin develop&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;수정 작업을 push 하고 Github에 가보면 다음과 같이 나타납니다.&lt;br&gt;&lt;img src=&quot;https://github.com/Minny27/GitExample/assets/68800789/3bcb2483-5c79-45be-b11c-74adc8f67c2a&quot; width=40%&gt;&lt;/p&gt;
&lt;p&gt;여기서 &lt;strong&gt;Compare &amp;amp; pull request&lt;/strong&gt;를 클릭하면 PR을 남길 수 있습니다.&lt;/p&gt;</description>
      <category>Git</category>
      <category>Git</category>
      <category>git 명령어</category>
      <category>github</category>
      <category>협업</category>
      <author>Minny27</author>
      <guid isPermaLink="true">https://minny27.tistory.com/119</guid>
      <comments>https://minny27.tistory.com/119#entry119comment</comments>
      <pubDate>Fri, 9 Jun 2023 12:00:07 +0900</pubDate>
    </item>
    <item>
      <title>기록 및 정리에 대한 생각's</title>
      <link>https://minny27.tistory.com/118</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;음.. 모르거나 궁금한 것들을 노션에 개인적으로 정리했었는데 이제는 블로그에 그때 그때 정리해보는 트라이를 해보려고 합니다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이유는 블로그 관리해야지.. 해야지.. 하다가 방치되서...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 쉬운 말, 더 잘 정리되어 있는 페이지이면 당연히 좋겠지만 '누군가의 시선을 생각하기보다 나의 생각 및 고민을 좀 더 직관적으로 표현하는 것이 중요한 건 아닐까?' 라는 생각이 들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 알게 되거나 안 되는 것에 대해서 그냥 적어보려고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;끝이 어디가 될지 모르겠지만 또 가봐야겠습니다. 화이팅!!&lt;/p&gt;</description>
      <category>기타</category>
      <category>기록</category>
      <category>생각</category>
      <category>정리</category>
      <author>Minny27</author>
      <guid isPermaLink="true">https://minny27.tistory.com/118</guid>
      <comments>https://minny27.tistory.com/118#entry118comment</comments>
      <pubDate>Mon, 27 Mar 2023 09:49:59 +0900</pubDate>
    </item>
    <item>
      <title>[iOS / RxSwift] Subject</title>
      <link>https://minny27.tistory.com/117</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;Subject&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;A Subject is a sort of bridge or proxy that is available in some implementations of ReactiveX that acts both as an observer and as an Observable. Because it is an observer, it can subscribe to one or more Observables, and because it is an Observable, it can pass through the items it observes by reemitting them, and it can also emit new items.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Subject&lt;/b&gt;는 observer와 Observable 모두로 작동하는 일부 ReactiveX 구현에서 사용할 수 있는 일종의 브리지 또는 프록시입니다. 옵저버이기 때문에 하나 이상의 옵저버블을 구독할 수 있고 옵저버블이기 때문에 관찰한 항목을 다시 방출하여 통과할 수 있으며 새 아이템을 방출할 수도 있습니다.&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: #5f6d2b;&quot;&gt;Because a Subject subscribes to an Observable, it will trigger that Observable to begin emitting items (if that Observable is &amp;ldquo;cold&amp;rdquo; &amp;mdash; that is, if it waits for a subscription before it begins to emit items). This can have the effect of making the resulting Subject a &amp;ldquo;hot&amp;rdquo; Observable variant of the original &amp;ldquo;cold&amp;rdquo; Observable.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Subject가 Observable을 구독하기 때문에 Observable이 항목 방출을 시작하도록 트리거합니다(그 Observable이 &quot;cold&quot;인 경우, 즉 항목을 방출하기 시작하기 전에 구독을 기다리는 경우). 이것은 결과 Subject를 원래 &quot;cold&quot; Observable의 &quot;hot&quot; Observable 변형으로 만드는 효과를 가질 수 있습니다.&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;color: #5f6d2b;&quot;&gt;&lt;b&gt;Varieties of Subject(Subject의 종류)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;There are four varieties of Subject that are designed for particular use cases. Not all of these are available in all implementations, and some implementations use other naming conventions (for example, in RxScala, what is called a &amp;ldquo;PublishSubject&amp;rdquo; here is known simply as a &amp;ldquo;Subject&amp;rdquo;):&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;특정 사용 사례를 위해 설계된 4가지 종류의 Subject가 있습니다. 이 모든 것이 모든 구현에서 사용할 수 있는 것은 아니며 일부 구현에서는 다른 명명 규칙을 사용합니다(예: RxScala에서는 여기에서 &quot;PublishSubject&quot;라고 하는 것을 단순히 &quot;Subject&quot;라고 함).&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;AsyncSubject&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6DiFz/btrLYlcxHMl/erekJwuYBsSY9ZidJEHgrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6DiFz/btrLYlcxHMl/erekJwuYBsSY9ZidJEHgrk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6DiFz/btrLYlcxHMl/erekJwuYBsSY9ZidJEHgrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6DiFz%2FbtrLYlcxHMl%2FerekJwuYBsSY9ZidJEHgrk%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;500&quot; height=&quot;316&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;810&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: #5f6d2b;&quot;&gt;An&amp;nbsp;AsyncSubject&amp;nbsp;emits the last value (and only the last value) emitted by the source Observable, and only after that source Observable completes. (If the source Observable does not emit any values, the&amp;nbsp;AsyncSubject&amp;nbsp;also completes without emitting any values.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;AsyncSubject는 source Observable이 내보낸 마지막 값(그리고 마지막 값만)을 내보냅니다.&lt;/b&gt; (소스 Observable이 값을 내보내지 않으면 AsyncSubject도 값을 내보내지 않고 완료됩니다.)&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-origin-width=&quot;1280&quot; data-origin-height=&quot;790&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQNFlm/btrLNqthWPw/AQYsTr9fhKf2oSEGzhAclK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQNFlm/btrLNqthWPw/AQYsTr9fhKf2oSEGzhAclK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQNFlm/btrLNqthWPw/AQYsTr9fhKf2oSEGzhAclK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQNFlm%2FbtrLNqthWPw%2FAQYsTr9fhKf2oSEGzhAclK%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;500&quot; height=&quot;309&quot; data-origin-width=&quot;1280&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;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;It will also emit this same final value to any subsequent observers. However, if the source Observable terminates with an error, the&amp;nbsp;AsyncSubject&amp;nbsp;will not emit any items, but will simply pass along the error notification from the source Observable.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;또한 후속 관찰자에게 동일한 최종 값을 내보냅니다. 그러나 &lt;b&gt;소스 Observable이 오류로 종료되면 AsyncSubject는 항목을 내보내지 않고 단순히 소스 Observable의 오류 알림을 전달합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;BehaviorSubject&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;830&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/09ct9/btrLTVMbTd9/b9lRZ2KmJJIHKB7FRoU88k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/09ct9/btrLTVMbTd9/b9lRZ2KmJJIHKB7FRoU88k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/09ct9/btrLTVMbTd9/b9lRZ2KmJJIHKB7FRoU88k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F09ct9%2FbtrLTVMbTd9%2Fb9lRZ2KmJJIHKB7FRoU88k%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;500&quot; height=&quot;324&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;830&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: #5f6d2b;&quot;&gt;When an observer subscribes to a&amp;nbsp;BehaviorSubject, it begins by emitting the item most recently emitted by the source Observable (or a seed/default value if none has yet been emitted) and then continues to emit any other items emitted later by the source Observable(s).&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;observer가 BehaviorSubject를 구독할 때, &lt;b&gt;소스 Observable에서 가장 최근에 내보낸 항목(또는 아직 내보내지 않은 경우 시드/기본값)을 내보내는 것으로 시작한 다음 소스 Observable에서 나중에 내보낸 다른 항목을 계속 내보냅니다.&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-origin-width=&quot;1280&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcmylj/btrLOnpsNmv/kDALci5HqIs24p9BAjAjb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcmylj/btrLOnpsNmv/kDALci5HqIs24p9BAjAjb0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcmylj/btrLOnpsNmv/kDALci5HqIs24p9BAjAjb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbcmylj%2FbtrLOnpsNmv%2FkDALci5HqIs24p9BAjAjb0%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;500&quot; height=&quot;316&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;810&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: #5f6d2b;&quot;&gt;However, if the source Observable terminates with an error, the&amp;nbsp;BehaviorSubject&amp;nbsp;will not emit any items to subsequent observers, but will simply pass along the error notification from the source Observable.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그러나&amp;nbsp;소스&amp;nbsp;Observable이&amp;nbsp;&lt;b&gt;오류로&amp;nbsp;종료되면&amp;nbsp;BehaviorSubject는&amp;nbsp;후속&amp;nbsp;관찰자에게&amp;nbsp;항목을&amp;nbsp;내보내지&amp;nbsp;않고&amp;nbsp;단순히&amp;nbsp;소스&amp;nbsp;Observable의&amp;nbsp;오류&amp;nbsp;알림을&amp;nbsp;전달합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;PublishSubject&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZLPxF/btrLZzuVqGg/t0YkyQOuYEsZj41OQjTKb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZLPxF/btrLZzuVqGg/t0YkyQOuYEsZj41OQjTKb0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZLPxF/btrLZzuVqGg/t0YkyQOuYEsZj41OQjTKb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZLPxF%2FbtrLZzuVqGg%2Ft0YkyQOuYEsZj41OQjTKb0%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;500&quot; height=&quot;316&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;810&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: #5f6d2b;&quot;&gt;PublishSubject&amp;nbsp;emits to an observer only those items that are emitted by the source Observable(s) subsequent to the time of the subscription.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;PublishSubject는 구독 시간 이후에 소스 Observable(들)에 의해 방출된 항목만 관찰자에게 방출합니다.&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: #5f6d2b;&quot;&gt;Note that a&amp;nbsp;PublishSubject may begin emitting items immediately upon creation (unless you have taken steps to prevent this), and so there is a risk that one or more items may be lost between the time the Subject is created and the observer subscribes to it. If you need to guarantee delivery of all items from the source Observable, you&amp;rsquo;ll need either to form that Observable with Create&amp;nbsp;so that you can manually reintroduce &amp;ldquo;cold&amp;rdquo; Observable behavior (checking to see that all observers have subscribed before beginning to emit items), or switch to using a&amp;nbsp;ReplaySubject&amp;nbsp;instead.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;PublishSubject는 생성 즉시 항목을 방출하기 시작할 수 있으며(이를 방지하기 위한 조치를 취하지 않는 한) &lt;b&gt;Subject가 생성되고 관찰자가 구독하는 시간 사이에 하나 이상의 항목이 손실될 위험이 있습니다.&lt;/b&gt; 소스 Observable에서 모든 항목의 전달을 보장해야 하는 경우 &quot;콜드&quot; Observable 동작을 수동으로 다시 도입할 수 있도록 Create을 사용하여 해당 Observable을 구성해야 합니다&lt;b&gt;(항목 방출을 시작하기 전에 모든 관찰자가 구독했는지 확인) 또는 대신 ReplaySubject를 사용하도록 전환합니다.&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-origin-width=&quot;1280&quot; data-origin-height=&quot;790&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wsCEX/btrLTCTv9uy/dSKkJYM3bEXxPFWm2PuUt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wsCEX/btrLTCTv9uy/dSKkJYM3bEXxPFWm2PuUt1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wsCEX/btrLTCTv9uy/dSKkJYM3bEXxPFWm2PuUt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwsCEX%2FbtrLTCTv9uy%2FdSKkJYM3bEXxPFWm2PuUt1%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;500&quot; height=&quot;309&quot; data-origin-width=&quot;1280&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;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;If the source Observable terminates with an error, the&amp;nbsp;PublishSubject&amp;nbsp;will not emit any items to subsequent observers, but will simply pass along the error notification from the source Observable.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;소스 Observable이 오류로 종료되면 PublishSubject는 후속 관찰자에게 항목을 내보내지 않고 단순히 소스 Observable의 오류 알림을 전달합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;ReplaySubject&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WYev5/btrLOlSHMDj/Hdh6YLjMyZU5rheNkKGKKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WYev5/btrLOlSHMDj/Hdh6YLjMyZU5rheNkKGKKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WYev5/btrLOlSHMDj/Hdh6YLjMyZU5rheNkKGKKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWYev5%2FbtrLOlSHMDj%2FHdh6YLjMyZU5rheNkKGKKk%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;500&quot; height=&quot;316&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;810&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: #5f6d2b;&quot;&gt;ReplaySubject&amp;nbsp;emits to any observer all of the items that were emitted by the source Observable(s), regardless of when the observer subscribes.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;ReplaySubject는 관찰자가 구독하는 시기에 관계없이 소스 Observable에서 방출한 모든 항목을 관찰자에게 방출합니다.&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: #5f6d2b;&quot;&gt;There are also versions of&amp;nbsp;ReplaySubject&amp;nbsp;that will throw away old items once the replay buffer threatens to grow beyond a certain size, or when a specified timespan has passed since the items were originally emitted.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;재생 버퍼가 특정 크기 이상으로 커질 위험이 있거나 항목이 원래 방출된 이후 지정된 시간이 경과하면 오래된 항목을 버리는 ReplaySubject 버전도 있습니다.&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: #5f6d2b;&quot;&gt;If you use a&amp;nbsp;ReplaySubject&amp;nbsp;as an observer, take care not to call its&amp;nbsp;onNext&amp;nbsp;method (or its other&amp;nbsp;on&amp;nbsp;methods) from multiple threads, as this could lead to coincident (non-sequential) calls, which violates&amp;nbsp;&lt;a style=&quot;color: #5f6d2b;&quot; href=&quot;https://reactivex.io/documentation/contract.html&quot;&gt;the Observable contract&lt;/a&gt;&amp;nbsp;and creates an ambiguity in the resulting Subject as to which item or notification should be replayed first.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;ReplaySubject를 관찰자로 사용하는 경우 여러 스레드에서 &lt;b&gt;onNext 메서드(또는 다른 메서드)를 호출하지 않도록 주의하십시오.&lt;/b&gt; 이 경우 &lt;b&gt;동시 호출(순차적이지 않음)이 발생할 수 있으며&lt;/b&gt;, 이는 Observable 계약을 위반하고 결과 Subject에 어떤 아이템 또는 알림을 먼저 재생해야 하는지에 대한 &lt;b&gt;모호성을 발생시킬 수 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;※ 참고 출처&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;a href=&quot;https://reactivex.io/documentation/subject.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ReactiveX 공식 문서&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1662995629588&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;ReactiveX - Subject&quot; data-og-description=&quot;If you have a Subject and you want to pass it along to some other agent without exposing its Subscriber interface, you can mask it by calling its asObservable method, which will return the Subject as a pure Observable. See Also&quot; data-og-host=&quot;reactivex.io&quot; data-og-source-url=&quot;https://reactivex.io/documentation/subject.html&quot; data-og-url=&quot;https://reactivex.io/documentation/subject.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/q9HSG/hyPLj2E8Ks/qhqXkwgpkAuJfF3AnPiIZ1/img.png?width=1280&amp;amp;height=830&amp;amp;face=0_0_1280_830,https://scrap.kakaocdn.net/dn/btORlI/hyPLhRjyi0/jP1pw4LtnzkCJCnIqkZ1N1/img.png?width=1280&amp;amp;height=810&amp;amp;face=0_0_1280_810,https://scrap.kakaocdn.net/dn/b8aMmG/hyPLle6vms/mp0PeIK9XwG5nYRhtIxE2k/img.png?width=1280&amp;amp;height=810&amp;amp;face=0_0_1280_810&quot;&gt;&lt;a href=&quot;https://reactivex.io/documentation/subject.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://reactivex.io/documentation/subject.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/q9HSG/hyPLj2E8Ks/qhqXkwgpkAuJfF3AnPiIZ1/img.png?width=1280&amp;amp;height=830&amp;amp;face=0_0_1280_830,https://scrap.kakaocdn.net/dn/btORlI/hyPLhRjyi0/jP1pw4LtnzkCJCnIqkZ1N1/img.png?width=1280&amp;amp;height=810&amp;amp;face=0_0_1280_810,https://scrap.kakaocdn.net/dn/b8aMmG/hyPLle6vms/mp0PeIK9XwG5nYRhtIxE2k/img.png?width=1280&amp;amp;height=810&amp;amp;face=0_0_1280_810');&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;ReactiveX - Subject&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;If you have a Subject and you want to pass it along to some other agent without exposing its Subscriber interface, you can mask it by calling its asObservable method, which will return the Subject as a pure Observable. See Also&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;reactivex.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>RxSwift</category>
      <category>IOS</category>
      <category>rx</category>
      <category>rxswift</category>
      <category>subject</category>
      <category>Swift</category>
      <author>Minny27</author>
      <guid isPermaLink="true">https://minny27.tistory.com/117</guid>
      <comments>https://minny27.tistory.com/117#entry117comment</comments>
      <pubDate>Tue, 13 Sep 2022 00:23:40 +0900</pubDate>
    </item>
    <item>
      <title>[iOS / RxSwift] Single</title>
      <link>https://minny27.tistory.com/116</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;Single&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;RxJava (and its derivatives like RxGroovy &amp;amp; RxScala) has developed an Observable variant called &amp;ldquo;Single.&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;RxJava(및&amp;nbsp;RxGroovy&amp;nbsp;및&amp;nbsp;RxScala와&amp;nbsp;같은&amp;nbsp;파생&amp;nbsp;제품)는&amp;nbsp;&quot;&lt;b&gt;Single&lt;/b&gt;&quot;이라는&amp;nbsp;&lt;b&gt;Observable&amp;nbsp;변형&lt;/b&gt;을&amp;nbsp;개발했습니다.&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: #5f6d2b;&quot;&gt;A Single is something like an Observable, but instead of emitting a series of values &amp;mdash; anywhere from none at all to an infinite number &amp;mdash; it always either emits one value or an error notification.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Single&lt;/b&gt;은&amp;nbsp;&lt;b&gt;Observable&lt;/b&gt;과&amp;nbsp;비슷하지만&amp;nbsp;일련의&amp;nbsp;값을&amp;nbsp;내보내는&amp;nbsp;대신(전혀&amp;nbsp;없는&amp;nbsp;것부터&amp;nbsp;무한한&amp;nbsp;수까지)&amp;nbsp;&lt;b&gt;항상&amp;nbsp;하나의&amp;nbsp;값이나&amp;nbsp;오류&amp;nbsp;알림을&amp;nbsp;내보냅니다.&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: #5f6d2b;&quot;&gt;For this reason, instead of subscribing to a Single with the three methods you use to respond to notifications from an Observable (onNext, onError, and onCompleted), you only use two methods to subscribe:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이러한&amp;nbsp;이유로&amp;nbsp;&lt;b&gt;Observable&lt;/b&gt;의&amp;nbsp;알림에&amp;nbsp;응답하는&amp;nbsp;데&amp;nbsp;사용하는&amp;nbsp;세&amp;nbsp;가지&amp;nbsp;방법(&lt;b&gt;onNext&lt;/b&gt;,&amp;nbsp;&lt;b&gt;onError&lt;/b&gt;&amp;nbsp;및&amp;nbsp;&lt;b&gt;onCompleted&lt;/b&gt;)으로&amp;nbsp;&lt;b&gt;Single&lt;/b&gt;을&amp;nbsp;구독하는&amp;nbsp;대신&amp;nbsp;구독에&amp;nbsp;두&amp;nbsp;가지&amp;nbsp;방법만&amp;nbsp;사용합니다.&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: #5f6d2b;&quot;&gt;&lt;b&gt;onSuccess&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;a Single passes this method the sole item that the Single emits&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;성공&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Single은&amp;nbsp;이&amp;nbsp;메서드를&amp;nbsp;Single이&amp;nbsp;방출하는&amp;nbsp;&lt;b&gt;유일한&amp;nbsp;항목으로&amp;nbsp;전달합니다.&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: #5f6d2b;&quot;&gt;&lt;b&gt;onError&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;a Single passes this method the Throwable that caused the Single to be unable to emit an item&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;오류 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Single이 이 메서드를 전달하여 Single이 항목을 방출할 수 없게 만든 Throwable이 됩니다.&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: #5f6d2b;&quot;&gt;A Single will call only one of these methods, and will only call it once. Upon calling either method, the Single terminates and the subscription to it ends.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Single은&amp;nbsp;이러한&amp;nbsp;메서드&amp;nbsp;중&amp;nbsp;하나만&amp;nbsp;호출하고&amp;nbsp;한&amp;nbsp;번만&amp;nbsp;호출합니다.&amp;nbsp;&lt;b&gt;두&amp;nbsp;메서드&amp;nbsp;중&amp;nbsp;하나를&amp;nbsp;호출하면&amp;nbsp;Single이&amp;nbsp;종료되고&amp;nbsp;이에&amp;nbsp;대한&amp;nbsp;구독이&amp;nbsp;종료됩니다.&lt;/b&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;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;Composition via Single Operators&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Like Observables, Singles can be manipulated by means of a variety of operators. Some operators also allow for an interface between the Observable world and the Single world so that you can mix the two varieties:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Observable과&amp;nbsp;마찬가지로&amp;nbsp;Singles는&amp;nbsp;다양한&amp;nbsp;연산자를&amp;nbsp;통해&amp;nbsp;조작할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;일부&amp;nbsp;연산자는&amp;nbsp;Observable&amp;nbsp;세계와&amp;nbsp;단일&amp;nbsp;세계&amp;nbsp;사이의&amp;nbsp;인터페이스를&amp;nbsp;허용하여&amp;nbsp;두&amp;nbsp;종류를&amp;nbsp;혼합할&amp;nbsp;수도&amp;nbsp;있습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 518px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 17px;&quot;&gt;operator&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 17px;&quot;&gt;returns&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 17px;&quot;&gt;description&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 17px;&quot;&gt;compose&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 17px;&quot;&gt;Single&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 17px;&quot;&gt;사용자&amp;nbsp;지정&amp;nbsp;연산자를&amp;nbsp;만들&amp;nbsp;수&amp;nbsp;있습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 35px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 35px;&quot;&gt;concat&lt;span&gt;&amp;nbsp;&lt;/span&gt;and&lt;span&gt;&amp;nbsp;&lt;/span&gt;concatWith&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 35px;&quot;&gt;Observable&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 35px;&quot;&gt;여러&amp;nbsp;Singles에&amp;nbsp;의해&amp;nbsp;방출된&amp;nbsp;항목을&amp;nbsp;&lt;b&gt;Observable 방출로 연결&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 17px;&quot;&gt;create&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 17px;&quot;&gt;Single&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 17px;&quot;&gt;구독자 메서드를 명시적으로 호출하여 처음부터 &lt;b&gt;Single 만듦&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 17px;&quot;&gt;delay&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 17px;&quot;&gt;Single&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 17px;&quot;&gt;단일 항목의 &lt;b&gt;방출을 미룸&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 17px;&quot;&gt;doOnError&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 17px;&quot;&gt;Single&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 17px;&quot;&gt;onError를 호출할 때 지정한 메서드도 호출하는 Single을 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 17px;&quot;&gt;doOnSuccess&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 17px;&quot;&gt;Single&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 17px;&quot;&gt;onSuccess를 호출할 때 지정한 메서드도 호출하는 Single을 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 17px;&quot;&gt;error&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 17px;&quot;&gt;Single&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 17px;&quot;&gt;구독자에게 즉시 오류를 알리는 Single을 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 17px;&quot;&gt;flatMap&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 17px;&quot;&gt;Single&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 17px;&quot;&gt;Single이&amp;nbsp;내보낸&amp;nbsp;항목에&amp;nbsp;적용된&amp;nbsp;&lt;b&gt;함수의 결과인 Single을 반환&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 35px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 35px;&quot;&gt;flatMapObservable&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 35px;&quot;&gt;Observable&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 35px;&quot;&gt;Single에서&amp;nbsp;내보낸&amp;nbsp;항목에&amp;nbsp;적용된&lt;b&gt; 함수의 결과인 Observable을 반환&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 17px;&quot;&gt;from&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 17px;&quot;&gt;Single&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 17px;&quot;&gt;&lt;b&gt;Future를&amp;nbsp;Single로&amp;nbsp;변환&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 17px;&quot;&gt;just&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 17px;&quot;&gt;Single&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 17px;&quot;&gt;&lt;b&gt;지정된 항목을 내보내는 Single을 반환&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 35px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 35px;&quot;&gt;map&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 35px;&quot;&gt;Single&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 35px;&quot;&gt;소스 Single에서 내보낸 항목에 적용된 &lt;b&gt;함수의 결과를 내보내는 Single을 반환&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 35px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 35px;&quot;&gt;merge&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 35px;&quot;&gt;Single&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 35px;&quot;&gt;두 번째 Single을 방출하는 Single을 &lt;b&gt;두 번째 Single에서 방출하는 항목을 방출하는 Single로 변환&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 35px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 35px;&quot;&gt;merge&lt;span&gt;&amp;nbsp;&lt;/span&gt;and&lt;span&gt;&amp;nbsp;&lt;/span&gt;mergeWith&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 35px;&quot;&gt;Observable&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 35px;&quot;&gt;&lt;b&gt;여러 싱글에 의해 방출된 항목을 관찰 가능한 방출로 병합&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 17px;&quot;&gt;observeOn&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 17px;&quot;&gt;Single&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 17px;&quot;&gt;Single이 특정 스케줄러에서 구독자 메서드를 호출하도록 지시&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 17px;&quot;&gt;onErrorReturn&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 17px;&quot;&gt;Single&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 17px;&quot;&gt;오류 알림을 보내는 Single을 지정된 항목을 내보내는 Single로 변환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 17px;&quot;&gt;subscribeOn&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 17px;&quot;&gt;Single&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 17px;&quot;&gt;Single이 특정 스케줄러에서 작동하도록 지시&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 35px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 35px;&quot;&gt;timeout&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 35px;&quot;&gt;Single&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 35px;&quot;&gt;소스 Single이 지정된 시간 동안 값을 내보내지 않으면 오류를 알리는 Single을 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 17px;&quot;&gt;toSingle&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 17px;&quot;&gt;Single&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 17px;&quot;&gt;단일 항목을 방출하는 Observable을 해당 항목을 방출하는 Single로 변환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 35px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 35px;&quot;&gt;toObservable&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 35px;&quot;&gt;Observable&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 35px;&quot;&gt;Single을 Observable로 변환하여 Single에 의해 방출된 항목을 방출한 다음 완료&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 35px;&quot;&gt;
&lt;td style=&quot;width: 16.7442%; height: 35px;&quot;&gt;zip&lt;span&gt;&amp;nbsp;&lt;/span&gt;and&lt;span&gt;&amp;nbsp;&lt;/span&gt;zipWith&lt;/td&gt;
&lt;td style=&quot;width: 9.53489%; height: 35px;&quot;&gt;Single&lt;/td&gt;
&lt;td style=&quot;width: 73.6047%; height: 35px;&quot;&gt;두 개 이상의 다른 Single에서 방출된 항목에 적용된 함수의 결과인 항목을 방출하는 Single을 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;※ 참고 출처&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;a href=&quot;https://reactivex.io/documentation/single.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ReactiveX 공식 문서&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1662995752645&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;ReactiveX - Single&quot; data-og-description=&quot;&quot; data-og-host=&quot;reactivex.io&quot; data-og-source-url=&quot;https://reactivex.io/documentation/single.html&quot; data-og-url=&quot;https://reactivex.io/documentation/single.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://reactivex.io/documentation/single.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://reactivex.io/documentation/single.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;ReactiveX - Single&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;reactivex.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>RxSwift</category>
      <category>IOS</category>
      <category>rx</category>
      <category>rxswift</category>
      <category>Single</category>
      <category>Swift</category>
      <author>Minny27</author>
      <guid isPermaLink="true">https://minny27.tistory.com/116</guid>
      <comments>https://minny27.tistory.com/116#entry116comment</comments>
      <pubDate>Mon, 12 Sep 2022 01:44:38 +0900</pubDate>
    </item>
    <item>
      <title>[iOS / RxSwift] Operators</title>
      <link>https://minny27.tistory.com/115</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;Introduction&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Each language-specific implementation of ReactiveX implements a set of operators. Although there is much overlap between implementations, there are also some operators that are only implemented in certain implementations. Also, each implementation tends to name its operators to resemble those of similar methods that are already familiar from other contexts in that language.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;ReactiveX의&amp;nbsp;각&amp;nbsp;언어별&amp;nbsp;구현은&amp;nbsp;일련의&amp;nbsp;&lt;b&gt;연산자를&amp;nbsp;구현&lt;/b&gt;합니다.&amp;nbsp;구현&amp;nbsp;간에&amp;nbsp;겹치는&amp;nbsp;부분이&amp;nbsp;많지만&amp;nbsp;특정&amp;nbsp;구현에서만&amp;nbsp;구현되는&amp;nbsp;일부&amp;nbsp;연산자도&amp;nbsp;있습니다.&amp;nbsp;또한&amp;nbsp;각&amp;nbsp;구현은&amp;nbsp;해당&amp;nbsp;언어의&amp;nbsp;다른&amp;nbsp;컨텍스트에서&amp;nbsp;이미&amp;nbsp;친숙한&amp;nbsp;유사한&amp;nbsp;메서드의&amp;nbsp;연산자와&amp;nbsp;유사하도록&amp;nbsp;연산자&amp;nbsp;이름을&amp;nbsp;지정하는&amp;nbsp;경향이&amp;nbsp;있습니다.&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;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;Chaining Operators&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Most operators operate on an Observable and return an Observable. This allows you to apply these operators one after the other, in a chain. Each operator in the chain modifies the Observable that results from the operation of the previous operator.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;대부분의&amp;nbsp;연산자는&amp;nbsp;&lt;b&gt;Observable&lt;/b&gt;에서&amp;nbsp;작동하고&amp;nbsp;&lt;b&gt;Observable&lt;/b&gt;을&amp;nbsp;반환합니다.&amp;nbsp;&lt;b&gt;이렇게&amp;nbsp;하면&amp;nbsp;이러한&amp;nbsp;연산자를&amp;nbsp;체인에서&amp;nbsp;차례로&amp;nbsp;적용할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/b&gt;&amp;nbsp;&lt;b&gt;체인의&amp;nbsp;각&amp;nbsp;연산자는&amp;nbsp;이전&amp;nbsp;연산자의&amp;nbsp;작업&amp;nbsp;결과인&amp;nbsp;Observable을&amp;nbsp;수정합니다.&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: #5f6d2b;&quot;&gt;There are other patterns, like the Builder Pattern, in which a variety of methods of a particular class operate on an item of that same class by modifying that object through the operation of the method. These patterns also allow you to chain the methods in a similar way. But while in the Builder Pattern, the order in which the methods appear in the chain does not usually matter, with the Observable operators order matters.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;특정 클래스의 다양한 메서드가 메서드의 작업을 통해 해당 개체를 수정하여 동일한 클래스의 항목에 대해 작동하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Builder Pattern&lt;/b&gt;과 같은 다른 패턴이 있습니다. 이러한 패턴을 사용하면 유사한 방식으로 메서드를 연결할 수도 있습니다. 그러나 빌더 패턴에서 메서드가 체인에 나타나는 순서는 일반적으로 중요하지 않으며&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Observable 연산자의 순서가 중요합니다.&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: #5f6d2b;&quot;&gt;A chain of Observable operators do not operate independently on the original Observable that originates the chain, but they operate in turn, each one operating on the Observable generated by the operator immediately previous in the chain.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Observable&lt;/b&gt;&amp;nbsp;연산자&amp;nbsp;체인은&amp;nbsp;체인을&amp;nbsp;생성한&amp;nbsp;원래&amp;nbsp;&lt;b&gt;Observable&lt;/b&gt;에서&amp;nbsp;독립적으로&amp;nbsp;작동하지&amp;nbsp;않지만&amp;nbsp;차례로&amp;nbsp;작동하며&amp;nbsp;각각은&amp;nbsp;체인의&amp;nbsp;바로&amp;nbsp;이전에&amp;nbsp;연산자가&amp;nbsp;생성한&amp;nbsp;&lt;b&gt;Observable&lt;/b&gt;에서&amp;nbsp;작동합니다.&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;Operators&amp;nbsp;By&amp;nbsp;Category&lt;/b&gt;&lt;/h2&gt;
&lt;h3 id=&quot;creating&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Creating Observables(Observable 생성)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 Observable을 만드는 연산자들&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/create.html&quot;&gt;&lt;b&gt;Create&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 직접적인 코드 구현을 통해 &lt;b&gt;옵저버 메서드를 호출하여&lt;/b&gt; Observable을 생성&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/defer.html&quot;&gt;&lt;b&gt;Defer&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 옵저버가 구독하기 전까지는 Observable 생성을 지연하고 &lt;b&gt;구독이 시작되면 옵저버 별로 새로운 Observable을 생성&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/empty-never-throw.html&quot;&gt;&lt;b&gt;Empty/Never/Throw&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 아주 정확하고 제한된 행동을 하는 Observable을 생성&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/from.html&quot;&gt;&lt;b&gt;From&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;다른 객체나 자료 구조&lt;/b&gt;를 Observable로 변환&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/interval.html&quot;&gt;&lt;b&gt;Interval&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 특정 &lt;b&gt;시간별로 연속된 정수형&lt;/b&gt;을 배출하는 Observable을 생성&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/just.html&quot;&gt;&lt;b&gt;Just&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;객체 하나 또는 객체집합&lt;/b&gt;을 Observable로 변환. 변환된 Observable은 원본 객체들을 발행&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/range.html&quot;&gt;&lt;b&gt;Range&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;연속된 범위(Range)의 정수&lt;/b&gt;를 발행하는 Observable을 생성&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/repeat.html&quot;&gt;&lt;b&gt;Repeat&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 특정 항목이나 &lt;b&gt;연속된 항목들을 반복적으로 배출&lt;/b&gt;하는 Observable을 생성&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/start.html&quot;&gt;&lt;b&gt;Start&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;함수의 실행 결과를 배출&lt;/b&gt;하는 Observable을 생성&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/timer.html&quot;&gt;&lt;b&gt;Timer&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;지정된 시간이 지나고 난 후 항목을 하나 배출&lt;/b&gt;하는 Observable을 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;transforming&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Transforming Observables(Observable 변환)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Observable이 &lt;b&gt;배출한 항목들을 변환&lt;/b&gt;하는 연산자들&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/buffer.html&quot;&gt;&lt;b&gt;Buffer&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable로부터 정기적으로 항목들을 수집하고 묶음으로 만든 후에 묶음 안에 있는 항목들을 한번에 하나씩 배출하지 않고 &lt;b&gt;수집된 묶음 단위로 배출&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/flatmap.html&quot;&gt;&lt;b&gt;FlatMap&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 하나의 Observable이 발행하는 항목들을 여러개의 Observable로 변환하고, &lt;b&gt;항목들의 배출을 차례차례 줄 세워 하나의 Observable로 전달&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/groupby.html&quot;&gt;&lt;b&gt;GroupBy&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 원본 Observable이 배출하는 &lt;b&gt;항목들을 키(Key) 별로 묶은 후 Observable에 담는다.&lt;/b&gt; 이렇게 키 별로 만들어진 Observable들은 자기가 담고 있는 묶음의 항목들을 배출한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/map.html&quot;&gt;&lt;b&gt;Map&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;Observable이 배출한 항목에 함수를 적용&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/scan.html&quot;&gt;&lt;b&gt;Scan&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable이 배출한 항목에 연속적으로 함수를 적용하고 실행한 후 &lt;b&gt;성공적으로 실행된 함수의 리턴 값&lt;/b&gt;을 발행한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/window.html&quot;&gt;&lt;b&gt;Window&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 정기적으로 Observable의 항목들을 더 작은 단위의 Observable 윈도우로 나눈 후에, 한번에 하나씩 항목들을 발행하는 대신 작게 나눠진 윈도우 단위로 항목들을 배출한다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;filtering&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Filtering Observables(Observable 필터링)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소스 Observable에서 선택적으로 항목을 배출하는 연산자들&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/debounce.html&quot;&gt;&lt;b&gt;Debounce&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable의 시간 흐름이 지속되는 상태에서 다른 항목들은 배출하지 않고 &lt;b&gt;특정 시간마다 그 시점에 존재하는 항목 하나를 Observable로부터 배출&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/distinct.html&quot;&gt;&lt;b&gt;Distinct&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable이 배출하는 항목들 중 &lt;b&gt;중복을 제거한 항목들을 배출&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/elementat.html&quot;&gt;&lt;b&gt;ElementAt&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;Obserable에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;i&gt;n&lt;/i&gt;번째 항목만 배출&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/filter.html&quot;&gt;&lt;b&gt;Filter&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;테스트 조건을 만족하는 항목들만 배출&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/first.html&quot;&gt;&lt;b&gt;First&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;맨 첫 번째 항목&lt;/b&gt; 또는 &lt;b&gt;조건을 만족하는 첫 번째 항목만 배출&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/ignoreelements.html&quot;&gt;&lt;b&gt;IgnoreElements&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;항목들을 배출하지는 않고 종료 알림은 보낸다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/last.html&quot;&gt;&lt;b&gt;Last&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;Observable의 마지막 항목만 배출&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/sample.html&quot;&gt;&lt;b&gt;Sample&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;특정 시간 간격으로 최근에 Observable이 배출한 항목들을 배출&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/skip.html&quot;&gt;&lt;b&gt;Skip&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable이 &lt;b&gt;배출한 처음&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;i&gt;n&lt;/i&gt;개의 항목들을 숨긴다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/skiplast.html&quot;&gt;&lt;b&gt;SkipLast&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable이 &lt;b&gt;배출한 마지막&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;i&gt;n&lt;/i&gt;개의 항목들을 숨긴다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/take.html&quot;&gt;&lt;b&gt;Take&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable이 &lt;b&gt;배츨한 처음&lt;i&gt;n&lt;/i&gt;개의 항목들만 배출&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/takelast.html&quot;&gt;&lt;b&gt;TakeLast&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable이 &lt;b&gt;배출한 마지막 &lt;i&gt;n&lt;/i&gt;개의 항목들만 배출&lt;/b&gt;한다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;combining&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Combining Observables(Observables 결합)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 개의 소스 Observable들을 하나의 Observable로 만드는 연산자들&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/and-then-when.html&quot;&gt;&lt;b&gt;And/Then/When&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 두 개 이상의 &lt;b&gt;Observable&lt;/b&gt;들이 배출한 항목들을 'Pattern'과 'Plan' 중계자를 이용해서 결합한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/combinelatest.html&quot;&gt;&lt;b&gt;CombineLatest&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;두 개의 Observable 중 하나가 항목을 배출할 때 배출된 마지막 항목과 다른 한 Observable이 배출한 항목을 결합한 후 함수를 적용하여 실행 후 실행된 결과를 배출&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/join.html&quot;&gt;&lt;b&gt;Join&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; A Observable과 B Observable이 배출한 항목들을 결합하는데, 이때 B Observable은 배출한 항목이 타임 윈도우를 가지고 있고 이 타임 윈도우가 열린 동안 A Observable은 항목의 배출을 계속한다. Join 연산자는 B Observable의 항목을 배출하고 배출된 항목은 타임 윈도우를 시작시킨다. 타임 윈도우가 열려 있는 동안 A Observable은 자신의 항목들을 계속 배출하여 이 두 항목들을 결합한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/merge.html&quot;&gt;&lt;b&gt;Merge&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;복수 개의 Observable들이 배출하는 항목들을 머지시켜 하나의 Observable로 만든다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/startwith.html&quot;&gt;&lt;b&gt;StartWith&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 소스 Observable이 항목을 배출하기 전에 &lt;b&gt;다른 항목들을 앞에 추가한 후 배출&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/switch.html&quot;&gt;&lt;b&gt;Switch&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable들을 배출하는 Observable을 &lt;b&gt;싱글 Observable로 변환&lt;/b&gt;하다. 변환된 싱글 Observable은 변환 전 소스 Observable들이 배출한 항목들을 배출한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/zip.html&quot;&gt;&lt;b&gt;Zip&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 명시한 함수를 통해 여러 &lt;b&gt;Observable들이 배출한 항목들을 결합하고 함수의 실행 결과를 배출&lt;/b&gt;한다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;error&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;오류 처리 연산자&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Observable이 던진 오류를 복구할 수 있도록 도와주는 연산자들&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/catch.html&quot;&gt;&lt;b&gt;Catch&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 오류를 무시하고 배출되는 항목들을 계속 진행시켜 &lt;b&gt;'onError'로부터 전달된 오류를 복구&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/retry.html&quot;&gt;&lt;b&gt;Retry&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 만약 소스 &lt;b&gt;Observable이 'onError' 알림을 보낼 경우, 오류 없이 실행이 완료되기를 기대하며 재구독을 시도&lt;/b&gt;한다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;utility&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Observable 유틸리티 연산자&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Obserable과 함께 동작하는 유용한 도우미 연산자들&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/delay.html&quot;&gt;&lt;b&gt;Delay&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable의 배출을 &lt;b&gt;특정 시간동안 미룬다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/do.html&quot;&gt;&lt;b&gt;Do&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable의 생명주기 동안 발생하는 &lt;b&gt;여러 이벤트에서 실행될 액션을 등록&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/materialize-dematerialize.html&quot;&gt;&lt;b&gt;Materialize/Dematerialize&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;배출된 항목이 어떤 알림을 통해 옵저버에게 전달 됐는지를 표현&lt;/b&gt;하며, 그 반대 과정을 수행할 수 있다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/observeon.html&quot;&gt;&lt;b&gt;ObserveOn&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 옵저버가 &lt;b&gt;어느 스케줄러 상에서 Observable을 관찰할지 명시&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/serialize.html&quot;&gt;&lt;b&gt;Serialize&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;Observable이 직렬화된 호출을 생성하고 제대로 동작하도록 강제&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/subscribe.html&quot;&gt;&lt;b&gt;Subscribe&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;Observable이 배출하는 항목과 알림을 기반으로 동작&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/subscribeon.html&quot;&gt;&lt;b&gt;SubscribeOn&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;Observable을 구독할 때 사용할 스케줄러를 명시&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/timeinterval.html&quot;&gt;&lt;b&gt;TimeInterval&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 항목들을 배출하는 &lt;b&gt;Observable&lt;/b&gt;을, &lt;b&gt;항목을 배출하는데 걸린 시간이 얼마인지를 가리키는 Observable로 변환&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/timeout.html&quot;&gt;&lt;b&gt;Timeout&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 소스 Obvservable을 그대로 전달하지만, 대신 &lt;b&gt;특정 시간 동안 배출된 항목이 없으면 오류 알림을 보낸다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/timestamp.html&quot;&gt;&lt;b&gt;Timestamp&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable이 &lt;b&gt;배출한 항목에 타임 스탬프를 추가&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/using.html&quot;&gt;&lt;b&gt;Using&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 소스 Observable과 동일한 생명주기를 갖는 Observable을 생성하는데, 이 &lt;b&gt;Observable은 생명주기가 완료되면 리소스를 종료하고 반환&lt;/b&gt;한다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;conditional&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;조건과 불린 연산자(Boolean)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나 이상의 Observable 또는 Observable이 배출한 항목을 평가하는 연산자들&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/all.html&quot;&gt;&lt;b&gt;All&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable이 배출한 &lt;b&gt;전체 항목들이 어떤 조건을 만족시키는지 판단&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/amb.html&quot;&gt;&lt;b&gt;Amb&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 두 개 이상의 소스 Observable이 주어 질때, 그 중 &lt;b&gt;첫 번째로 항목을 배출한 Observable이 배출하는 항목들을 전달&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/contains.html&quot;&gt;&lt;b&gt;Contains&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable이 &lt;b&gt;특정 항목을 배출하는지 아닌지를 판단&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/defaultifempty.html&quot;&gt;&lt;b&gt;DefaultIfEmpty&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 소스 &lt;b&gt;Observable이 배출하는 항목을 전달한다. 만약 배출되는 항목이 없으면 기본 항목을 배출&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/sequenceequal.html&quot;&gt;&lt;b&gt;SequenceEqual&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;두 개의 Observable이 항목을 같은 순서로 배출하는지 판단&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/skipuntil.html&quot;&gt;&lt;b&gt;SkipUntil&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;두 번째 Observable이 항목을 배출하기 전까지 배출된 항목들을 버린다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/skipwhile.html&quot;&gt;&lt;b&gt;SkipWhile&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 특정 조건이 &lt;b&gt;false를 리턴하기 전까지 Observable이 배출한 항목들을 버린다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/takeuntil.html&quot;&gt;&lt;b&gt;TakeUntil&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 두 번째 Observable이 항목을 발행하기 시작했거나 &lt;b&gt;두 번째 Observable이 종료되면 그 때부터 발행되는 항목들은 버린다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/takewhile.html&quot;&gt;&lt;b&gt;TakeWhile&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 특정 조건이 &lt;b&gt;false를 리턴하기 시작하면 그 이후에 배출되는 항목들을 버린다&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;mathematical&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;수학과 집계 연산자&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Observable이 배출하는 항목 전체를 대상으로 동작하는 연산자들&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/average.html&quot;&gt;&lt;b&gt;Average&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable이 발행한 항목의 &lt;b&gt;평균 값&lt;/b&gt;을 발행한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/concat.html&quot;&gt;&lt;b&gt;Concat&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 두 개 이상의 Observable들이 항목을 발행할 때 Observable 순서대로 배출하는 &lt;b&gt;항목들을 하나의 Observable 배출로 연이어 배출&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/count.html&quot;&gt;&lt;b&gt;Count&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 소스 Observable이 발행한 &lt;b&gt;항목의 개수&lt;/b&gt;를 배출한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/max.html&quot;&gt;&lt;b&gt;Max&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable이 발행한 &lt;b&gt;항목 중 값이 가장 큰 항목을 배출&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/min.html&quot;&gt;&lt;b&gt;Min&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable이 발행한 &lt;b&gt;항목 중 값이 가장 작은 항목을 배출&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/reduce.html&quot;&gt;&lt;b&gt;Reduce&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable이 배출한 항목에 함수를 &lt;b&gt;순서대로 적용하고 함수를 연산한 후 최종 결과를 발행&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/sum.html&quot;&gt;&lt;b&gt;Sum&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; Observable이 배출한 항목의 &lt;b&gt;합계를 배출&lt;/b&gt;한다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;backpressure&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;역압(Backpressure) 연산자&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/backpressure.html&quot;&gt;&lt;b&gt;backpressure operators&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 옵저버가 소비하는 것보다 더 빠르게 항목들을 생산하는 &lt;b&gt;Observable을 복제하는 전략&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;connectable&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;연결 가능한 Observable 연산자&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀 더 정확히 제어되는 구독 역학을 가진 전문 Observable들&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/connect.html&quot;&gt;&lt;b&gt;Connect&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;구독자가 항목 배출을 시작할 수 있도록 연결 가능한 Observable에게 명령을 내린다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/publish.html&quot;&gt;&lt;b&gt;Publish&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;일반 Observable을 연결 가능한 Observable로 변환&lt;/b&gt;한다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/refcount.html&quot;&gt;&lt;b&gt;RefCount&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 일반 &lt;b&gt;Observable처럼 동작하는 연결 가능한 Observable을 만든다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/replay.html&quot;&gt;&lt;b&gt;Replay&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 비록 옵저버가 Observable이 항목 배출을 시작한 후에 &lt;b&gt;구독을 했다 하더라도 배출된 모든 항목들을 볼 수 있도록 한다&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;conversion&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Observable 변환 연산자&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators/to.html&quot;&gt;&lt;b&gt;To&lt;/b&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;b&gt;Observable을 다른 객체나 자료 구조로 변환&lt;/b&gt;한다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;새로운&amp;nbsp;Observable을&amp;nbsp;생성하는&amp;nbsp;연산자.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;※ 참고 출처&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ReactiveX 공식 문서&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1662128645083&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;ReactiveX - Operators&quot; data-og-description=&quot;Introduction Each language-specific implementation of ReactiveX implements a set of operators. Although there is much overlap between implementations, there are also some operators that are only implemented in certain implementations. Also, each implementa&quot; data-og-host=&quot;reactivex.io&quot; data-og-source-url=&quot;https://reactivex.io/documentation/operators.html&quot; data-og-url=&quot;https://reactivex.io/documentation/operators.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://reactivex.io/documentation/operators.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://reactivex.io/documentation/operators.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;ReactiveX - Operators&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Introduction Each language-specific implementation of ReactiveX implements a set of operators. Although there is much overlap between implementations, there are also some operators that are only implemented in certain implementations. Also, each implementa&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;reactivex.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>RxSwift</category>
      <category>IOS</category>
      <category>Operators</category>
      <category>rx</category>
      <category>rxswift</category>
      <category>Swift</category>
      <author>Minny27</author>
      <guid isPermaLink="true">https://minny27.tistory.com/115</guid>
      <comments>https://minny27.tistory.com/115#entry115comment</comments>
      <pubDate>Fri, 2 Sep 2022 23:24:15 +0900</pubDate>
    </item>
    <item>
      <title>[iOS / RxSwift] Observable</title>
      <link>https://minny27.tistory.com/114</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;Observable&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;In ReactiveX an observer subscribes to an Observable. Then that observer reacts to whatever item or sequence of items the Observable emits. This pattern facilitates concurrent operations because it does not need to block while waiting for the Observable to emit objects, but instead it creates a sentry in the form of an observer that stands ready to react appropriately at whatever future time the Observable does so.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;ReactiveX에서 &lt;b&gt;observer는 Observable을 구독합니다.&lt;/b&gt; 그런 다음 해당 &lt;b&gt;observer는 Observable이 방출하는 아이템 또는 아이템 시퀀스에 반응합니다.&lt;/b&gt; 이 패턴은 Observable이 객체를 방출하기를 &lt;b&gt;기다리는 동안 블락할 필요가 없기 때문에&lt;/b&gt; &lt;b&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: #5f6d2b;&quot;&gt;This page explains what the reactive pattern is and what Observables and observers are (and how observers subscribe to Observables). Other pages show how you use the variety of Observable operators to link Observables together and change their behaviors.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 페이지는 반응 패턴이 무엇인지, Observable과 Observer가 무엇인지(그리고 Observer가 Observable을 구독하는 방법)을 설명합니다. 다른 페이지에서는 다양한 Observable operator를 사용하여 Observable을 함께 연결하고 동작을 변경하는 방법을 보여줍니다.&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: #5f6d2b;&quot;&gt;This documentation accompanies its explanations with &amp;ldquo;marble diagrams.&amp;rdquo; Here is how marble diagrams represent Observables and transformations of Observables:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 문서에는 &quot;마블 다이어그램&quot;과 함께 설명이 함께 제공됩니다. 다음은 마블 다이어그램이 Observable과 Observable의 변환을 나타내는 방법입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1210&quot; data-origin-height=&quot;570&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bp28yY/btrKYFRylq8/M8pKIoeQNzkv1TfrwUiesk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bp28yY/btrKYFRylq8/M8pKIoeQNzkv1TfrwUiesk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bp28yY/btrKYFRylq8/M8pKIoeQNzkv1TfrwUiesk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbp28yY%2FbtrKYFRylq8%2FM8pKIoeQNzkv1TfrwUiesk%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;500&quot; height=&quot;236&quot; data-origin-width=&quot;1210&quot; data-origin-height=&quot;570&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;Background&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;In many software programming tasks, you more or less expect that the instructions you write will execute and complete incrementally, one-at-a-time, in order as you have written them. But in ReactiveX, many instructions may execute in parallel and their results are later captured, in arbitrary order, by &amp;ldquo;observers.&amp;rdquo; Rather than calling a method, you define a mechanism for retrieving and transforming the data, in the form of an &amp;ldquo;Observable,&amp;rdquo; and then subscribe an observer to it, at which point the previously-defined mechanism fires into action with the observer standing sentry to capture and respond to its emissions whenever they are ready.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;많은 소프트웨어 프로그래밍 작업에서 작성하는 명령이 작성한 순서대로 한 번에 하나씩 점진적으로 실행되고 완료될 것으로 예상합니다. 그러나 ReactiveX에서는 많은 명령어가 &lt;b&gt;병렬(Parallel)로 실행&lt;/b&gt;될 수 있으며 그 결과는 나중에 &quot;observers&quot;에 의해 임의의 순서로 캡처됩니다. 메소드를 호출하는 대신 &quot;Observable&quot;의 형태로 데이터를 검색하고 변환하는 메커니즘을 정의한 다음 observer을 구독합니다. 이 지점에서 이전에 정의된 메커니즘은 observer가 서 있는 보초와 함께 동작하여 준비가 될 때마다 emission을 포착하고 대응합니다.&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: #5f6d2b;&quot;&gt;An advantage of this approach is that when you have a bunch of tasks that are not dependent on each other, you can start them all at the same time rather than waiting for each one to finish before starting the next one &amp;mdash; that way, your entire bundle of tasks only takes as long to complete as the longest task in the bundle.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;이&amp;nbsp;접근&amp;nbsp;방식의&amp;nbsp;장점은&lt;/b&gt;&amp;nbsp;서로&amp;nbsp;의존하지&amp;nbsp;않는&amp;nbsp;여러&amp;nbsp;작업이&amp;nbsp;있을&amp;nbsp;때&amp;nbsp;다음&amp;nbsp;작업을&amp;nbsp;시작하기&amp;nbsp;전에&amp;nbsp;각&amp;nbsp;작업이&amp;nbsp;완료되기를&amp;nbsp;기다리는&amp;nbsp;대신&amp;nbsp;&lt;b&gt;동시에&amp;nbsp;모든&amp;nbsp;작업을&amp;nbsp;시작할&amp;nbsp;수&amp;nbsp;있다는&amp;nbsp;것&lt;/b&gt;입니다.&amp;nbsp;&lt;b&gt;작업&amp;nbsp;번들은&amp;nbsp;번들에서&amp;nbsp;가장&amp;nbsp;긴&amp;nbsp;작업만큼&amp;nbsp;완료하는&amp;nbsp;데&amp;nbsp;시간이&amp;nbsp;걸립니다.&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: #5f6d2b;&quot;&gt;There are many terms used to describe this model of asynchronous programming and design. This document will use the following terms: An observer subscribes to an Observable. An Observable emits items or sends notifications to its observers by calling the observers&amp;rsquo; methods.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 비동기 프로그래밍 및 설계 모델을 설명하는 데 사용되는 용어가 많이 있습니다. 이 문서에서는 다음과 같은 용어를 사용합니다. &lt;b&gt;observer는 Observable을 구독합니다.&lt;/b&gt; &lt;b&gt;Observable은 항목을 내보내거나 observer의 메서드를 호출하여 observer에게 알림을 보냅니다.&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: #5f6d2b;&quot;&gt;In other documents and other contexts, what we are calling an &amp;ldquo;observer&amp;rdquo; is sometimes called a &amp;ldquo;subscriber,&amp;rdquo; &amp;ldquo;watcher,&amp;rdquo; or &amp;ldquo;reactor.&amp;rdquo; This model in general is often referred to as the &amp;ldquo;reactor pattern&amp;rdquo;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;다른 문서 및 기타 맥락에서 우리가 &quot;&lt;b&gt;observer&lt;/b&gt;&quot;라고 부르는 것을 &quot;구독자&quot;, &quot;감시자&quot; 또는 &quot;반응기&quot;라고 하는 경우가 있습니다. 일반적으로 이 모델을 &quot;&lt;b&gt;reactor pattern&lt;/b&gt;&quot;이라고 합니다.&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;color: #5f6d2b;&quot;&gt;&lt;b&gt;Establishing Observers&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;This page uses Groovy like pseudocode for its examples, but there are ReactiveX implementations in many languages.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이&amp;nbsp;페이지는&amp;nbsp;예제를&amp;nbsp;위해&amp;nbsp;Groovy와&amp;nbsp;유사한&amp;nbsp;의사&amp;nbsp;코드를&amp;nbsp;사용하지만&amp;nbsp;많은&amp;nbsp;언어로&amp;nbsp;ReactiveX&amp;nbsp;구현이&amp;nbsp;있습니다.&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: #5f6d2b;&quot;&gt;In an ordinary method call &amp;mdash; that is, not the sort of asynchronous, parallel calls typical in ReactiveX &amp;mdash; the flow is something like this:&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Call a method.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Store the return value from that method in a variable.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Use that variable and its new value to do something useful.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;ReactiveX에서&amp;nbsp;일반적으로&amp;nbsp;사용되는&amp;nbsp;일종의&amp;nbsp;비동기식&amp;nbsp;병렬&amp;nbsp;호출이&amp;nbsp;아닌&amp;nbsp;일반&amp;nbsp;메서드&amp;nbsp;호출에서&amp;nbsp;흐름은&amp;nbsp;다음과&amp;nbsp;같습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;메서드를 호출&lt;/li&gt;
&lt;li&gt;해당 메서드의 반환 값을 변수에 저장&lt;/li&gt;
&lt;li&gt;해당 변수와 새 값을 사용하여 유용한 작업을 수행&lt;/li&gt;
&lt;/ol&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: #5f6d2b;&quot;&gt;Or,&amp;nbsp;something&amp;nbsp;like&amp;nbsp;this:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;또는&amp;nbsp;다음과&amp;nbsp;같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1661869748373&quot; class=&quot;sql&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// make the call, assign its return value to `returnVal`
returnVal = someMethod(itsParameters);
// do something useful with returnVal&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;In the asynchronous model the flow goes more like this:&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Define a method that does something useful with the return value from the asynchronous call; this method is part of the observer.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Define the asynchronous call itself as an Observable.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Attach the observer to that Observable by subscribing it (this also initiates the actions of the Observable).&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Go&amp;nbsp;on&amp;nbsp;with&amp;nbsp;your&amp;nbsp;business;&amp;nbsp;whenever&amp;nbsp;the&amp;nbsp;call&amp;nbsp;returns,&amp;nbsp;the&amp;nbsp;observer&amp;rsquo;s&amp;nbsp;method&amp;nbsp;will&amp;nbsp;begin&amp;nbsp;to&amp;nbsp;operate&amp;nbsp;on&amp;nbsp;its&amp;nbsp;return&amp;nbsp;value&amp;nbsp;or&amp;nbsp;values&amp;nbsp;&amp;mdash;&amp;nbsp;the&amp;nbsp;items&amp;nbsp;emitted&amp;nbsp;by&amp;nbsp;the&amp;nbsp;Observable.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Which looks something like this:&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;비동기식&amp;nbsp;모델에서&amp;nbsp;흐름은&amp;nbsp;다음과&amp;nbsp;같이&amp;nbsp;진행됩니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;비동기 호출의 반환 값으로 유용한 작업을 수행하는 메서드를 정의합니다. 이 방법은 관찰자의 일부입니다.&lt;/li&gt;
&lt;li&gt;비동기 호출 자체를 Observable로 정의합니다.&lt;/li&gt;
&lt;li&gt;Observable을 구독하여 관찰자를 해당 Observable에 연결합니다(이는 Observable의 작업도 시작함).&lt;/li&gt;
&lt;li&gt;작업을 계속하십시오. 호출이 반환될 때마다 관찰자의 메서드는 반환 값(Observable에서 내보낸 항목)에 대해 작동하기 시작합니다.&lt;br /&gt;다음과&amp;nbsp;같이&amp;nbsp;보입니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1661870121995&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// defines, but does not invoke, the Subscriber's onNext handler
// (in this example, the observer is very simple and has only an onNext handler)
def myOnNext = { it -&amp;gt; do something useful with it };
// defines, but does not invoke, the Observable
def myObservable = someObservable(itsParameters);
// subscribes the Subscriber to the Observable, and invokes the Observable
myObservable.subscribe(myOnNext);
// go on about my business&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;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;onNext,&amp;nbsp;onCompleted,&amp;nbsp;and&amp;nbsp;onError&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;The Subscribe method is how you connect an observer to an Observable. Your observer implements some subset of the following methods:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;구독&amp;nbsp;방법은&amp;nbsp;관찰자를&amp;nbsp;관찰자에&amp;nbsp;연결하는&amp;nbsp;방법입니다.&amp;nbsp;관찰자는&amp;nbsp;다음&amp;nbsp;메서드의&amp;nbsp;일부&amp;nbsp;하위&amp;nbsp;집합을&amp;nbsp;구현합니다.&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: #5f6d2b;&quot;&gt;onNext&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;An Observable calls this method whenever the Observable emits an item. This method takes as a parameter the item emitted by the Observable.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Observable은 Observable이 항목을 방출할 때마다 이 메서드를 호출합니다.&lt;/b&gt; 이 메소드는 Observable이 내보낸 항목을 매개변수로 사용합니다.&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: #5f6d2b;&quot;&gt;onError&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;An Observable calls this method to indicate that it has failed to generate the expected data or has encountered some other error. It will not make further calls to onNext or onCompleted. The onError method takes as its parameter an indication of what caused the error.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Observable은&amp;nbsp;이&amp;nbsp;메서드를&amp;nbsp;호출하여&amp;nbsp;예상&amp;nbsp;데이터&amp;nbsp;생성에&amp;nbsp;실패했거나&amp;nbsp;다른&amp;nbsp;오류가&amp;nbsp;발생했음을&amp;nbsp;나타냅니다.&amp;nbsp;&lt;b&gt;onNext&amp;nbsp;또는&amp;nbsp;onCompleted를&amp;nbsp;더&amp;nbsp;이상&amp;nbsp;호출하지&amp;nbsp;않습니다.&lt;/b&gt;&amp;nbsp;onError&amp;nbsp;메서드는&amp;nbsp;매개변수로&amp;nbsp;&lt;b&gt;오류를&amp;nbsp;일으킨&amp;nbsp;원인&lt;/b&gt;을&amp;nbsp;나타냅니다.&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: #5f6d2b;&quot;&gt;onCompleted&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;An Observable calls this method after it has called onNext for the final time, if it has not encountered any errors.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Observable은&amp;nbsp;오류가&amp;nbsp;발생하지&amp;nbsp;않은&amp;nbsp;경우&amp;nbsp;마지막으로&amp;nbsp;onNext를&amp;nbsp;호출한&amp;nbsp;후&amp;nbsp;이&amp;nbsp;메서드를&amp;nbsp;호출합니다.&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: #5f6d2b;&quot;&gt;By the terms of the Observable contract, it may call onNext zero or more times, and then may follow those calls with a call to either onCompleted or onError but not both, which will be its last call. By convention, in this document, calls to onNext are usually called &amp;ldquo;emissions&amp;rdquo; of items, whereas calls to onCompleted or onError are called &amp;ldquo;notifications.&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Observable 조건에 따라 onNext를 0번 이상 호출한 다음 해당 호출에 따라 onCompleted 또는 onError 중 하나를 호출할 수 있지만 둘 다 호출할 수는 없습니다. 이 호출은 마지막 호출이 됩니다. 관례에 따라 이 문서에서 &lt;b&gt;onNext에 대한 호출은 일반적으로 항목의 &quot;방출&quot;&lt;/b&gt;이라고 하는 반면 &lt;b&gt;onCompleted 또는 onError에 대한 호출은 &quot;알림&quot;&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: #5f6d2b;&quot;&gt;A more complete subscribe call example looks like this:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;보다&amp;nbsp;완전한&amp;nbsp;구독&amp;nbsp;호출&amp;nbsp;예는&amp;nbsp;다음과&amp;nbsp;같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1661870595905&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def myOnNext     = { item -&amp;gt; /* do something useful with item */ };
def myError      = { throwable -&amp;gt; /* react sensibly to a failed call */ };
def myComplete   = { /* clean up after the final response */ };
def myObservable = someMethod(itsParameters);
myObservable.subscribe(myOnNext, myError, myComplete);
// go on about my business&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;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;Unsubscribing&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;In some ReactiveX implementations, there is a specialized observer interface, Subscriber, that implements an unsubscribe method. You can call this method to indicate that the Subscriber is no longer interested in any of the Observables it is currently subscribed to. Those Observables can then (if they have no other interested observers) choose to stop generating new items to emit.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;일부 ReactiveX 구현에는 구독 취소 메서드를 구현하는 특수 observer 인터페이스인 &lt;b&gt;Subscriber&lt;/b&gt;가 있습니다. &lt;b&gt;구독자가 현재 구독 중인 Observable에 더 이상 관심이 없음을 나타내기 위해 이 메서드를 호출할 수 있습니다.&lt;/b&gt; 그런 다음 해당 Observable은 (관심 있는 다른 observer가 없는 경우) 방출할 새 아이템 생성을 중지하도록 선택할 수 있습니다.&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: #5f6d2b;&quot;&gt;The results of this unsubscription will cascade back through the chain of operators that applies to the Observable that the observer subscribed to, and this will cause each link in the chain to stop emitting items. This is not guaranteed to happen immediately, however, and it is possible for an Observable to generate and attempt to emit items for a while even after no observers remain to observe these emissions.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;이 구독 취소의 결과는 관찰자가 구독한 Observable에 적용되는 연산자 체인을 통해 다시 캐스케이드백되며 이로 인해 체인의 각 링크에서 항목 방출이 중지됩니다.&lt;/b&gt; 그러나 이것은 즉시 발생한다고 보장되지 않으며 이러한 방출을 관찰할 observer가 남아 있지 않은 후에도 잠시 동안 Observable이 항목을 생성하고 방출을 시도할 수 있습니다.&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;color: #5f6d2b;&quot;&gt;&lt;b&gt;Some Notes on Naming Conventions(네이밍 규칙 참고 사항)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Each language-specific implementation of ReactiveX has its own naming quirks. There is no canonical naming standard, though there are many commonalities between implementations.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;ReactiveX의&amp;nbsp;각&amp;nbsp;언어별&amp;nbsp;구현에는&amp;nbsp;고유한&amp;nbsp;이름&amp;nbsp;지정&amp;nbsp;문제가&amp;nbsp;있습니다.&amp;nbsp;구현&amp;nbsp;간에&amp;nbsp;많은&amp;nbsp;공통점이&amp;nbsp;있지만&amp;nbsp;정식&amp;nbsp;명명&amp;nbsp;표준은&amp;nbsp;없습니다.&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: #5f6d2b;&quot;&gt;Furthermore, some of these names have different implications in other contexts, or seem awkward in the idiom of a particular implementing language.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;또한&amp;nbsp;이러한&amp;nbsp;이름&amp;nbsp;중&amp;nbsp;일부는&amp;nbsp;다른&amp;nbsp;컨텍스트에서&amp;nbsp;다른&amp;nbsp;의미를&amp;nbsp;갖거나&amp;nbsp;특정&amp;nbsp;구현&amp;nbsp;언어의&amp;nbsp;관용구에서&amp;nbsp;어색해&amp;nbsp;보입니다.&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: #5f6d2b;&quot;&gt;For example there is the onEvent naming pattern (e.g. onNext, onCompleted, onError). In some contexts such names would indicate methods by means of which event handlers are registered. In ReactiveX, however, they name the event handlers themselves.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;예를&amp;nbsp;들어&amp;nbsp;onEvent&amp;nbsp;이름&amp;nbsp;지정&amp;nbsp;패턴이&amp;nbsp;있습니다(예:&amp;nbsp;onNext,&amp;nbsp;onCompleted,&amp;nbsp;onError).&amp;nbsp;일부&amp;nbsp;컨텍스트에서&amp;nbsp;이러한&amp;nbsp;이름은&amp;nbsp;이벤트&amp;nbsp;핸들러가&amp;nbsp;&lt;b&gt;등록되는&amp;nbsp;방법을&amp;nbsp;나타내는&amp;nbsp;메서드&lt;/b&gt;를&amp;nbsp;나타냅니다.&amp;nbsp;그러나&amp;nbsp;ReactiveX에서는&amp;nbsp;이벤트&amp;nbsp;핸들러&amp;nbsp;자체의&amp;nbsp;이름을&amp;nbsp;지정합니다.&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;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;&amp;ldquo;Hot&amp;rdquo;&amp;nbsp;and&amp;nbsp;&amp;ldquo;Cold&amp;rdquo;&amp;nbsp;Observables&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;When does an Observable begin emitting its sequence of items? It depends on the Observable. A &amp;ldquo;hot&amp;rdquo; Observable may begin emitting items as soon as it is created, and so any observer who later subscribes to that Observable may start observing the sequence somewhere in the middle. A &amp;ldquo;cold&amp;rdquo; Observable, on the other hand, waits until an observer subscribes to it before it begins to emit items, and so such an observer is guaranteed to see the whole sequence from the beginning.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Observable&lt;/b&gt;은&amp;nbsp;언제&amp;nbsp;항목&amp;nbsp;시퀀스를&amp;nbsp;방출하기&amp;nbsp;시작합니까?&amp;nbsp;&lt;b&gt;Observable&lt;/b&gt;에&amp;nbsp;따라&amp;nbsp;다릅니다.&amp;nbsp;&lt;b&gt;&quot;hot&quot; Observable은&amp;nbsp;생성되자마자&amp;nbsp;항목을&amp;nbsp;방출하기&amp;nbsp;시작&lt;/b&gt;할&amp;nbsp;수&amp;nbsp;있으므로&amp;nbsp;나중에&amp;nbsp;해당&amp;nbsp;&lt;b&gt;Observable&lt;/b&gt;을&amp;nbsp;구독하는&amp;nbsp;모든&amp;nbsp;관찰자는&amp;nbsp;중간&amp;nbsp;어딘가에서&amp;nbsp;시퀀스를&amp;nbsp;관찰하기&amp;nbsp;시작할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;반면에&amp;nbsp;&lt;b&gt;&quot;cold&quot; Observable은&amp;nbsp;항목을&amp;nbsp;방출하기&amp;nbsp;시작하기&amp;nbsp;전에&amp;nbsp;관찰자가&amp;nbsp;구독할&amp;nbsp;때까지&amp;nbsp;기다리므로&lt;/b&gt;&amp;nbsp;그러한&amp;nbsp;관찰자는&amp;nbsp;처음부터&amp;nbsp;전체&amp;nbsp;시퀀스를&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있습니다.&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: #5f6d2b;&quot;&gt;In some implementations of ReactiveX, there is also something called a &amp;ldquo;Connectable&amp;rdquo; Observable. Such an Observable does not begin emitting items until its Connect method is called, whether or not any observers have subscribed to it.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;ReactiveX의 일부 구현에는 &quot;&lt;b&gt;Connectable&lt;/b&gt;&quot; &lt;b&gt;Observable&lt;/b&gt;이라는&amp;nbsp;것도&amp;nbsp;있습니다.&amp;nbsp;그러한&amp;nbsp;&lt;b&gt;Observable&lt;/b&gt;은 observer가 구독했는지 여부에 관계없이 &lt;b&gt;Connect 메서드가 호출될 때까지 항목을 방출하기 시작하지 않습니다.&lt;/b&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;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;Composition via Observable Operators(관찰 가능한 연산자를 통한 구성)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Observables and observers are only the start of ReactiveX. By themselves they&amp;rsquo;d be nothing more than a slight extension of the standard observer pattern, better suited to handling a sequence of events rather than a single callback.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Observable과&amp;nbsp;Observer는&amp;nbsp;ReactiveX의&amp;nbsp;시작일&amp;nbsp;뿐입니다.&amp;nbsp;그&amp;nbsp;자체로는&amp;nbsp;표준&amp;nbsp;관찰자&amp;nbsp;패턴의&amp;nbsp;약간의&amp;nbsp;확장일&amp;nbsp;뿐이며&amp;nbsp;&lt;b&gt;단일&amp;nbsp;콜백보다&amp;nbsp;일련의&amp;nbsp;이벤트를&amp;nbsp;처리하는&amp;nbsp;데&amp;nbsp;더&amp;nbsp;적합합니다.&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: #5f6d2b;&quot;&gt;The real power comes with the &amp;ldquo;reactive extensions&amp;rdquo; (hence &amp;ldquo;ReactiveX&amp;rdquo;) &amp;mdash; operators that allow you to transform, combine, manipulate, and work with the sequences of items emitted by Observables.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;진정한&amp;nbsp;힘은&amp;nbsp;&lt;b&gt;Observable&lt;/b&gt;에서 내보낸 아이템 시퀀스를 변환, 결합, 조작 및 작업할 수 있는 &quot;reactive extensions&quot;(따라서 &quot;ReactiveX&quot;)과 함께 제공됩니다.&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: #5f6d2b;&quot;&gt;These Rx operators allow you to compose asynchronous sequences together in a declarative manner with all the efficiency benefits of callbacks but without the drawbacks of nesting callback handlers that are typically associated with asynchronous systems.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이러한&amp;nbsp;Rx&amp;nbsp;연산자를&amp;nbsp;사용하면&amp;nbsp;콜백의&amp;nbsp;모든&amp;nbsp;효율성&amp;nbsp;이점과&amp;nbsp;함께&amp;nbsp;&lt;b&gt;선언적&amp;nbsp;방식&lt;/b&gt;으로&amp;nbsp;&lt;b&gt;비동기&amp;nbsp;시퀀스&lt;/b&gt;를&amp;nbsp;함께&amp;nbsp;구성할&amp;nbsp;수&amp;nbsp;있지만&amp;nbsp;일반적으로&amp;nbsp;비동기&amp;nbsp;시스템과&amp;nbsp;관련된&amp;nbsp;중첩&amp;nbsp;콜백&amp;nbsp;핸들러의&amp;nbsp;단점이&amp;nbsp;없습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;※ 참고 출처&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;a href=&quot;https://reactivex.io/documentation/observable.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ReactiveX 공식 문서&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1661964133080&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;ReactiveX - Observable&quot; data-og-description=&quot;Observable In ReactiveX an observer subscribes to an Observable. Then that observer reacts to whatever item or sequence of items the Observable emits. This pattern facilitates concurrent operations because it does not need to block while waiting for the Ob&quot; data-og-host=&quot;reactivex.io&quot; data-og-source-url=&quot;https://reactivex.io/documentation/observable.html&quot; data-og-url=&quot;https://reactivex.io/documentation/observable.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/czZdI1/hyPDgzbe7W/vznw0GkhFxFdkuKv7lLkKk/img.png?width=1210&amp;amp;height=570&amp;amp;face=0_0_1210_570&quot;&gt;&lt;a href=&quot;https://reactivex.io/documentation/observable.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://reactivex.io/documentation/observable.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/czZdI1/hyPDgzbe7W/vznw0GkhFxFdkuKv7lLkKk/img.png?width=1210&amp;amp;height=570&amp;amp;face=0_0_1210_570');&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;ReactiveX - Observable&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Observable In ReactiveX an observer subscribes to an Observable. Then that observer reacts to whatever item or sequence of items the Observable emits. This pattern facilitates concurrent operations because it does not need to block while waiting for the Ob&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;reactivex.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>RxSwift</category>
      <category>IOS</category>
      <category>Observable</category>
      <category>rx</category>
      <category>rxswift</category>
      <category>Swift</category>
      <author>Minny27</author>
      <guid isPermaLink="true">https://minny27.tistory.com/114</guid>
      <comments>https://minny27.tistory.com/114#entry114comment</comments>
      <pubDate>Thu, 1 Sep 2022 01:53:10 +0900</pubDate>
    </item>
    <item>
      <title>[iOS / Swift] Memory Safety</title>
      <link>https://minny27.tistory.com/113</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;Memory Safety(메모리&amp;nbsp;안전)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;By default, Swift prevents unsafe behavior from happening in your code. For example, Swift ensures that variables are initialized before they&amp;rsquo;re used, memory isn&amp;rsquo;t accessed after it&amp;rsquo;s been deallocated, and array indices are checked for out-of-bounds errors.&lt;/span&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;기본적으로&amp;nbsp;Swift는&amp;nbsp;코드에서&amp;nbsp;안전하지&amp;nbsp;않은&amp;nbsp;동작이&amp;nbsp;발생하는&amp;nbsp;것을&amp;nbsp;방지합니다.&amp;nbsp;예를&amp;nbsp;들어,&amp;nbsp;Swift는&amp;nbsp;&lt;b&gt;변수가&amp;nbsp;사용되기&amp;nbsp;전에&amp;nbsp;초기화되고&lt;/b&gt;,&amp;nbsp;&lt;b&gt;할당이&amp;nbsp;해제된&amp;nbsp;후&amp;nbsp;메모리에&amp;nbsp;액세스되지&amp;nbsp;않으며&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: #5f6d2b;&quot;&gt;Swift also makes sure that multiple accesses to the same area of memory don&amp;rsquo;t conflict, by requiring code that modifies a location in memory to have exclusive access to that memory. Because Swift manages memory automatically, most of the time you don&amp;rsquo;t have to think about accessing memory at all. However, it&amp;rsquo;s important to understand where potential conflicts can occur, so you can avoid writing code that has conflicting access to memory. If your code does contain conflicts, you&amp;rsquo;ll get a compile-time or runtime error.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;또한&amp;nbsp;Swift는&amp;nbsp;메모리의&amp;nbsp;위치를&amp;nbsp;수정하는&amp;nbsp;코드가&amp;nbsp;해당&amp;nbsp;메모리에&amp;nbsp;&lt;b&gt;독점적으로&amp;nbsp;액세스할&amp;nbsp;수&amp;nbsp;있도록&amp;nbsp;요구함&lt;/b&gt;으로써&amp;nbsp;동일한&amp;nbsp;메모리&amp;nbsp;영역에&amp;nbsp;대한&amp;nbsp;다중&amp;nbsp;액세스가&amp;nbsp;충돌하지&amp;nbsp;않도록&amp;nbsp;합니다.&amp;nbsp;Swift는&amp;nbsp;&lt;b&gt;메모리를&amp;nbsp;자동으로&amp;nbsp;관리&lt;/b&gt;하기&amp;nbsp;때문에&amp;nbsp;대부분의&amp;nbsp;경우&amp;nbsp;메모리&amp;nbsp;액세스에&amp;nbsp;대해&amp;nbsp;전혀&amp;nbsp;생각할&amp;nbsp;필요가&amp;nbsp;없습니다.&amp;nbsp;그러나&amp;nbsp;잠재적인&amp;nbsp;충돌이&amp;nbsp;발생할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;위치를&amp;nbsp;이해하는&amp;nbsp;것이&amp;nbsp;중요하므로&amp;nbsp;메모리에&amp;nbsp;대한&amp;nbsp;액세스&amp;nbsp;충돌이&amp;nbsp;있는&amp;nbsp;코드&amp;nbsp;작성을&amp;nbsp;피할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;코드에&amp;nbsp;충돌이&amp;nbsp;포함되어&amp;nbsp;있으면&amp;nbsp;컴파일&amp;nbsp;시간&amp;nbsp;또는&amp;nbsp;런타임&amp;nbsp;오류가&amp;nbsp;발생합니다.&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;color: #5f6d2b;&quot;&gt;&lt;b&gt;Understanding Conflicting Access to Memory(메모리에 대한 충돌 액세스 이해)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Access to memory happens in your code when you do things like set the value of a variable or pass an argument to a function. For example, the following code contains both a read access and a write access:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;변수 값을 설정하거나 함수에 인자를 전달하는 것과 같은 작업을 수행할 때, 코드에서 메모리에 대한 액세스가 발생합니다. 예를 들어 다음 코드에는 읽기 액세스와 쓰기 액세스가 모두 포함되어 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1661435478858&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// A write access to the memory where one is stored.
var one = 1

// A read access from the memory where one is stored.
print(&quot;We're number \(one)!&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;A conflicting access to memory can occur when different parts of your code are trying to access the same location in memory at the same time. Multiple accesses to a location in memory at the same time can produce unpredictable or inconsistent behavior. In Swift, there are ways to modify a value that span several lines of code, making it possible to attempt to access a value in the middle of its own modification.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;메모리에 대한 액세스 충돌은 코드의 다른 부분이 동시에 메모리의 동일한 위치에 액세스하려고 할 때 발생할 수 있습니다. 동시에 메모리의 한 위치에 여러 번 액세스하면 예측할 수 없거나 일관성이 없는 동작이 발생할 수 있습니다. Swift에는 여러 줄의 코드에 걸쳐 있는 값을 수정하는 방법이 있습니다. 이를 통해 자체 수정 중에 값에 액세스를 시도할 수 있습니다.&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: #5f6d2b;&quot;&gt;You can see a similar problem by thinking about how you update a budget that&amp;rsquo;s written on a piece of paper. Updating the budget is a two-step process: First you add the items&amp;rsquo; names and prices, and then you change the total amount to reflect the items currently on the list. Before and after the update, you can read any information from the budget and get a correct answer, as shown in the figure below.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;종이에 적힌 예산을 어떻게 업데이트할지 생각해 보면 비슷한 문제를 볼 수 있습니다. 예산 업데이트는 두 단계 프로세스입니다. 먼저 항목의 이름과 가격을 추가한 다음 현재 목록에 있는 항목을 반영하도록 총액을 변경합니다. 업데이트 전후에는 아래 그림과 같이 예산에서 모든 정보를 읽고 정답을 얻을 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cPYRhh/btrKzOuu0gX/ZlZYQYlqOGXlK7FKG4Cvw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cPYRhh/btrKzOuu0gX/ZlZYQYlqOGXlK7FKG4Cvw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cPYRhh/btrKzOuu0gX/ZlZYQYlqOGXlK7FKG4Cvw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcPYRhh%2FbtrKzOuu0gX%2FZlZYQYlqOGXlK7FKG4Cvw0%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;500&quot; height=&quot;162&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;400&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: #5f6d2b;&quot;&gt;While you&amp;rsquo;re adding items to the budget, it&amp;rsquo;s in a temporary, invalid state because the total amount hasn&amp;rsquo;t been updated to reflect the newly added items. Reading the total amount during the process of adding an item gives you incorrect information.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;예산에&amp;nbsp;항목을&amp;nbsp;추가하는&amp;nbsp;동안&amp;nbsp;총&amp;nbsp;금액이&amp;nbsp;새로&amp;nbsp;추가된&amp;nbsp;항목을&amp;nbsp;반영하도록&amp;nbsp;업데이트되지&amp;nbsp;않았기&amp;nbsp;때문에&amp;nbsp;예산은&amp;nbsp;일시적이고&amp;nbsp;잘못된&amp;nbsp;상태입니다.&amp;nbsp;항목을&amp;nbsp;추가하는&amp;nbsp;과정에서&amp;nbsp;총&amp;nbsp;금액을&amp;nbsp;읽으면&amp;nbsp;잘못된&amp;nbsp;정보를&amp;nbsp;제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;This example also demonstrates a challenge you may encounter when fixing conflicting access to memory: There are sometimes multiple ways to fix the conflict that produce different answers, and it&amp;rsquo;s not always obvious which answer is correct. In this example, depending on whether you wanted the original total amount or the updated total amount, either $5 or $320 could be the correct answer. Before you can fix the conflicting access, you have to determine what it was intended to do.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이&amp;nbsp;예는&amp;nbsp;또한&amp;nbsp;충돌하는&amp;nbsp;메모리&amp;nbsp;액세스를&amp;nbsp;수정할&amp;nbsp;때&amp;nbsp;직면할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;문제를&amp;nbsp;보여줍니다.&amp;nbsp;충돌을&amp;nbsp;수정하는&amp;nbsp;여러&amp;nbsp;가지&amp;nbsp;방법으로&amp;nbsp;다른&amp;nbsp;답변이&amp;nbsp;생성되는&amp;nbsp;경우가&amp;nbsp;있으며&amp;nbsp;어떤&amp;nbsp;답변이&amp;nbsp;올바른지&amp;nbsp;항상&amp;nbsp;명확하지&amp;nbsp;않습니다.&amp;nbsp;이&amp;nbsp;예에서&amp;nbsp;원래&amp;nbsp;총&amp;nbsp;금액을&amp;nbsp;원하는지&amp;nbsp;아니면&amp;nbsp;업데이트된&amp;nbsp;총&amp;nbsp;금액을&amp;nbsp;원하는지에&amp;nbsp;따라&amp;nbsp;$5&amp;nbsp;또는&amp;nbsp;$320가&amp;nbsp;정답이&amp;nbsp;될&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;충돌하는&amp;nbsp;액세스를&amp;nbsp;수정하기&amp;nbsp;전에&amp;nbsp;의도한&amp;nbsp;작업을&amp;nbsp;결정해야&amp;nbsp;합니다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;NOTE&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;If you&amp;rsquo;ve written concurrent or multithreaded code, conflicting access to memory might be a familiar problem. However, the conflicting access discussed here can happen on a single thread and doesn&amp;rsquo;t involve concurrent or multithreaded code.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;동시&amp;nbsp;또는&amp;nbsp;다중&amp;nbsp;스레드&amp;nbsp;코드를&amp;nbsp;작성했다면&amp;nbsp;메모리에&amp;nbsp;대한&amp;nbsp;액세스&amp;nbsp;충돌이&amp;nbsp;익숙한&amp;nbsp;문제일&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;그러나&amp;nbsp;여기에서&amp;nbsp;설명하는&amp;nbsp;충돌&amp;nbsp;액세스는&amp;nbsp;단일&amp;nbsp;스레드에서&amp;nbsp;발생할&amp;nbsp;수&amp;nbsp;있으며&amp;nbsp;동시&amp;nbsp;또는&amp;nbsp;다중&amp;nbsp;스레드&amp;nbsp;코드를&amp;nbsp;포함하지&amp;nbsp;않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;If you have conflicting access to memory from within a single thread, Swift guarantees that you&amp;rsquo;ll get an error at either compile time or runtime. For multithreaded code, use Thread Sanitizer to help detect conflicting access across threads.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;단일&amp;nbsp;스레드&amp;nbsp;내에서&amp;nbsp;충돌하는&amp;nbsp;메모리&amp;nbsp;액세스가&amp;nbsp;있는&amp;nbsp;경우&amp;nbsp;Swift는&amp;nbsp;컴파일&amp;nbsp;시간이나&amp;nbsp;런타임에&amp;nbsp;오류가&amp;nbsp;발생하도록&amp;nbsp;보장합니다.&lt;/b&gt; 다중&amp;nbsp;스레드&amp;nbsp;코드의&amp;nbsp;경우&amp;nbsp;Thread&amp;nbsp;Sanitizer를&amp;nbsp;사용하여&amp;nbsp;스레드&amp;nbsp;간에&amp;nbsp;충돌하는&amp;nbsp;액세스를&amp;nbsp;감지할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;Characteristics of Memory Access(메모리 액세스의 특성)&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;There are three characteristics of memory access to consider in the context of conflicting access: whether the access is a read or a write, the duration of the access, and the location in memory being accessed. Specifically, a conflict occurs if you have two accesses that meet all of the following conditions:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;At least one is a write access or a nonatomic access.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;They access the same location in memory.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Their durations overlap.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;액세스가 충돌하는 상황에서 고려해야 할 메모리 액세스의 세 가지 특성이 있습니다. 액세스가 읽기인지 쓰기인지, 액세스 기간 및 액세스되는 메모리의 위치입니다. 특히 다음 조건을 모두 충족하는 두 개의 액세스 권한이 있는 경우 충돌이 발생합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;적어도 하나는 쓰기 액세스 또는 비원자 액세스입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;메모리의 동일한 위치에 액세스합니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;기간이 겹칩니다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;The difference between a read and write access is usually obvious: a write access changes the location in memory, but a read access doesn&amp;rsquo;t. The location in memory refers to what is being accessed&amp;mdash;for example, a variable, constant, or property. The duration of a memory access is either instantaneous or long-term.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&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: #5f6d2b;&quot;&gt;An operation is atomic if it uses only C atomic operations; otherwise it&amp;rsquo;s nonatomic. For a list of those functions, see the stdatomic(3) man page.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;C&amp;nbsp;원자적&amp;nbsp;연산만&amp;nbsp;사용하는&amp;nbsp;경우&amp;nbsp;연산은&amp;nbsp;원자적입니다.&amp;nbsp;그렇지&amp;nbsp;않으면&amp;nbsp;비원자적입니다.&amp;nbsp;이러한&amp;nbsp;함수&amp;nbsp;목록은&amp;nbsp;stdatomic(3)&amp;nbsp;매뉴얼&amp;nbsp;페이지를&amp;nbsp;참조하십시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;An access is instantaneous if it&amp;rsquo;s not possible for other code to run after that access starts but before it ends. By their nature, two instantaneous accesses can&amp;rsquo;t happen at the same time. Most memory access is instantaneous. For example, all the read and write accesses in the code listing below are instantaneous:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;액세스가&amp;nbsp;시작된&amp;nbsp;후&amp;nbsp;종료되기&amp;nbsp;전에&amp;nbsp;다른&amp;nbsp;코드를&amp;nbsp;실행할&amp;nbsp;수&amp;nbsp;없는&amp;nbsp;경우&amp;nbsp;액세스는&amp;nbsp;즉각적입니다.&amp;nbsp;본질적으로&amp;nbsp;두&amp;nbsp;개의&amp;nbsp;즉각적인&amp;nbsp;액세스는&amp;nbsp;동시에&amp;nbsp;발생할&amp;nbsp;수&amp;nbsp;없습니다.&amp;nbsp;&lt;/b&gt;대부분의&amp;nbsp;메모리&amp;nbsp;액세스는&amp;nbsp;즉각적입니다.&amp;nbsp;예를&amp;nbsp;들어&amp;nbsp;아래&amp;nbsp;코드&amp;nbsp;목록의&amp;nbsp;모든&amp;nbsp;읽기&amp;nbsp;및&amp;nbsp;쓰기&amp;nbsp;액세스는&amp;nbsp;즉각적입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1661436771872&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func oneMore(than number: Int) -&amp;gt; Int {
    return number + 1
}

var myNumber = 1
myNumber = oneMore(than: myNumber)
print(myNumber)
// Prints &quot;2&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;However, there are several ways to access memory, called long-term accesses, that span the execution of other code. The difference between instantaneous access and long-term access is that it&amp;rsquo;s possible for other code to run after a long-term access starts but before it ends, which is called overlap. A long-term access can overlap with other long-term accesses and instantaneous accesses.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그러나&amp;nbsp;다른&amp;nbsp;코드&amp;nbsp;실행에&amp;nbsp;걸쳐&amp;nbsp;메모리에&amp;nbsp;액세스하는&amp;nbsp;여러&amp;nbsp;가지&amp;nbsp;방법이&amp;nbsp;있습니다.&amp;nbsp;이를&amp;nbsp;장기&amp;nbsp;액세스라고&amp;nbsp;합니다.&amp;nbsp;즉시&amp;nbsp;액세스와&amp;nbsp;장기&amp;nbsp;액세스의&amp;nbsp;차이점은&amp;nbsp;&lt;b&gt;장기&amp;nbsp;액세스가&amp;nbsp;시작된&amp;nbsp;후&amp;nbsp;종료되기&amp;nbsp;전에&amp;nbsp;다른&amp;nbsp;코드가&amp;nbsp;실행될&amp;nbsp;수&amp;nbsp;있다는&amp;nbsp;점입니다.&amp;nbsp;이를&amp;nbsp;오버랩이라고&amp;nbsp;합니다.&lt;/b&gt; 장기 액세스는 다른 장기 액세스 및 순간 액세스와 중첩될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Overlapping accesses appear primarily in code that uses in-out parameters in functions and methods or mutating methods of a structure. The specific kinds of Swift code that use long-term accesses are discussed in the sections below.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;중복 액세스는 주로 함수 및 메서드에서 &lt;b&gt;in-out 매개변수&lt;/b&gt;를 사용하거나 &lt;b&gt;구조체의 메서드를 변경(mutating)하는 코드&lt;/b&gt;에서 나타납니다. 장기 액세스를 사용하는 특정 종류의 Swift 코드는 아래 섹션에서 설명합니다.&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;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;Conflicting Access to In-Out Parameters(In-Out&amp;nbsp;매개변수에&amp;nbsp;대한&amp;nbsp;액세스&amp;nbsp;충돌)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;A function has long-term write access to all of its in-out parameters. The write access for an in-out parameter starts after all of the non-in-out parameters have been evaluated and lasts for the entire duration of that function call. If there are multiple in-out parameters, the write accesses start in the same order as the parameters appear.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;함수는 모든 in-out 매개변수에 대한 장기 쓰기 액세스 권한을 가집니다.&lt;/b&gt; in-out 매개변수에 대한 쓰기 액세스는 모든 non-in-out 매개변수가 평가된 후 시작되고 해당 함수 호출의 전체 기간 동안 지속됩니다. &lt;b&gt;in-out&amp;nbsp;매개변수가 여러 개인 경우 쓰기 액세스는 매개변수가 나타나는 순서대로 시작됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;One consequence of this long-term write access is that you can&amp;rsquo;t access the original variable that was passed as in-out, even if scoping rules and access control would otherwise permit it&amp;mdash;any access to the original creates a conflict. For example:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 장기 쓰기 액세스의 결과 중 하나는 범위 지정 규칙과 액세스 제어가 허용하더라도 in-out으로 전달된 원래 변수에 액세스할 수 없다는 것입니다. 원본에 대한 액세스는 충돌을 일으킵니다. 예를 들어:&lt;/p&gt;
&lt;pre id=&quot;code_1661437406197&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var stepSize = 1

func increment(_ number: inout Int) {
    number += stepSize
}

increment(&amp;amp;stepSize)
// Error: conflicting accesses to stepSize&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;In the code above, stepSize is a global variable, and it&amp;rsquo;s normally accessible from within increment(_:). However, the read access to stepSize overlaps with the write access to number. As shown in the figure below, both number and stepSize refer to the same location in memory. The read and write accesses refer to the same memory and they overlap, producing a conflict.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위의&amp;nbsp;코드에서&amp;nbsp;stepSize는&amp;nbsp;전역&amp;nbsp;변수이며&amp;nbsp;일반적으로&amp;nbsp;increment(_:)&amp;nbsp;내에서&amp;nbsp;액세스할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;&lt;b&gt;그러나&amp;nbsp;stepSize에&amp;nbsp;대한&amp;nbsp;읽기&amp;nbsp;액세스는&amp;nbsp;number에&amp;nbsp;대한&amp;nbsp;쓰기&amp;nbsp;액세스와&amp;nbsp;겹칩니다.&lt;/b&gt;&amp;nbsp;아래&amp;nbsp;그림과&amp;nbsp;같이&amp;nbsp;number와&amp;nbsp;stepSize는&amp;nbsp;모두&amp;nbsp;메모리의&amp;nbsp;동일한&amp;nbsp;위치를&amp;nbsp;참조합니다.&amp;nbsp;읽기&amp;nbsp;및&amp;nbsp;쓰기&amp;nbsp;액세스는&amp;nbsp;동일한&amp;nbsp;메모리를&amp;nbsp;참조하며&amp;nbsp;중복되어&amp;nbsp;충돌이&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;884&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfXfHB/btrKAjucdqb/CtZTk3Q5lHXkPgEF6MBTbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfXfHB/btrKAjucdqb/CtZTk3Q5lHXkPgEF6MBTbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfXfHB/btrKAjucdqb/CtZTk3Q5lHXkPgEF6MBTbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfXfHB%2FbtrKAjucdqb%2FCtZTk3Q5lHXkPgEF6MBTbK%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;500&quot; height=&quot;89&quot; data-origin-width=&quot;884&quot; data-origin-height=&quot;158&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: #5f6d2b;&quot;&gt;One way to solve this conflict is to make an explicit copy of stepSize:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이&amp;nbsp;충돌을&amp;nbsp;해결하는&amp;nbsp;한&amp;nbsp;가지&amp;nbsp;방법은&amp;nbsp;stepSize의&amp;nbsp;명시적&amp;nbsp;복사본을&amp;nbsp;만드는&amp;nbsp;것입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1661437731058&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Make an explicit copy.
var copyOfStepSize = stepSize
increment(&amp;amp;copyOfStepSize)

// Update the original.
stepSize = copyOfStepSize
// stepSize is now 2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;When you make a copy of stepSize before calling increment(_:), it&amp;rsquo;s clear that the value of copyOfStepSize is incremented by the current step size. The read access ends before the write access starts, so there isn&amp;rsquo;t a conflict.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;increment(_:)를&amp;nbsp;호출하기&amp;nbsp;전에&amp;nbsp;stepSize의&amp;nbsp;복사본을&amp;nbsp;만들&amp;nbsp;때&amp;nbsp;copyOfStepSize의&amp;nbsp;값이&amp;nbsp;현재&amp;nbsp;단계&amp;nbsp;크기만큼&amp;nbsp;증가하는&amp;nbsp;것이&amp;nbsp;분명합니다.&amp;nbsp;읽기&amp;nbsp;접근은&amp;nbsp;쓰기&amp;nbsp;접근이&amp;nbsp;시작되기&amp;nbsp;전에&amp;nbsp;끝나므로&amp;nbsp;충돌이&amp;nbsp;없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Another consequence of long-term write access to in-out parameters is that passing a single variable as the argument for multiple in-out parameters of the same function produces a conflict. For example:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;in-out&amp;nbsp;매개변수에&amp;nbsp;대한&amp;nbsp;장기&amp;nbsp;쓰기&amp;nbsp;액세스의&amp;nbsp;또&amp;nbsp;다른&amp;nbsp;결과는&amp;nbsp;&lt;b&gt;동일한&amp;nbsp;함수의&amp;nbsp;여러&amp;nbsp;in-out&amp;nbsp;매개변수에&amp;nbsp;대한&amp;nbsp;인수로&amp;nbsp;단일&amp;nbsp;변수를&amp;nbsp;전달하면&amp;nbsp;충돌이&amp;nbsp;발생한다는&amp;nbsp;것입니다.&lt;/b&gt;&amp;nbsp;예를&amp;nbsp;들어:&lt;/p&gt;
&lt;pre id=&quot;code_1661437852332&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func balance(_ x: inout Int, _ y: inout Int) {
    let sum = x + y
    x = sum / 2
    y = sum - x
}
var playerOneScore = 42
var playerTwoScore = 30
balance(&amp;amp;playerOneScore, &amp;amp;playerTwoScore)  // OK
balance(&amp;amp;playerOneScore, &amp;amp;playerOneScore)
// Error: conflicting accesses to playerOneScore&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;The balance(_:_:) function above modifies its two parameters to divide the total value evenly between them. Calling it with playerOneScore and playerTwoScore as arguments doesn&amp;rsquo;t produce a conflict&amp;mdash;there are two write accesses that overlap in time, but they access different locations in memory. In contrast, passing playerOneScore as the value for both parameters produces a conflict because it tries to perform two write accesses to the same location in memory at the same time.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위의&amp;nbsp;balance(_:_:)&amp;nbsp;함수는&amp;nbsp;두&amp;nbsp;매개변수를&amp;nbsp;수정하여&amp;nbsp;전체&amp;nbsp;값을&amp;nbsp;균등하게&amp;nbsp;나눕니다.&amp;nbsp;playerOneScore&amp;nbsp;및&amp;nbsp;playerTwoScore를&amp;nbsp;인수로&amp;nbsp;사용하여&amp;nbsp;호출하면&amp;nbsp;충돌이&amp;nbsp;발생하지&amp;nbsp;않습니다.&amp;nbsp;시간적으로&amp;nbsp;겹치는&amp;nbsp;두&amp;nbsp;개의&amp;nbsp;쓰기&amp;nbsp;액세스가&amp;nbsp;있지만&amp;nbsp;메모리의&amp;nbsp;다른&amp;nbsp;위치에&amp;nbsp;액세스합니다.&amp;nbsp;대조적으로&amp;nbsp;두&amp;nbsp;매개변수의&amp;nbsp;값으로&amp;nbsp;playerOneScore를&amp;nbsp;전달하면&amp;nbsp;&lt;b&gt;메모리의&amp;nbsp;동일한&amp;nbsp;위치에&amp;nbsp;대해&amp;nbsp;동시에&amp;nbsp;두&amp;nbsp;개의&amp;nbsp;쓰기&amp;nbsp;액세스를&amp;nbsp;수행하려고&amp;nbsp;하기&amp;nbsp;때문에&amp;nbsp;충돌이&amp;nbsp;발생합니다.&lt;/b&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;NOTE&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Because operators are functions, they can also have long-term accesses to their in-out parameters. For example, if&amp;nbsp;balance(_:_:)&amp;nbsp;was an operator function named&amp;nbsp;&amp;lt;^&amp;gt;, writing&amp;nbsp;playerOneScore&amp;nbsp;&amp;lt;^&amp;gt;&amp;nbsp;playerOneScore&amp;nbsp;would result in the same conflict as&amp;nbsp;balance(&amp;amp;playerOneScore,&amp;nbsp;&amp;amp;playerOneScore).&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;연산자는 함수이기 때문에 in-out 매개변수에 장기간 액세스할 수도 있습니다. 예를 들어, balance(_:_:)가 &amp;lt;^&amp;gt;라는 연산자 함수인 경우 playerOneScore &amp;lt;^&amp;gt; playerOneScore를 작성하면 balance(&amp;amp;playerOneScore, &amp;amp;playerOneScore)와 동일한 충돌이 발생합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&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;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;Conflicting Access to self in Methods(메서드에서&amp;nbsp;self에&amp;nbsp;대한&amp;nbsp;충돌&amp;nbsp;액세스)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;A mutating method on a structure has write access to self for the duration of the method call. For example, consider a game where each player has a health amount, which decreases when taking damage, and an energy amount, which decreases when using special abilities.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;구조체의 mutating 메서드는 메서드 호출 기간 동안 자체에 대한 쓰기 액세스 권한을 가집니다. 예를 들어, 각 플레이어가 피해를 입을 때 감소하는 건강 양이 있고 특수 능력을 사용할 때 감소하는 에너지 양이 있는 게임을 고려하십시오.&lt;/p&gt;
&lt;pre id=&quot;code_1661438105039&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct Player {
    var name: String
    var health: Int
    var energy: Int

    static let maxHealth = 10
    mutating func restoreHealth() {
        health = Player.maxHealth
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;In the restoreHealth() method above, a write access to self starts at the beginning of the method and lasts until the method returns. In this case, there&amp;rsquo;s no other code inside restoreHealth() that could have an overlapping access to the properties of a Player instance. The shareHealth(with:) method below takes another Player instance as an in-out parameter, creating the possibility of overlapping accesses.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위의 restoreHealth() 메서드에서 self에 대한 쓰기 액세스는 메서드의 시작 부분에서 시작하여 메서드가 반환될 때까지 지속됩니다. 이 경우 플레이어 인스턴스의 프로퍼티에 중복 액세스할 수 있는 restoreHealth() 내부에 다른 코드가 없습니다. 아래의 shareHealth(with:) 메서드는 다른 Player 인스턴스를 in-out 매개변수로 사용하여 액세스가 겹칠 가능성을 만듭니다.&lt;/p&gt;
&lt;pre id=&quot;code_1661438296719&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;extension Player {
    mutating func shareHealth(with teammate: inout Player) {
        balance(&amp;amp;teammate.health, &amp;amp;health)
    }
}

var oscar = Player(name: &quot;Oscar&quot;, health: 10, energy: 10)
var maria = Player(name: &quot;Maria&quot;, health: 5, energy: 10)
oscar.shareHealth(with: &amp;amp;maria)  // OK&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;In the example above, calling the&amp;nbsp;shareHealth(with:)&amp;nbsp;method for Oscar&amp;rsquo;s player to share health with Maria&amp;rsquo;s player doesn&amp;rsquo;t cause a conflict. There&amp;rsquo;s a write access to&amp;nbsp;oscar&amp;nbsp;during the method call because&amp;nbsp;oscar&amp;nbsp;is the value of&amp;nbsp;self&amp;nbsp;in a mutating method, and there&amp;rsquo;s a write access to&amp;nbsp;maria&amp;nbsp;for the same duration because&amp;nbsp;maria&amp;nbsp;was passed as an in-out parameter. As shown in the figure below, they access different locations in memory. Even though the two write accesses overlap in time, they don&amp;rsquo;t conflict.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위의&amp;nbsp;예에서&amp;nbsp;Oscar의&amp;nbsp;플레이어가&amp;nbsp;Maria의&amp;nbsp;플레이어와&amp;nbsp;건강을&amp;nbsp;공유하도록&amp;nbsp;shareHealth(with:)&amp;nbsp;메서드를&amp;nbsp;호출해도&amp;nbsp;충돌이&amp;nbsp;발생하지&amp;nbsp;않습니다.&amp;nbsp;oscar는&amp;nbsp;mutating&amp;nbsp;메서드에서&amp;nbsp;self의&amp;nbsp;값이기&amp;nbsp;때문에&amp;nbsp;메서드&amp;nbsp;호출&amp;nbsp;중에&amp;nbsp;oscar에&amp;nbsp;대한&amp;nbsp;쓰기&amp;nbsp;액세스가&amp;nbsp;있고,&amp;nbsp;Maria가&amp;nbsp;in-out&amp;nbsp;매개변수로&amp;nbsp;전달되었기&amp;nbsp;때문에&amp;nbsp;동일한&amp;nbsp;기간&amp;nbsp;동안&amp;nbsp;Maria에&amp;nbsp;대한&amp;nbsp;쓰기&amp;nbsp;액세스가&amp;nbsp;있습니다.&amp;nbsp;아래&amp;nbsp;그림과&amp;nbsp;같이&amp;nbsp;메모리의&amp;nbsp;다른&amp;nbsp;위치에&amp;nbsp;액세스합니다.&amp;nbsp;두&amp;nbsp;쓰기&amp;nbsp;액세스가&amp;nbsp;시간적으로&amp;nbsp;겹치더라도&amp;nbsp;충돌하지&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;1098&quot; data-origin-height=&quot;248&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zmYt9/btrKzJUugqN/Etq4GXgnJCpdTeZ4ohkVv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zmYt9/btrKzJUugqN/Etq4GXgnJCpdTeZ4ohkVv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zmYt9/btrKzJUugqN/Etq4GXgnJCpdTeZ4ohkVv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzmYt9%2FbtrKzJUugqN%2FEtq4GXgnJCpdTeZ4ohkVv0%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;500&quot; height=&quot;113&quot; data-origin-width=&quot;1098&quot; data-origin-height=&quot;248&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: #5f6d2b;&quot;&gt;However,&amp;nbsp;if&amp;nbsp;you&amp;nbsp;pass&amp;nbsp;oscar&amp;nbsp;as&amp;nbsp;the&amp;nbsp;argument&amp;nbsp;to&amp;nbsp;shareHealth(with:),&amp;nbsp;there&amp;rsquo;s&amp;nbsp;a&amp;nbsp;conflict:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그러나&amp;nbsp;shareHealth(with:)의&amp;nbsp;인수로&amp;nbsp;oscar를&amp;nbsp;전달하면&amp;nbsp;충돌이&amp;nbsp;발생합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1661438680740&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;oscar.shareHealth(with: &amp;amp;oscar)
// Error: conflicting accesses to oscar&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;The mutating method needs write access to self for the duration of the method, and the in-out parameter needs write access to teammate for the same duration. Within the method, both self and teammate refer to the same location in memory&amp;mdash;as shown in the figure below. The two write accesses refer to the same memory and they overlap, producing a conflict.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;mutating&amp;nbsp;메소드는&amp;nbsp;메소드&amp;nbsp;기간&amp;nbsp;동안&amp;nbsp;self에&amp;nbsp;대한&amp;nbsp;쓰기&amp;nbsp;액세스가&amp;nbsp;필요하고&amp;nbsp;in-out&amp;nbsp;매개변수는&amp;nbsp;동일한&amp;nbsp;기간&amp;nbsp;동안&amp;nbsp;teammate에&amp;nbsp;대한&amp;nbsp;쓰기&amp;nbsp;액세스가&amp;nbsp;필요합니다.&lt;/b&gt;&amp;nbsp;메서드&amp;nbsp;내에서&amp;nbsp;자신과&amp;nbsp;팀원&amp;nbsp;모두&amp;nbsp;아래&amp;nbsp;그림과&amp;nbsp;같이&amp;nbsp;메모리의&amp;nbsp;동일한&amp;nbsp;위치를&amp;nbsp;참조합니다.&amp;nbsp;두&amp;nbsp;개의&amp;nbsp;쓰기&amp;nbsp;액세스는&amp;nbsp;동일한&amp;nbsp;메모리를&amp;nbsp;참조하고&amp;nbsp;겹치므로&amp;nbsp;충돌이&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;1098&quot; data-origin-height=&quot;248&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bC1EFy/btrKz4YaiGo/wsWAP93SlxswjKyXS7iy31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bC1EFy/btrKz4YaiGo/wsWAP93SlxswjKyXS7iy31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bC1EFy/btrKz4YaiGo/wsWAP93SlxswjKyXS7iy31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbC1EFy%2FbtrKz4YaiGo%2FwsWAP93SlxswjKyXS7iy31%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;500&quot; height=&quot;113&quot; data-origin-width=&quot;1098&quot; data-origin-height=&quot;248&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;&lt;b&gt;Conflicting Access to Properties(프로퍼티에 대한 액세스 충돌)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;Types like structures, tuples, and enumerations are made up of individual constituent values, such as the properties of a structure or the elements of a tuple. Because these are value types, mutating any piece of the value mutates the whole value, meaning read or write access to one of the properties requires read or write access to the whole value. For example, overlapping write accesses to the elements of a tuple produces a conflict:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;구조체, 튜플 및 열거형와 같은 타입은 구조체의 프로퍼티이나 튜플의 요소와 같은 개별 구성 값으로 구성됩니다. 이들은 값 타입이기 때문에 값의 일부를 변경하면 전체 값이 변경됩니다. &lt;b&gt;즉, 프로퍼티 중 하나에 대한 읽기 또는 쓰기 액세스에는 전체 값에 대한 읽기 또는 쓰기 액세스가 필요합니다.&lt;/b&gt; 예를 들어, 튜플의 요소에 대한 중복 쓰기 액세스는 충돌을 생성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1661438866772&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var playerInformation = (health: 10, energy: 20)
balance(&amp;amp;playerInformation.health, &amp;amp;playerInformation.energy)
// Error: conflicting access to properties of playerInformation&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;In the example above, calling balance(_:_:) on the elements of a tuple produces a conflict because there are overlapping write accesses to playerInformation. Both playerInformation.health and playerInformation.energy are passed as in-out parameters, which means balance(_:_:) needs write access to them for the duration of the function call. In both cases, a write access to the tuple element requires a write access to the entire tuple. This means there are two write accesses to playerInformation with durations that overlap, causing a conflict.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위의&amp;nbsp;예에서&amp;nbsp;튜플의&amp;nbsp;요소에&amp;nbsp;대해&amp;nbsp;balance(_:_:)를&amp;nbsp;호출하면&amp;nbsp;playerInformation에&amp;nbsp;대한&amp;nbsp;중복&amp;nbsp;쓰기&amp;nbsp;액세스가&amp;nbsp;있기&amp;nbsp;때문에&amp;nbsp;충돌이&amp;nbsp;발생합니다.&amp;nbsp;playerInformation.health와&amp;nbsp;playerInformation.energy는&amp;nbsp;모두&amp;nbsp;in-out&amp;nbsp;매개변수로&amp;nbsp;전달됩니다.&amp;nbsp;즉,&amp;nbsp;balance(_:_:)는&amp;nbsp;함수&amp;nbsp;호출&amp;nbsp;기간&amp;nbsp;동안&amp;nbsp;이에&amp;nbsp;대한&amp;nbsp;쓰기&amp;nbsp;액세스&amp;nbsp;권한이&amp;nbsp;필요합니다.&amp;nbsp;&lt;b&gt;두&amp;nbsp;경우&amp;nbsp;모두&amp;nbsp;튜플&amp;nbsp;요소에&amp;nbsp;대한&amp;nbsp;쓰기&amp;nbsp;액세스에는&amp;nbsp;전체&amp;nbsp;튜플에&amp;nbsp;대한&amp;nbsp;쓰기&amp;nbsp;액세스&amp;nbsp;권한이&amp;nbsp;필요합니다.&lt;/b&gt;&amp;nbsp;이는&amp;nbsp;플레이어&amp;nbsp;정보에&amp;nbsp;대한&amp;nbsp;두&amp;nbsp;개의&amp;nbsp;쓰기&amp;nbsp;액세스가&amp;nbsp;중복되는&amp;nbsp;지속&amp;nbsp;시간으로&amp;nbsp;인해&amp;nbsp;충돌을&amp;nbsp;일으키고&amp;nbsp;있음을&amp;nbsp;의미합니다.&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: #5f6d2b;&quot;&gt;The code below shows that the same error appears for overlapping write accesses to the properties of a structure that&amp;rsquo;s stored in a global variable.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;아래 코드는 전역 변수에 저장된 구조체의 프로퍼티에 대한 중복 쓰기 액세스에 대해 동일한 오류가 나타나는 것을 보여줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1661439197392&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var holly = Player(name: &quot;Holly&quot;, health: 10, energy: 10)
balance(&amp;amp;holly.health, &amp;amp;holly.energy)  // Error&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;In practice, most access to the properties of a structure can overlap safely. For example, if the variable holly in the example above is changed to a local variable instead of a global variable, the compiler can prove that overlapping access to stored properties of the structure is safe:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;실제로 구조체 프로퍼티에 대한 대부분의 액세스는 안전하게 겹칠 수 있습니다. 예를 들어 위의 예에서 변수 holly가 전역 변수 대신 &lt;b&gt;지역 변수&lt;/b&gt;로 변경되면 컴파일러는 &lt;b&gt;구조체의 저장 프로퍼티에 대한 중복 액세스가 안전하다&lt;/b&gt;는 것을 증명할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1661439311762&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func someFunction() {
    var oscar = Player(name: &quot;Oscar&quot;, health: 10, energy: 10)
    balance(&amp;amp;oscar.health, &amp;amp;oscar.energy)  // OK
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;In the example above, Oscar&amp;rsquo;s health and energy are passed as the two in-out parameters to balance(_:_:). The compiler can prove that memory safety is preserved because the two stored properties don&amp;rsquo;t interact in any way.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위의 예에서 Oscar의 건강과 에너지는 balance(_:_:)에 대한 두 개의 in-out 매개변수로 전달됩니다. 컴파일러는 두 개의 저장 프로퍼티가 어떤 식으로든 상호 작용하지 않기 때문에 메모리 안전이 유지됨을 증명할 수 있습니다.&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: #5f6d2b;&quot;&gt;The restriction against overlapping access to properties of a structure isn&amp;rsquo;t always necessary to preserve memory safety.Memory safety is the desired guarantee, but exclusive access is a stricter requirement than memory safety-which means some code preserves memory safety, even though it violates exclusive access to memory. Swift allows this memory-safe code if the compiler can prove that the nonexclusive access to memory is still safe. Specifically, it can prove that overlapping access to properties of a structure is safe if the following conditions apply:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;메모리 안전을 유지하기 위해 구조체 프로퍼티에 대한 중복 액세스에 대한 제한이 항상 필요한 것은 아닙니다. 메모리 안전은 원하는 보장이지만 배타적 액세스는 메모리 안전보다 더 엄격한 요구 사항입니다. 즉, 일부 코드는 메모리에 대한 배타적 액세스를 위반하더라도 메모리 안전을 유지합니다. 컴파일러가 메모리에 대한 비독점적 액세스가 여전히 안전하다는 것을 증명할 수 있는 경우 Swift는 이 메모리 안전 코드를 허용합니다. 특히 다음 조건이 적용되는 경우 구조채 프로퍼티에 대한 중복 액세스가 안전하다는 것을 증명할 수 있습니다.&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: #5f6d2b;&quot;&gt;You&amp;rsquo;re&amp;nbsp;accessing&amp;nbsp;only&amp;nbsp;stored&amp;nbsp;properties&amp;nbsp;of&amp;nbsp;an&amp;nbsp;instance,&amp;nbsp;not&amp;nbsp;computed&amp;nbsp;properties&amp;nbsp;or&amp;nbsp;class&amp;nbsp;properties.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;The structure is the value of a local variable, not a global variable.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;The structure is either not captured by any closures, or it&amp;rsquo;s captured only by nonescaping closures.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #5f6d2b;&quot;&gt;If the compiler can&amp;rsquo;t prove the access is safe, it doesn&amp;rsquo;t allow the access.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;연산 프로퍼티나 클래스 타입이 아닌 인스턴스의 저장된 프로퍼티에만 액세스하고 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구조체는 전역 변수가 아니라 &lt;b&gt;지역 변수&lt;/b&gt;의 값입니다.&lt;/li&gt;
&lt;li&gt;구조체는 클로저에 의해 캡처되지 않거나 &lt;b&gt;nonescaping 클로저&lt;/b&gt;에만 캡처됩니다.&lt;/li&gt;
&lt;li&gt;컴파일러가 액세스가 안전한지 증명할 수 없으면 액세스를 허용하지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;※ 참고 출처&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;a href=&quot;https://docs.swift.org/swift-book/LanguageGuide/MemorySafety.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;애플 개발자 문서&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1661440289717&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;Memory Safety &amp;mdash; The Swift Programming Language (Swift 5.7)&quot; data-og-description=&quot;Memory Safety By default, Swift prevents unsafe behavior from happening in your code. For example, Swift ensures that variables are initialized before they&amp;rsquo;re used, memory isn&amp;rsquo;t accessed after it&amp;rsquo;s been deallocated, and array indices are checked for &quot; data-og-host=&quot;docs.swift.org&quot; data-og-source-url=&quot;https://docs.swift.org/swift-book/LanguageGuide/MemorySafety.html&quot; data-og-url=&quot;https://docs.swift.org/swift-book/LanguageGuide/MemorySafety.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.swift.org/swift-book/LanguageGuide/MemorySafety.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.swift.org/swift-book/LanguageGuide/MemorySafety.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;Memory Safety &amp;mdash; The Swift Programming Language (Swift 5.7)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Memory Safety By default, Swift prevents unsafe behavior from happening in your code. For example, Swift ensures that variables are initialized before they&amp;rsquo;re used, memory isn&amp;rsquo;t accessed after it&amp;rsquo;s been deallocated, and array indices are checked for&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.swift.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>Swift Langage Guide</category>
      <category>IOS</category>
      <category>Language Guide</category>
      <category>Memory Safety</category>
      <category>Swift</category>
      <author>Minny27</author>
      <guid isPermaLink="true">https://minny27.tistory.com/113</guid>
      <comments>https://minny27.tistory.com/113#entry113comment</comments>
      <pubDate>Fri, 26 Aug 2022 00:19:13 +0900</pubDate>
    </item>
    <item>
      <title>[iOS / UIKit] View Controller Life Cycle(뷰 컨트롤러 생명 주기)</title>
      <link>https://minny27.tistory.com/112</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;오늘 설명할 내용은 view controller life cycle입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;iOS 앱 개발에 있어서 필수적으로 알아야 하는 개념입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;일반적으로 iOS 앱 화면에 view controller를 띄우는데&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;view controller에는 생명주기(life cycle)가 있고, 이를 고려해서 앱을 개발해야 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;view controller의 생명주기를 도식화하면 다음과 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;618&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YPccz/btrxdH8FzcM/NT0cKlXaIKDp3AyZJnbPY0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YPccz/btrxdH8FzcM/NT0cKlXaIKDp3AyZJnbPY0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YPccz/btrxdH8FzcM/NT0cKlXaIKDp3AyZJnbPY0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYPccz%2FbtrxdH8FzcM%2FNT0cKlXaIKDp3AyZJnbPY0%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;500&quot; height=&quot;618&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;618&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;생명주기와 관련된 메서드들에 대해서 알아보겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. init(coder:)&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;View Controller을 &lt;b&gt;storyboard&lt;/b&gt;로 생성할 경우, view controller의 객체가 생성될 때 초기화 작업을 하는 메서드가 바로 &lt;b&gt;init(coder:) &lt;/b&gt;메서드입니다. &lt;b&gt;init(coder:) &lt;/b&gt;메서드는 view controller가 생명주기 동안 필요한 자원을 할당합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. init(nibName:bundle:)&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;Storyboard가 아닌 분리된, nib파일로 생성할 경우 &lt;b&gt;init(nibName:bundle)&lt;/b&gt; 메서드로 view controller를 초기화할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. loadView()&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;View Controller에 나타날 view를 만드는 메서드&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;View Controller를 코드로 생성할 때 사용하는 메서드입니다. view controller를 storyboard 혹은. nib 파일로 생성하는 경우, override하지 않는 것이 좋습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;outlet과 action이 이 메서드에서 생성되고 연결됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. viewDidLoad()&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;모든 outlet(테이블 뷰, 버튼 등)이 메모리에 로드된 후 호출되는 메서드.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;이 메서드는 view controller 생명주기 동안 한 번만 실행됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;이 메서드에서 다음의 공통된 작업을 수행합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;네트워크 호출&lt;/li&gt;
&lt;li&gt;User Interface(addSubview 같은 작업)&lt;/li&gt;
&lt;li&gt;한 번 실행하는 작업&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;5. viewWillAppear(_:)&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;View&lt;/b&gt;가 뷰 계층에 추가될 것임을 뷰 컨트롤러에 알리는 메서드&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;이 메서드는 화면에 view controller가 나타난 이후에 호출되는 메서드입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;이 메서드는 다음과 같은 상황에서 사용할 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;비디오 또는 소리 재생&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;화면에 포함된 애니메이션 실행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;화면에 포함된 데이터 업데이트&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;화면 전환 이후 다시 돌아와서 수행하는 작업&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;6. viewDidAppear(_:)&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;뷰가 뷰 계층에 추가되었음을 뷰 컨트롤러에 알리는 메서드&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;데이터를 포함하고 있는 view controller의 view가 완전히 화면에 나타나고 호출되는 메서드입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;7. viewWillDisappear(_:)&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;뷰가 뷰 계층에서 제거될 것임을 뷰 컨트롤러에 알리는 메서드&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;다음 view controller로 화면이 전환되기 전, original view controller가 화면에서 사라질 때 이 메서드가 호출됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;8. viewDidDisappear(_:)&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;뷰가 뷰 계층에서 제거되었음을 뷰 컨트롤러에 알리는 메서드&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;View Controller가 화면에서 사라지고 나서 이 메서드가 호출됩니다. &lt;b&gt;화면에서 view controller가 사라진 이후에는 멈추어야 할 작업들 이 메서드를 override 하여 작성할 수 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;화면이 사라질 때 필요 없을 수 있는 작업은 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;notification을 듣는 행위 멈추기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;다른 객체의 프로퍼티를 observing 멈추기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;네트워크를 호출&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;9. deinit()&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;다른 객체와 마찬가지로 View Controller가 메모리에서 사라지기 전 이 메서드가 호출됩니다. &lt;b&gt;ARC에 의해 할당 해제되지 않은 자원들을 해제하기 위해 override 할 수 있습니다.&lt;/b&gt; 또한 백그라운드에서 실행되는 메서드를 이 메서드 내에서 멈출 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;View Controller가 화면에서 사라지는 것이 메모리에서 해제되는 것은 아닙니다.&lt;/b&gt; 많은 container view controller들이 그들의 view controller들을 메모리에서 유지하고 있기 때문입니다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;예를 들어 Navigation Controller를 더욱 깊숙이 들어가 보면 이전에 보였던 모든 view controller들이 여전히 메모리에 남아있습니다. &lt;b&gt;Navigation Controller는 View Hierarchy 내에서 Back을 하는 경우에만 사라진 View Controller를 할당 해제할 수 있습니다.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;이러한 이유로 화면에서 사라진 view controller들이 정상적으로 작동하고 여전히 notification을 받을 수 있다는 것을 명심해야 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;※ 참고 출처&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;a href=&quot;https://baked-corn.tistory.com/32&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;baked-corn&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;a href=&quot;https://developer.apple.com/documentation/uikit/uiviewcontroller&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;애플 개발자 문서&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;a href=&quot;https://medium.com/good-morning-swift/ios-view-controller-life-cycle-2a0f02e74ff5&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;medium&lt;/a&gt;&lt;/p&gt;</description>
      <category>UIKit</category>
      <category>IOS</category>
      <category>Life Cycle</category>
      <category>UIKit</category>
      <category>View Controller</category>
      <category>생명주기</category>
      <author>Minny27</author>
      <guid isPermaLink="true">https://minny27.tistory.com/112</guid>
      <comments>https://minny27.tistory.com/112#entry112comment</comments>
      <pubDate>Fri, 25 Mar 2022 13:55:03 +0900</pubDate>
    </item>
    <item>
      <title>Join Us - 지원</title>
      <link>https://minny27.tistory.com/111</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이기고 싶다면 합류하라!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LCK 리그 일정, 선수 정보, 순위, 뉴스를 한 눈에!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;# LCK 리그 금일 경기 일정과 선수 정보 제공&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 경기 일정을 확인할 수 있어요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀을 선택하면 그 팀의 선수를 볼 수 있어요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선수를 선택하면 그 선수의 정보를 확인할 수 있어요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;# LCK 리그 월별 일정 제공&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;월별로 경기 일정을 확인할 수 있어요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;# LCK 리그 순위 제공&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리그 순위를 확인해보세요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시즌을 선택하면 해당 시즌의 순위를 확인할 수 있어요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;# LOL 뉴스 제공&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;롤관련 뉴스를 확인할 수 있어요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뉴스를&lt;span&gt; &lt;/span&gt;클릭하면&lt;span&gt; &lt;/span&gt;해당&lt;span&gt; &lt;/span&gt;기사를&lt;span&gt; &lt;/span&gt;볼&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있어요&lt;/p&gt;</description>
      <category>App 출시</category>
      <author>Minny27</author>
      <guid isPermaLink="true">https://minny27.tistory.com/111</guid>
      <comments>https://minny27.tistory.com/111#entry111comment</comments>
      <pubDate>Sat, 12 Mar 2022 13:39:59 +0900</pubDate>
    </item>
    <item>
      <title>Join Us - 개인정보 처리 방침</title>
      <link>https://minny27.tistory.com/110</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;lt; ELLO &amp;gt;('&lt;a href=&quot;https://minny27.tistory.com/'이하&quot;&gt;https://minny27.tistory.com/'이하&lt;/a&gt; 'ELLO')은(는) 「개인정보 보호법」 제30조에 따라 정보주체의 개인정보를 보호하고 이와 관련한 고충을 신속하고 원활하게 처리할 수 있도록 하기 위하여 다음과 같이 개인정보 처리방침을 수립&amp;middot;공개합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;○ 이 개인정보처리방침은&lt;span&gt;&amp;nbsp;&lt;/span&gt;2022년&lt;span&gt;&amp;nbsp;&lt;/span&gt;1월&lt;span&gt;&amp;nbsp;&lt;/span&gt;1부터 적용됩니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;제1조(개인정보의 처리 목적)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&amp;lt; ELLO &amp;gt;('&lt;a href=&quot;https://minny27.tistory.com/'이하&quot;&gt;https://minny27.tistory.com/'이하&lt;/a&gt; 'ELLO')은(는) 다음의 목적을 위하여 개인정보를 처리합니다. 처리하고 있는 개인정보는 다음의 목적 이외의 용도로는 이용되지 않으며 이용 목적이 변경되는 경우에는 「개인정보 보호법」 제18조에 따라 별도의 동의를 받는 등 필요한 조치를 이행할 예정입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 홈페이지 회원가입 및 관리&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;제2조(개인정보의 처리 및 보유 기간)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;①&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt; ELLO &amp;gt;은(는) 법령에 따른 개인정보 보유&amp;middot;이용기간 또는 정보주체로부터 개인정보를 수집 시에 동의받은 개인정보 보유&amp;middot;이용기간 내에서 개인정보를 처리&amp;middot;보유합니다.&lt;br /&gt;&lt;br /&gt;② 각각의 개인정보 처리 및 보유 기간은 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1.&amp;lt;홈페이지 회원가입 및 관리&amp;gt;&lt;/li&gt;
&lt;li&gt;&amp;lt;홈페이지 회원가입 및 관리&amp;gt;와 관련한 개인정보는 수집.이용에 관한 동의일로부터&amp;lt;1년&amp;gt;까지 위 이용목적을 위하여 보유.이용됩니다.&lt;/li&gt;
&lt;li&gt;보유근거 : 고지&amp;middot;통지&lt;/li&gt;
&lt;li&gt;관련법령 : 신용정보의 수집/처리 및 이용 등에 관한 기록 : 3년&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;제3조(정보주체와 법정대리인의 권리&amp;middot;의무 및 그 행사방법)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;① 정보주체는 ELLO에 대해 언제든지 개인정보 열람&amp;middot;정정&amp;middot;삭제&amp;middot;처리정지 요구 등의 권리를 행사할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;② 제1항에 따른 권리 행사는ELLO에 대해 「개인정보 보호법」 시행령 제41조제1항에 따라 서면, 전자우편, 모사전송(FAX) 등을 통하여 하실 수 있으며 ELLO은(는) 이에 대해 지체 없이 조치하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;③ 제1항에 따른 권리 행사는 정보주체의 법정대리인이나 위임을 받은 자 등 대리인을 통하여 하실 수 있습니다.이 경우 &amp;ldquo;개인정보 처리 방법에 관한 고시(제2020-7호)&amp;rdquo; 별지 제11호 서식에 따른 위임장을 제출하셔야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;④ 개인정보 열람 및 처리정지 요구는 「개인정보 보호법」 제35조 제4항, 제37조 제2항에 의하여 정보주체의 권리가 제한 될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;⑤ 개인정보의 정정 및 삭제 요구는 다른 법령에서 그 개인정보가 수집 대상으로 명시되어 있는 경우에는 그 삭제를 요구할 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;⑥ ELLO은(는) 정보주체 권리에 따른 열람의 요구, 정정&amp;middot;삭제의 요구, 처리정지의 요구 시 열람 등 요구를 한 자가 본인이거나 정당한 대리인인지를 확인합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;제4조(개인정보의 파기)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;① &amp;lt; ELLO &amp;gt; 은(는) 개인정보 보유기간의 경과, 처리목적 달성 등 개인정보가 불필요하게 되었을 때에는 지체없이 해당 개인정보를 파기합니다.&lt;br /&gt;&lt;br /&gt;② 정보주체로부터 동의받은 개인정보 보유기간이 경과하거나 처리목적이 달성되었음에도 불구하고 다른 법령에 따라 개인정보를 계속 보존하여야 하는 경우에는, 해당 개인정보를 별도의 데이터베이스(DB)로 옮기거나 보관장소를 달리하여 보존합니다.&lt;br /&gt;1. 법령 근거 :&lt;br /&gt;2. 보존하는 개인정보 항목 : 계좌정보, 거래날짜&lt;br /&gt;&lt;br /&gt;③ 개인정보 파기의 절차 및 방법은 다음과 같습니다.&lt;br /&gt;1. 파기절차&lt;br /&gt;&amp;lt; ELLO &amp;gt; 은(는) 파기 사유가 발생한 개인정보를 선정하고, &amp;lt; ELLO &amp;gt; 의 개인정보 보호책임자의 승인을 받아 개인정보를 파기합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 파기방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;전자적 파일 형태의 정보는 기록을 재생할 수 없는 기술적 방법을 사용합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;제5조(개인정보의 안전성 확보 조치)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&amp;lt; ELLO &amp;gt;은(는) 개인정보의 안전성 확보를 위해 다음과 같은 조치를 취하고 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 개인정보에 대한 접근 제한&lt;br /&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;제6조(개인정보 자동 수집 장치의 설치&amp;bull;운영 및 거부에 관한 사항)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;ELLO 은(는) 정보주체의 이용정보를 저장하고 수시로 불러오는 &amp;lsquo;쿠키(cookie)&amp;rsquo;를 사용하지 않습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;제7조 (개인정보 보호책임자)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;①&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;ELLO&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;은(는) 개인정보 처리에 관한 업무를 총괄해서 책임지고, 개인정보 처리와 관련한 정보주체의 불만처리 및 피해구제 등을 위하여 아래와 같이 개인정보 보호책임자를 지정하고 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;▶ 개인정보 보호책임자&lt;/li&gt;
&lt;li&gt;성명 : 이승민&lt;/li&gt;
&lt;li&gt;이메일 : dltmdals0608@naver.com&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;제8조(권익침해 구제방법)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;정보주체는 개인정보침해로 인한 구제를 받기 위하여 개인정보분쟁조정위원회, 한국인터넷진흥원 개인정보침해신고센터 등에 분쟁해결이나 상담 등을 신청할 수 있습니다. 이 밖에 기타 개인정보침해의 신고, 상담에 대하여는 아래의 기관에 문의하시기 바랍니다.&lt;br /&gt;&lt;br /&gt;1. 개인정보분쟁조정위원회 : (국번없이) 1833-6972 (www.kopico.go.kr)&lt;br /&gt;2. 개인정보침해신고센터 : (국번없이) 118 (privacy.kisa.or.kr)&lt;br /&gt;3. 대검찰청 : (국번없이) 1301 (www.spo.go.kr)&lt;br /&gt;4. 경찰청 : (국번없이) 182 (ecrm.cyber.go.kr)&lt;br /&gt;&lt;br /&gt;「개인정보보호법」제35조(개인정보의 열람), 제36조(개인정보의 정정&amp;middot;삭제), 제37조(개인정보의 처리정지 등)의 규정에 의한 요구에 대 하여 공공기관의 장이 행한 처분 또는 부작위로 인하여 권리 또는 이익의 침해를 받은 자는 행정심판법이 정하는 바에 따라 행정심판을 청구할 수 있습니다.&lt;br /&gt;&lt;br /&gt;※ 행정심판에 대해 자세한 사항은 중앙행정심판위원회(www.simpan.go.kr) 홈페이지를 참고하시기 바랍니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;제9조(개인정보 처리방침 변경)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;① 이 개인정보처리방침은 2022년 1월 1부터 적용됩니다.&lt;/p&gt;</description>
      <category>App 출시</category>
      <author>Minny27</author>
      <guid isPermaLink="true">https://minny27.tistory.com/110</guid>
      <comments>https://minny27.tistory.com/110#entry110comment</comments>
      <pubDate>Sat, 12 Mar 2022 01:13:55 +0900</pubDate>
    </item>
  </channel>
</rss>