<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>오늘도앱개발</title>
    <link>https://todayapp.tistory.com/</link>
    <description>ios앱개발일지</description>
    <language>ko</language>
    <pubDate>Thu, 6 Aug 2026 00:21:28 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>민궝</managingEditor>
    <item>
      <title>[TIL] 포도맛(스레드) 에러</title>
      <link>https://todayapp.tistory.com/40</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트를 하던 중에 안나오던 &lt;b&gt;&lt;span style=&quot;color: #6164c6;&quot;&gt;포도맛 에러&lt;/span&gt;&lt;/b&gt;가 나왔다..&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-16 오후 2.10.15.png&quot; data-origin-width=&quot;2018&quot; data-origin-height=&quot;280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWCN1Y/btsFRAGgedG/ZHPGnE6wXl7VfyokQjkgcK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWCN1Y/btsFRAGgedG/ZHPGnE6wXl7VfyokQjkgcK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWCN1Y/btsFRAGgedG/ZHPGnE6wXl7VfyokQjkgcK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWCN1Y%2FbtsFRAGgedG%2FZHPGnE6wXl7VfyokQjkgcK%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;2018&quot; height=&quot;280&quot; data-filename=&quot;스크린샷 2024-03-16 오후 2.10.15.png&quot; data-origin-width=&quot;2018&quot; data-origin-height=&quot;280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #6164c6;&quot;&gt;&lt;code&gt;UI 업데이트 관련된 코드는 메인스레드에서 돌아가게 보장해줘라!!&lt;/code&gt;&lt;/span&gt; 라는 에러다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기능이 구현되는덴 지장이 없었지만 노란색이든 보라색이든 경고성 에러도 없어야 마음이 편하다,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 없애는게 맞고..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 나는 저 &lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;recordOrder&lt;/span&gt;&lt;/b&gt;&amp;nbsp;프로퍼티에 보라색 줄이 떠서 &lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;recordOrder&lt;/span&gt;&lt;/b&gt;가 문제가 있는줄 알고 쓰인 곳을 다 찾아봤다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 전혀 문제가 되는 곳이 없었다,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭐지?!?!?!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도저히 못찾겠어서 빌드해서 언제 저 에러가 뜨는지 확인해봤다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 이게 머선일,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 &lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CompletionView&lt;/span&gt;&lt;/b&gt;가 나타날때 저 에러가 뜨는 것이었다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;isShowingCompletionView&lt;/span&gt;&lt;/b&gt;가 &lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CompletionView&lt;/span&gt;&lt;/b&gt;을 호출하는 프로퍼티다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;isShowingCompletionView &lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;프로퍼티가 바뀔때 코드는 한군데 밖에 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-16 오후 2.26.54.png&quot; data-origin-width=&quot;1598&quot; data-origin-height=&quot;194&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cs7VmC/btsFRh1eBbS/ianZME88PKdDnNgSbAIY9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cs7VmC/btsFRh1eBbS/ianZME88PKdDnNgSbAIY9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cs7VmC/btsFRh1eBbS/ianZME88PKdDnNgSbAIY9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcs7VmC%2FbtsFRh1eBbS%2FianZME88PKdDnNgSbAIY9k%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;1598&quot; height=&quot;194&quot; data-filename=&quot;스크린샷 2024-03-16 오후 2.26.54.png&quot; data-origin-width=&quot;1598&quot; data-origin-height=&quot;194&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 여기..!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 코드를 실행하는 Task안에 써주니 저 &lt;b&gt;&lt;span style=&quot;color: #6164c6;&quot;&gt;포도맛 에러&lt;/span&gt;&lt;/b&gt;를 뱉은것이었다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 고쳐주자&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-16 오후 2.28.54.png&quot; data-origin-width=&quot;1312&quot; data-origin-height=&quot;290&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5t9HA/btsFRaA2jkU/EaBM9GICRuUz7zb2rchkc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5t9HA/btsFRaA2jkU/EaBM9GICRuUz7zb2rchkc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5t9HA/btsFRaA2jkU/EaBM9GICRuUz7zb2rchkc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5t9HA%2FbtsFRaA2jkU%2FEaBM9GICRuUz7zb2rchkc1%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;1312&quot; height=&quot;290&quot; data-filename=&quot;스크린샷 2024-03-16 오후 2.28.54.png&quot; data-origin-width=&quot;1312&quot; data-origin-height=&quot;290&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Task안에서도 &lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;isShowingCompletionView&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;를 &lt;/span&gt;메인스레드에서 돌아가게 바꿔주었다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 다시 빌드해보니 당연히 에러가 없어졌다 ㅎㅎㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 깨달은건 보라색 줄이 뜨는 곳이 에러가 나는게 아니었다,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에 포도맛 에러가 뜨면 실행 후 어느 부분에서 포도를 뱉는지 확인해보자!!&lt;/p&gt;</description>
      <category>iOS 개발/SwiftUI</category>
      <author>민궝</author>
      <guid isPermaLink="true">https://todayapp.tistory.com/40</guid>
      <comments>https://todayapp.tistory.com/40#entry40comment</comments>
      <pubDate>Sat, 16 Mar 2024 14:32:54 +0900</pubDate>
    </item>
    <item>
      <title>[Git] History에서 특정 파일삭제</title>
      <link>https://todayapp.tistory.com/39</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;바로 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;GoogleService-Info.plist&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; 파일이었다&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분명 &lt;code&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;.gitignore&lt;/span&gt;&lt;/code&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;h2 data-ke-size=&quot;size26&quot;&gt;1. git rm -r --cached .&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;현재 branch의 모든 디렉토리 파일에서 캐시를 제거하는 명령어&lt;/blockquote&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: #006dd7;&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;git rm&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; : 파일 삭제&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;-r&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; : 하위 디렉토리 포함&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;--cached&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; : 캐시&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; : 디렉토리의 모든 파일&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 현재 branch에서 하위 디렉토리 포함 모든 파일에서 캐시를 삭제&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 commit, push를 해주면 해당 파일은 안올라갈것이다&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 나의 상황은 이미 올라가서 History commit에서 삭제시켜줘야 한다  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 작업을 하기전에 중요한게 있다&lt;/p&gt;
&lt;aside&gt;  반드시 해야됨 !!!!⭐️⭐️⭐️⭐️⭐️⭐️
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;현재 branch를 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;git pull&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;로 최신 branch로 만들어줘야한다.&lt;/li&gt;
&lt;li&gt;혹시 모를 상황에 대비해 반드시 &lt;code&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;backup&lt;/span&gt; &lt;span style=&quot;color: #ef5369;&quot;&gt;branch&lt;/span&gt;&lt;/code&gt;를 하나 만들어줘야한다.&lt;/li&gt;
&lt;li&gt;협업 중이라면 반드시 팀원들에게 말을 하고 작업을 해야한다.&lt;/li&gt;
&lt;/ol&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;/aside&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;이제 History의 파일을 제거해보자&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch 경로/파일명.확장자' --prune-empty --tag-name-filter cat -- --all&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;모든 branch의 커밋 히스토리에서 특정 파일을 찾아 제거하는 명령어&lt;/blockquote&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;git&lt;/span&gt; &lt;span style=&quot;color: #006dd7;&quot;&gt;filter-branch&lt;/span&gt;&lt;/code&gt; : 커밋 히스토리 재작성&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;--force&lt;/span&gt;&lt;/code&gt;&lt;/span&gt; : 강제 커밋&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;--index-filter&lt;/span&gt;&lt;/code&gt; : 커밋 인덱스 수정&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;'git rm --cached --ignore-unmatch 경로/파일명.확장자'&lt;/span&gt;&lt;/code&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;git rm&lt;/span&gt;&lt;/code&gt; : 파일 삭제&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;--cached&lt;/span&gt;&lt;/code&gt; : 캐시&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;--ignore-unmatch&lt;/span&gt;&lt;/code&gt; : 파일이 존재하지 않아도 넘어감&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;경로/파일명.확장자&lt;/span&gt;&lt;/code&gt; : 제거할 파일의 경로&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;--prune-empty&lt;/span&gt;&lt;/code&gt; : 필터링 작업 후 결과적으로 빈 커밋이 생성되었을 경우 해당 빈 커밋을 제거&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;--tag-name-filter cat&lt;/span&gt;&lt;/code&gt; : 모든 커밋 태그를 그대로 유지&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;--&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt;--all&lt;/span&gt;&lt;/code&gt; : 모든 브랜치에 대해 작업을 수행&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 모든 브랜치의 특정파일을 포함한 커밋에서 파일을 삭제하고 해당 커밋이 만들어진 빈 커밋을 제거해줘 그리고 커밋 태그를 그대로 유지하고 커밋 히스토리를 재작성&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;음,,,,, 우선 무지하게 긴 명령어다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 뜻도 모르고 블로그를 보고 일단 써봤다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 삭제하는데 성공했지만 commit 개수가 달라져서 당황했다,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 삭제하고 싶은거지 commit을 삭제하고 싶진 않아서였다&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;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;--prune-empty&lt;/span&gt;&lt;/code&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;즉 특정 파일만 올린 commit 이었던거다 (이 파일만 올라간 commit이 왜 있는지는 의문이다..)&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;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;--prune-empty&lt;/span&gt;&lt;/code&gt; 는 뺐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 나는 현재 브랜치만 작업을 해주고싶어서 &lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;-- --all&lt;/span&gt;&lt;/code&gt; 도 뺐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 두 옵션은 선택이다. 나머지는 해줘야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업이 성공하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;Ref refs/remotes/origin/main was rewritten&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이라는 문구가 뜬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실패하면 파일 경로를 잘 적어주었는지 확인하자!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 성공하면 커밋 히스토리를 변경하면서 커밋 해시값이 싹 다 바뀐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 add, commit, push를 해서 커밋 히스토리가 변경된 브랜치로 바꿔주자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;히스토리가 변경되었기 때문에 push할때 강제푸시를 해야한다 (backup 브랜치를 만들라고 한 이유)&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;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;git push origin&lt;/span&gt; &lt;span style=&quot;color: #006dd7;&quot;&gt;--force --all&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;all은 모든 브랜치를 의미하는거기 때문에 현재 브랜치만하고 싶으면 빼자&lt;/li&gt;
&lt;/ul&gt;
&lt;aside&gt;  push하고 꼭 해야될거 !!!!⭐️⭐️⭐️⭐️⭐️⭐️
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;다른 개발자들에게 알리기&lt;/b&gt;: 커밋 히스토리가 변경되었으므로 다른 개발자들에게 변경 사항을 알리고 작업을 동기화해야 한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로컬 브랜치 다시 설정하기&lt;/b&gt;: 다른 개발자들은 로컬 브랜치를 리셋하고 원격 저장소로부터 변경된 커밋 히스토리를 가져와야 한다.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;git&lt;/span&gt; &lt;span style=&quot;color: #006dd7;&quot;&gt;stash&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;git&lt;/span&gt; &lt;span style=&quot;color: #006dd7;&quot;&gt;fetch&lt;/span&gt; &lt;span style=&quot;color: #006dd7;&quot;&gt;origin &lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;git checkout &amp;lt;branch-name&amp;gt; &lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;git reset --hard origin/&amp;lt;branch-name&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;git&lt;/span&gt; &lt;span style=&quot;color: #006dd7;&quot;&gt;stash apply&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;기존 브랜치(커밋 히스토리 변경 전)에서 작업을 하고 있으면 위 명령어들로 커밋 히스토리를 변경해주면 된다.&lt;br /&gt;작업이 없으면 재클론 하는게 깔끔하다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/aside&gt;</description>
      <category>Git</category>
      <author>민궝</author>
      <guid isPermaLink="true">https://todayapp.tistory.com/39</guid>
      <comments>https://todayapp.tistory.com/39#entry39comment</comments>
      <pubDate>Fri, 15 Mar 2024 17:09:12 +0900</pubDate>
    </item>
    <item>
      <title>[ActionSheet] title 안나오게 할 수 있을까?</title>
      <link>https://todayapp.tistory.com/38</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;SwiftUI&lt;/span&gt;로 카카오톡 채팅을 구현하던중 채팅방을 나갈때 뜨는 sheet가 무엇인지 찾아보았다.&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_Photo_2023-07-31-15-14-19 001.jpeg&quot; data-origin-width=&quot;963&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MhTLM/btspk9zCAPZ/oaMEL2AL4xkYOwIRHq4Sd0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MhTLM/btspk9zCAPZ/oaMEL2AL4xkYOwIRHq4Sd0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MhTLM/btspk9zCAPZ/oaMEL2AL4xkYOwIRHq4Sd0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMhTLM%2Fbtspk9zCAPZ%2FoaMEL2AL4xkYOwIRHq4Sd0%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;275&quot; height=&quot;411&quot; data-filename=&quot;KakaoTalk_Photo_2023-07-31-15-14-19 001.jpeg&quot; data-origin-width=&quot;963&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구글링을 해보니 &lt;span style=&quot;background-color: #99cefa;&quot;&gt;ActionSheet&lt;/span&gt;라는 것을 쓴다고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구현 코드는 이렇다 !&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1690785052626&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ContentView: View {
    
    @State private var kakaoActionSheet = false 
    
    var body: some View {
        VStack {
            Button {
                kakaoActionSheet = true
            } label: {
                Image(systemName: &quot;door.left.hand.open&quot;)
            }
            .actionSheet(isPresented: $kakaoActionSheet) {
                ActionSheet(title: Text(&quot;채팅방을 나가면 대화내용이 모두 삭제되고\n채팅목록에서도 사라집니다.&quot;), 
                			buttons: [.destructive(Text(&quot;나가기&quot;)),
                            		  .destructive(Text(&quot;신고하고 나가기&quot;)),
                                      .cancel(Text(&quot;취소&quot;))])
            }
        }
       
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.sheet나 .alert와 같이 @State변수를 만들고 true값으로 바뀔 때 동작하는 것은 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드는 view의 &lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;modifier로 .actionSheet를 달아주고 ,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt; isPresented에 @State변수 값 ,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;그 안에 ActionSheet를 만들어 주면된다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left; color: #8a3db6;&quot;&gt;구현 영상&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;

            &lt;figure class=&quot;unsupported component-kakaotv&quot; contenteditable=&quot;false&quot; style=&quot;background:#000;margin:16px 0;min-height:72px;padding:10px 16px;display:flex;align-items:center;justify-content:center;text-align:center;box-sizing:border-box;width:100%;max-width:100%;&quot;&gt;
                &lt;p contenteditable=&quot;false&quot; style=&quot;margin:0;color:#8a8a8a;font-size:13px;line-height:1.6;user-select:none;pointer-events:none;&quot;&gt;동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.&lt;/p&gt;
            &lt;/figure&gt;
        
&lt;pre id=&quot;code_1690785224732&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ActionSheet(title: Text, message: Text?, buttons: [ActionSheet.Button])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ActionSheet의 형태는 이렇다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;먼저 title은 반드시 Text로 써줘야 한다. 안써주면 넣으라고 에러가 뜬다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-31 오후 3.52.13.png&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;276&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dOEcZc/btspmgE3iia/GtElNmlbk7Rnaa4H9zxcF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dOEcZc/btspmgE3iia/GtElNmlbk7Rnaa4H9zxcF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dOEcZc/btspmgE3iia/GtElNmlbk7Rnaa4H9zxcF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdOEcZc%2FbtspmgE3iia%2FGtElNmlbk7Rnaa4H9zxcF1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;515&quot; height=&quot;152&quot; data-filename=&quot;스크린샷 2023-07-31 오후 3.52.13.png&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;276&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;message는 title밑에 나온다. massage는 없어도 빌드가 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 내가 생각하기엔 message가 옵셔널 타입이니까 message는 없어도 되고 title,buttons는 반드시 써줘야 된다고 생각했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래도 혹시 몰라서 buttons도 지워봤다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;근데 이게 왠일..! buttons는 안써도 title처럼 넣어주라는 에러가 안뜬다 !&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-31 오후 3.55.49.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;148&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWgl2g/btspFmwOOeO/pnnLt6cyvflKQzPU7AOzJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWgl2g/btspFmwOOeO/pnnLt6cyvflKQzPU7AOzJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWgl2g/btspFmwOOeO/pnnLt6cyvflKQzPU7AOzJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWgl2g%2FbtspFmwOOeO%2FpnnLt6cyvflKQzPU7AOzJK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;558&quot; height=&quot;105&quot; data-filename=&quot;스크린샷 2023-07-31 오후 3.55.49.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;148&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그럼 어떻게 나오는거지..?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-31 오후 3.58.04.png&quot; data-origin-width=&quot;596&quot; data-origin-height=&quot;1202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lZzTJ/btspFlSeiaE/AURtM5m0vv3PODW2yvbiq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lZzTJ/btspFlSeiaE/AURtM5m0vv3PODW2yvbiq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lZzTJ/btspFlSeiaE/AURtM5m0vv3PODW2yvbiq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlZzTJ%2FbtspFlSeiaE%2FAURtM5m0vv3PODW2yvbiq1%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;187&quot; height=&quot;377&quot; data-filename=&quot;스크린샷 2023-07-31 오후 3.58.04.png&quot; data-origin-width=&quot;596&quot; data-origin-height=&quot;1202&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;버튼은 안써줘도 .cancel 버튼이 하나가 나온다. 음 그렇다면..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-31 오후 4.00.15.png&quot; data-origin-width=&quot;1410&quot; data-origin-height=&quot;408&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5O3gq/btspnj9udzw/TsUdunt53DBzOUWyCaSvG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5O3gq/btspnj9udzw/TsUdunt53DBzOUWyCaSvG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5O3gq/btspnj9udzw/TsUdunt53DBzOUWyCaSvG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5O3gq%2Fbtspnj9udzw%2FTsUdunt53DBzOUWyCaSvG0%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;660&quot; height=&quot;191&quot; data-filename=&quot;스크린샷 2023-07-31 오후 4.00.15.png&quot; data-origin-width=&quot;1410&quot; data-origin-height=&quot;408&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;역시 공식문서를 찾아보니 .cancel 버튼 하나가 초기화가 돼 있다 !!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이렇게 채팅방 나가기를 구현해서 ActionSheet를 알게 되었다~~&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;잠시 후..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ActionSheet는 채팅방 나가기 뿐 아니라 전화링크로 올라올때도 쓰인다. 이런식으로..!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_Photo_2023-07-31-16-05-59.jpeg&quot; data-origin-width=&quot;665&quot; data-origin-height=&quot;541&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ird8d/btsplbj0Ilr/32QZ0My9cvVkQRAB91tYO1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ird8d/btsplbj0Ilr/32QZ0My9cvVkQRAB91tYO1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ird8d/btsplbj0Ilr/32QZ0My9cvVkQRAB91tYO1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIrd8d%2Fbtsplbj0Ilr%2F32QZ0My9cvVkQRAB91tYO1%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;370&quot; height=&quot;301&quot; data-filename=&quot;KakaoTalk_Photo_2023-07-31-16-05-59.jpeg&quot; data-origin-width=&quot;665&quot; data-origin-height=&quot;541&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;근데 이 ActionSheet는 위에 title이 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 하지만 title은 반드시 써줘야 되기 때문에 title에 값을 &quot;&quot;로 주면 저렇게 뜨겠지 하고&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드를 구현해보았다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1690787557962&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ContentView: View {
    
    @State private var callActionSheet = false
    
    var body: some View {
        VStack {
            Button {
                callActionSheet = true
            } label: {
                Image(systemName: &quot;phone&quot;)
            }
            .actionSheet(isPresented: $callActionSheet) {
                ActionSheet(title: Text(&quot;&quot;) , buttons: [.default(Text(&quot;통화  1899-9900&quot;)),
                    .cancel(Text(&quot;취소&quot;))])
            }
        }
       
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;결과는 .. !!&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-31 오후 4.13.08.png&quot; data-origin-width=&quot;612&quot; data-origin-height=&quot;1214&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cruM1l/btspxcaAAOs/Rzmh7Hn9QT9kEEo1Yv7GgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cruM1l/btspxcaAAOs/Rzmh7Hn9QT9kEEo1Yv7GgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cruM1l/btspxcaAAOs/Rzmh7Hn9QT9kEEo1Yv7GgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcruM1l%2FbtspxcaAAOs%2FRzmh7Hn9QT9kEEo1Yv7GgK%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;212&quot; height=&quot;421&quot; data-filename=&quot;스크린샷 2023-07-31 오후 4.13.08.png&quot; data-origin-width=&quot;612&quot; data-origin-height=&quot;1214&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;어라.. title에 빈값을 줘도 자리는 그래도 차지하고 있다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하지만 title에는 Text를 반드시 넣어줘야 한다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구글링을 해봤더니 방법을 찾았다~~~~~!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우선 위에서 공부했던 ActionSheet는 deprecated 되었다고 한다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-31 오후 3.26.46.png&quot; data-origin-width=&quot;1446&quot; data-origin-height=&quot;674&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uP07c/btspFlxVZWL/SD0BbFL8DnS66kFZaUQr8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uP07c/btspFlxVZWL/SD0BbFL8DnS66kFZaUQr8k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uP07c/btspFlxVZWL/SD0BbFL8DnS66kFZaUQr8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuP07c%2FbtspFlxVZWL%2FSD0BbFL8DnS66kFZaUQr8k%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;568&quot; height=&quot;265&quot; data-filename=&quot;스크린샷 2023-07-31 오후 3.26.46.png&quot; data-origin-width=&quot;1446&quot; data-origin-height=&quot;674&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;deprecated는 애플에서 더 이상 지원하지 않는다는 것이다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하지만 애플은 무조건 deprecated를 시키는게 아니라 대체할 것을 만들고 시키니까 걱정안해도 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-31 오후 3.20.41.png&quot; data-origin-width=&quot;796&quot; data-origin-height=&quot;560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rM8bD/btspE4QBeJI/wXpTXrdSkaJ5AOnkPthluk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rM8bD/btspE4QBeJI/wXpTXrdSkaJ5AOnkPthluk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rM8bD/btspE4QBeJI/wXpTXrdSkaJ5AOnkPthluk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrM8bD%2FbtspE4QBeJI%2FwXpTXrdSkaJ5AOnkPthluk%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;409&quot; height=&quot;288&quot; data-filename=&quot;스크린샷 2023-07-31 오후 3.20.41.png&quot; data-origin-width=&quot;796&quot; data-origin-height=&quot;560&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위 처럼 ActionSheet 대신에 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;confirmationDialog&lt;/span&gt;를 사용하라고 친절하게 말해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ActionSheet를 지우고 confirmationDialog로 코드를 바꿨다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1690789228097&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ContentView: View {
    
    @State private var callActionSheet = false
    
    var body: some View {
        VStack {
            Button {
                callActionSheet = true
            } label: {
                Image(systemName: &quot;phone&quot;)
            }
            .confirmationDialog(&quot;&quot;,  isPresented: $callActionSheet) {
                Button(&quot;통화 1899-9900&quot;, role: .none) {}
                Button(&quot;취소&quot;, role: .cancel) {}
                
            }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구현방식도 ActionSheet와 비슷하다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;modifier로 .actionSheet -&amp;gt; .confirmationDialog 바꿔주고 &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;titlekey에 String 값,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt; isPresented에 @State변수 값 ,&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;그 안에 Button들을 넣어주면 된다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-31 오후 4.45.46.png&quot; data-origin-width=&quot;604&quot; data-origin-height=&quot;1202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt9Txc/btspnkgfD4K/c90AYcp029OW5xJt36DbkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt9Txc/btspnkgfD4K/c90AYcp029OW5xJt36DbkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt9Txc/btspnkgfD4K/c90AYcp029OW5xJt36DbkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbt9Txc%2FbtspnkgfD4K%2Fc90AYcp029OW5xJt36DbkK%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;201&quot; height=&quot;400&quot; data-filename=&quot;스크린샷 2023-07-31 오후 4.45.46.png&quot; data-origin-width=&quot;604&quot; data-origin-height=&quot;1202&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ActionSheet에서 title에 반드시 Text를 써줘야 했던것과 다르게 title 영역이 사라졌다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그럼 titlekey에 &quot;&quot;를 안주고 값을 넣어주면 title이 생기겠지? &quot;전화걸기&quot; 라는 값을 넣어주자 !&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1690790469725&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; .confirmationDialog(&quot;전화걸기&quot;,  isPresented: $callActionSheet) {
                Button(&quot;통화 1899-9900&quot;, role: .none) {}
                Button(&quot;취소&quot;, role: .cancel) {}
                
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;결과는...!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-31 오후 4.45.46.png&quot; data-origin-width=&quot;604&quot; data-origin-height=&quot;1202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z3655/btspFmRb8rh/hzR84Cbx82q6aPrCiBXXU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z3655/btspFmRb8rh/hzR84Cbx82q6aPrCiBXXU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z3655/btspFmRb8rh/hzR84Cbx82q6aPrCiBXXU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz3655%2FbtspFmRb8rh%2FhzR84Cbx82q6aPrCiBXXU1%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;204&quot; height=&quot;406&quot; data-filename=&quot;스크린샷 2023-07-31 오후 4.45.46.png&quot; data-origin-width=&quot;604&quot; data-origin-height=&quot;1202&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;어라..? 역시 단순하지 않다ㅎㅎㅎㅎ 원인이 뭔지 찾아보자..&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1690789345372&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func confirmationDialog&amp;lt;A&amp;gt;(
    _ titleKey: LocalizedStringKey,
    isPresented: Binding&amp;lt;Bool&amp;gt;,
    titleVisibility: Visibility = .automatic, @ViewBuilder actions: () -&amp;gt; A
) -&amp;gt; some View where A : View&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;내가 쓴 confirmationDialog의 형태를 보면 이렇게 돼있다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;딱 봐도 titleVisibility를 써야 될거 같지 않나!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;따로 써주지 않으면 기본값으로 .automatic으로 돼있는데 안나오는걸 보니 바꿔 줘야겠다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1690790733455&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.confirmationDialog(&quot;전화걸기&quot;,  isPresented: $callActionSheet, titleVisibility: .visible) {
                Button(&quot;통화 1899-9900&quot;, role: .none) {}
                Button(&quot;취소&quot;, role: .cancel) {}   
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;titleVisibility의 타입은 Visibility로 돼있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-31 오후 5.06.56.png&quot; data-origin-width=&quot;1426&quot; data-origin-height=&quot;222&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wlOPv/btspCm4Z2o2/KeUcS4o7mABIheSgKZoB21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wlOPv/btspCm4Z2o2/KeUcS4o7mABIheSgKZoB21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wlOPv/btspCm4Z2o2/KeUcS4o7mABIheSgKZoB21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwlOPv%2FbtspCm4Z2o2%2FKeUcS4o7mABIheSgKZoB21%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;565&quot; height=&quot;88&quot; data-filename=&quot;스크린샷 2023-07-31 오후 5.06.56.png&quot; data-origin-width=&quot;1426&quot; data-origin-height=&quot;222&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;Visibility는 애플에서 제공하는 enum이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-31 오후 5.07.04.png&quot; data-origin-width=&quot;1298&quot; data-origin-height=&quot;598&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bL1dXo/btspsVfZ2zk/Qx8si15OMh6EzcV6YN6GGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bL1dXo/btspsVfZ2zk/Qx8si15OMh6EzcV6YN6GGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bL1dXo/btspsVfZ2zk/Qx8si15OMh6EzcV6YN6GGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbL1dXo%2FbtspsVfZ2zk%2FQx8si15OMh6EzcV6YN6GGK%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;397&quot; height=&quot;183&quot; data-filename=&quot;스크린샷 2023-07-31 오후 5.07.04.png&quot; data-origin-width=&quot;1298&quot; data-origin-height=&quot;598&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;Visibility의&amp;nbsp;&lt;/span&gt;case는 automatic, visible , hidden으로 돼있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;automatic이 정확히 뭔지는 잘모르겠지만 visible과 hidden은 그냥 단어만 봐도 보여짐,&amp;nbsp; 숨김이 명확하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 나는 visible로 썼다!! 결과는..!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-31 오후 5.04.44.png&quot; data-origin-width=&quot;604&quot; data-origin-height=&quot;1202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EU3Dl/btsplOB83bt/W6xro5RoKN0oyJcs15Buq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EU3Dl/btsplOB83bt/W6xro5RoKN0oyJcs15Buq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EU3Dl/btsplOB83bt/W6xro5RoKN0oyJcs15Buq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEU3Dl%2FbtsplOB83bt%2FW6xro5RoKN0oyJcs15Buq1%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;216&quot; height=&quot;430&quot; data-filename=&quot;스크린샷 2023-07-31 오후 5.04.44.png&quot; data-origin-width=&quot;604&quot; data-origin-height=&quot;1202&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;역시 내가 생각한대로 title이 나왔다!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_Photo_2023-07-31-15-14-19 002.jpeg&quot; data-origin-width=&quot;1179&quot; data-origin-height=&quot;1098&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwHx5r/btspl7V1hWZ/fLE6qqnpWwmLo1k5fjyG60/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwHx5r/btspl7V1hWZ/fLE6qqnpWwmLo1k5fjyG60/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwHx5r/btspl7V1hWZ/fLE6qqnpWwmLo1k5fjyG60/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcwHx5r%2Fbtspl7V1hWZ%2FfLE6qqnpWwmLo1k5fjyG60%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;265&quot; height=&quot;247&quot; data-filename=&quot;KakaoTalk_Photo_2023-07-31-15-14-19 002.jpeg&quot; data-origin-width=&quot;1179&quot; data-origin-height=&quot;1098&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;당근마켓도 보면 title칸이 없는걸 보니 confirmationDialog를 쓴것같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(SwiftUI로 앱제작이 됐다면 UIkit의 ActionSheet는 title을 안보이게 할 수 있는것 같다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;내가 배운점은&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AcitonSheet는 title에 Text가 들어가야 돼서 자리를 반드시 차지한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;confirmationDialog는 title Visibility로 title을 숨기고 보이게 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AcitonSheet는 deprecated 되었으니 이왕이면 confirmationDialog 쓰는게 좋겠다 !&lt;/span&gt;&lt;/p&gt;</description>
      <category>iOS 개발/SwiftUI</category>
      <author>민궝</author>
      <guid isPermaLink="true">https://todayapp.tistory.com/38</guid>
      <comments>https://todayapp.tistory.com/38#entry38comment</comments>
      <pubDate>Mon, 31 Jul 2023 17:29:09 +0900</pubDate>
    </item>
    <item>
      <title>[Codable] color값 사용하기(연산프로퍼티)</title>
      <link>https://todayapp.tistory.com/33</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SwiftUI에서 데이터를 &lt;span style=&quot;background-color: #99cefa;&quot;&gt;JSON형식&lt;/span&gt;으로 변환하려면 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;Codable&lt;/span&gt;프로토콜을 채택해야 한다.&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1689088003879&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import Foundation
import SwiftUI

struct Sticker: Codable, Identifiable {
    var id: UUID = UUID()
    var memo: String
    var color: Color // &amp;lt;- 이놈 때문에 안됨
    var date: Date
    
    var dateString: String {
    
        let dateFormatter: DateFormatter = DateFormatter()
        dateFormatter.dateFormat = &quot;yyyy-MM-dd EEEE HH:mm&quot;
        
        return dateFormatter.string(from: date)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하지만 위에서 Color 데이터타입은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;Codable&lt;/span&gt;프로토콜에 맞지 않기 때문에 에러가뜬다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-12 오전 12.07.33.png&quot; data-origin-width=&quot;766&quot; data-origin-height=&quot;94&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beo3Qt/btsnhdJQaQp/Qaz8H6zWq9Fc3gMcldJCB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beo3Qt/btsnhdJQaQp/Qaz8H6zWq9Fc3gMcldJCB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beo3Qt/btsnhdJQaQp/Qaz8H6zWq9Fc3gMcldJCB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbeo3Qt%2FbtsnhdJQaQp%2FQaz8H6zWq9Fc3gMcldJCB1%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;701&quot; height=&quot;86&quot; data-filename=&quot;스크린샷 2023-07-12 오전 12.07.33.png&quot; data-origin-width=&quot;766&quot; data-origin-height=&quot;94&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;Codable&lt;/span&gt;은 &lt;b&gt;&lt;span style=&quot;background-color: #c1bef9;&quot;&gt;Decodable과 Encodable&lt;/span&gt;&lt;/b&gt; 프로토콜로 이루어진 typealiars(별명)인데&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-12 오전 12.09.48.png&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;238&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qewzL/btsnbJ35TLd/J8McjEntmNNhNWTT7HusC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qewzL/btsnbJ35TLd/J8McjEntmNNhNWTT7HusC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qewzL/btsnbJ35TLd/J8McjEntmNNhNWTT7HusC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqewzL%2FbtsnbJ35TLd%2FJ8McjEntmNNhNWTT7HusC0%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;656&quot; height=&quot;109&quot; data-filename=&quot;스크린샷 2023-07-12 오전 12.09.48.png&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;238&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Decodable과 Encodable의&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt; &quot;&lt;b&gt;Conforming Types(=적합한 타입)&lt;/b&gt;&quot;&lt;/span&gt;에는 Color타입이 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 color를&lt;b&gt; &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;연산프로퍼티&lt;/span&gt;&lt;/b&gt;로 만들어 해결할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Why?&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: start;&quot;&gt;연산 프로퍼티로 만든 color 값을 Codable에 포함할 수 있는 이유는 연산 프로퍼티가 실제 값을 저장하는 것이 아니라 계산에 의해 값을 반환하기 때문입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: start;&quot;&gt;Codable은 실제 값을 저장하는 프로퍼티만 인식하므로, 연산 프로퍼티는 직접 Codable을 준수할 필요가 없습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: start;&quot;&gt;즉, 연산 프로퍼티는 값을 직접 저장하지 않지만, 코드를 통해 값을 계산하고 반환하므로 이를 활용하여 값을 Codable에 포함시킬 수 있게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 먼저 &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;colorIndex : Int&lt;/b&gt;&lt;/span&gt; 를 만들자&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1689095513770&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var colorIndex: Int = 0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. color의 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;get&lt;/b&gt;&lt;/span&gt; 연산 프로퍼티를 만들어서 &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;colorIndex&lt;/span&gt;&lt;/b&gt;의 값을 swich문에 넣은 뒤 color값이 나오게 하자&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1689095544430&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var color: Color {
        get {
            switch colorIndex {
            case 0:
                return .cyan
            case 1:
                return .purple
            case 2:
                return .blue
            case 3:
                return .yellow
            case 4:
                return .brown
            default:
                return .white
            }
        }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. color의 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;set&lt;/b&gt;&lt;/span&gt; 연산 프로퍼티를 만들어서 받아온 color값을 swich문에 넣은 뒤 &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;colorIndex&lt;/span&gt;&lt;/b&gt;에 저장하자&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-&amp;gt; set에 newValue(받아온 color값)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1689095584089&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var color: Color {
        get {
            switch colorIndex {
            case 0:
                return .cyan
            case 1:
                return .purple
            case 2:
                return .blue
            case 3:
                return .yellow
            case 4:
                return .brown
            default:
                return .white
            }
        }
        
        set { 			  // set으로 colorIndex에 저장
            switch newValue {     // newValue(받아온 color값) 
            case .cyan:
                colorIndex = 0
            case .purple:
                colorIndex = 1
            case .blue:
                colorIndex = 2
            case .yellow:
                colorIndex = 3
            case .brown:
                colorIndex = 4
            default:
                colorIndex = 5
            }
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(연산프로퍼티는 set은 생략가능하지만 get은 생략할수 없어서 get먼저 생각하거나 동시에 생각하자.)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 그럼 이제 JSON형식으로 encode할때 color값이 들어가진다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 다시 JSON형식을 decode하면 값이 그대로 가져와진다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. 이제 코드에 color값을 불러오면 color의 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;get&lt;/b&gt;&lt;/span&gt; 연산 프로퍼티가 실행되어 &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;colorIndex&lt;/span&gt;&lt;/b&gt; 값에 맞는 color 값을 쓸 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>iOS 개발/SwiftUI</category>
      <author>민궝</author>
      <guid isPermaLink="true">https://todayapp.tistory.com/33</guid>
      <comments>https://todayapp.tistory.com/33#entry33comment</comments>
      <pubDate>Wed, 12 Jul 2023 00:55:18 +0900</pubDate>
    </item>
    <item>
      <title>[Clone App] Login - SwiftUI (#1)</title>
      <link>https://todayapp.tistory.com/32</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스터디에서 &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;SwiftUI&lt;/b&gt;&lt;/span&gt;로 &lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;로그인 화면&lt;/b&gt;&lt;/span&gt;을 만들어 보기로 했다!&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터가 저장되고 실제 로그인되는건 아니지만 로그인화면의 다양한 기능을 구현해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled (6).png&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;1204&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8wlqF/btsmGik4g3v/tvoOzsM4hZVpFn3Xlz8vF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8wlqF/btsmGik4g3v/tvoOzsM4hZVpFn3Xlz8vF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8wlqF/btsmGik4g3v/tvoOzsM4hZVpFn3Xlz8vF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8wlqF%2FbtsmGik4g3v%2FtvoOzsM4hZVpFn3Xlz8vF1%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;389&quot; height=&quot;412&quot; data-filename=&quot;Untitled (6).png&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;1204&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우선 화면 구성은 위 사진과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;먼저 1주차에선 &lt;b&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;화면 구성&lt;/span&gt;, &lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;이메일 정규식&lt;/span&gt;, &lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;비밀번호 텍스트 필드&lt;/span&gt;, &lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;로그인 동의&lt;/span&gt;&lt;/b&gt;를 구현하기로 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;화면구성&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. &lt;b&gt;Log in &lt;/b&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;(navigationTitle)&lt;/span&gt; : NavigationStack 이나 NavigationView를 써서 안쪽 view에&amp;nbsp;.navigationTitle(&quot;Log in&quot;)을 주면된다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688973533232&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ContentView: View {

 var body: some View {
        NavigationView {
            VStack {
            
            }.navigationTitle(&quot;Log in&quot;)
        }
  }      
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. &lt;b&gt;Description text &lt;/b&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;(Text)&lt;/span&gt; : 위 코드 VStack안에 Text(&quot;&lt;span style=&quot;text-align: start;&quot;&gt;Introduce your credentials&quot;&amp;nbsp;&lt;/span&gt;)써주면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;swift&quot; data-ke-language=&quot;swift&quot;&gt;&lt;code&gt; Text(&quot;Introduce your credentials&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. &lt;b&gt;Email textField &lt;/b&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;(TextField)&lt;/span&gt; : TextField() 안에 비었을 때 보여질값 , 바인딩 될 text 값을 넣으면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688975814939&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@State private var userID: String = &quot;&quot; //@State로 TextField의 text값이 바뀔때마다 값이 바뀜
									   
TextField(&quot;ID&quot; , text: $userID)
        .fontWeight(.bold) //글씨체 두껍게
     	.padding() //주변 뷰들과 간격 벌리기
        .foregroundColor(.black) //글씨색깔 검정색
        .frame(maxWidth: .infinity) //폭넓이 최대
        .background(.bar) //배경색
        .cornerRadius(10) //모서리 둥글게
        .keyboardType(.emailAddress) //이메일 형식의 키보드 올라오게&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. &lt;b&gt;Password secured textField &lt;/b&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;(SecureField)&lt;/span&gt; : 입력되는 값이 가려지기 위해 SecureField를 쓴다. TextField와 마찬가지로 비었을 때 보여질값 , 바인딩 될 text 값을 넣으면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688976628681&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@State private var userPassword: String = &quot;&quot; //@State로 SecureField의 text값이 바뀔때마다 값이 바뀜
  
SecureField(&quot;PASSWORD&quot; , text: $userPassword)
        .fontWeight(.bold) //글씨체
        .padding() //버튼과의 간격
        .foregroundColor(.black) //글씨색깔
        .frame(maxWidth: .infinity) //폭넓이 최대
        .background(.bar) //배경색
        .cornerRadius(10) //모서리 둥글게&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. &lt;b&gt;Toggle&lt;/b&gt; &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;(Toggle)&lt;/span&gt; : Toggle도 작동하려면 TextField와 마찬가지로 바인딩 될 Bool값이 필요하다. isOn에 바인딩 값을 넣어주면 된다. Bool값이 false면 닫히고 true면 열린다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688977332058&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@State private var loginAgree: Bool = false //@State로 Toggle의 값이 바뀔때마다 값이 바뀜
HStack {
        Text(&quot;Agree to terms and conditions&quot;).font(.caption2)
        Toggle(isOn: $loginAgree) {
                            
        }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6. &lt;b&gt;Sign in Button&lt;/b&gt; &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;(Button)&lt;/span&gt; : 로그인 버튼이고 action과 label로 구현한다. action에는 버튼을 눌렀을때 이벤트 , label에는 버튼 UI를 나타낸다. 버튼을 눌렀을때 이메일 정규식이 맞고 로그인 동의가 되어야만 로그인 성공 메시지가 뜬다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688978391063&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@State private var message: String = &quot;&quot; //로그인 여부에 따라 보여질 메시지 값
@State private var isValidEmail: Bool = false  //이메일 형식 여부 값

Button {
        checkLogin() //로그인 함수                       
} label: {
        Text(&quot;Sign in&quot;)
        .fontWeight(.bold) //글씨체
        .foregroundColor(.white) //글씨색깔
        .frame(width : 300) //폭넓이
        .padding() //주변뷰들과 간격 넓힘
        .background(.blue) //배경 : 파랑색
        .cornerRadius(10) //모서리 둥글게
}

//이메일 정규표현식 확인하기 위한 함수
 func isValidEmailAddress(_ email: String) -&amp;gt; Bool { 
        let emailRegex = &quot;[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}&quot;
        //일반적인 이메일 주소 패턴
        
        let emailPredicate = NSPredicate(format: &quot;SELF MATCHES %@&quot;, emailRegex) 
        //NSPredicate를 이용하여 주어진 문자열이 자기 자신과 정규식 패턴과 일치하는지를 평가
        
        return emailPredicate.evaluate(with: email)
        //입력한 이메일이 위의 정규식과 일치 불일치를 Bool값
}

//로그인 함수
func checkLogin() {
        isValidEmail = isValidEmailAddress(userID) 
        //userID를 위 함수에 보내서 이메일 정규식이 맞는지 확인 맞으면 true , 틀리면 false
        
        if loginAgree == false { //로그인 동의 토글값이 false이면 
            message = &quot;로그인 동의를 해주세요&quot;
        } else if isValidEmail == false { //이메일 형식이 false이면
            message = &quot;이메일 형식이 아닙니다&quot;
        } else {
            message = &quot;아이디 : \(userID) 비밀번호 : \(userPassword)&quot;
        }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;구현영상&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;

            &lt;figure class=&quot;unsupported component-kakaotv&quot; contenteditable=&quot;false&quot; style=&quot;background:#000;margin:16px 0;min-height:72px;padding:10px 16px;display:flex;align-items:center;justify-content:center;text-align:center;box-sizing:border-box;width:100%;max-width:100%;&quot;&gt;
                &lt;p contenteditable=&quot;false&quot; style=&quot;margin:0;color:#8a8a8a;font-size:13px;line-height:1.6;user-select:none;pointer-events:none;&quot;&gt;동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.&lt;/p&gt;
            &lt;/figure&gt;
        
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;전체코드&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1688979919117&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ContentView: View {
    @State private var userID: String = &quot;&quot;
    @State private var userPassword: String = &quot;&quot;
    @State private var loginAgree: Bool = false
    @State private var message: String = &quot;&quot;
    @State private var isValidEmail: Bool = false
    var body: some View {
        NavigationView {
                   VStack {
                       Text(&quot;Introduce your credentials&quot;)
                       TextField(&quot;ID&quot; , text: $userID)
                               .fontWeight(.bold) //글씨체 두껍게
                               .padding() //주변 뷰들과 간격 벌리기
                               .foregroundColor(.black) //글씨색깔 검정색
                               .frame(maxWidth: .infinity) //폭넓이 최대
                               .background(.bar) //배경색
                               .cornerRadius(10) //모서리 둥글게
                               .keyboardType(.emailAddress) //이메일 형식의 키보드 올라오게
                       
                       SecureField(&quot;PASSWORD&quot; , text: $userPassword)
                               .fontWeight(.bold) //글씨체
                               .padding() //버튼과의 간격
                               .foregroundColor(.black) //글씨색깔
                               .frame(maxWidth: .infinity) //폭넓이 최대
                               .background(.bar) //배경색
                               .cornerRadius(10) //모서리 둥글게
                       
                       Spacer().frame(height : 30)
                       
                       HStack {
                               Text(&quot;Agree to terms and conditions&quot;).font(.caption2)
                               Toggle(isOn: $loginAgree) {
                                                   
                               }
                       }
                       
                       Spacer().frame(height : 30)
                       Button {
                               checkLogin() //로그인 함수
                       } label: {
                               Text(&quot;Sign in&quot;)
                               .fontWeight(.bold) //글씨체
                               .foregroundColor(.white) //글씨색깔
                               .frame(width : 300) //폭넓이
                               .padding() //주변뷰들과 간격 넓힘
                               .background(.blue) //배경 : 파랑색
                               .cornerRadius(10) //모서리 둥글게
                       }
                       
                       Spacer().frame(height : 30)
                       Text(&quot;\(message)&quot;)
                       Spacer()
                   }.navigationTitle(&quot;Log in&quot;).padding()
               }
    }
    
    //이메일 정규표현식 확인하기 위한 함수
     func isValidEmailAddress(_ email: String) -&amp;gt; Bool {
            let emailRegex = &quot;[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}&quot;
            //일반적인 이메일 주소 패턴
            
            let emailPredicate = NSPredicate(format: &quot;SELF MATCHES %@&quot;, emailRegex)
            //NSPredicate를 이용하여 주어진 문자열이 자기 자신과 정규식 패턴과 일치하는지를 평가
            
            return emailPredicate.evaluate(with: email)
            //입력한 이메일이 위의 정규식과 일치 불일치를 Bool값
    }

    //로그인 함수
    func checkLogin() {
            isValidEmail = isValidEmailAddress(userID)
            //userID를 위 함수에 보내서 이메일 정규식이 맞는지 확인 맞으면 true , 틀리면 false
            
            if loginAgree == false { //로그인 동의 토글값이 false이면
                message = &quot;로그인 동의를 해주세요&quot;
            } else if isValidEmail == false { //이메일 형식이 false이면
                message = &quot;이메일 형식이 아닙니다&quot;
            } else {
                message = &quot;아이디 : \(userID) \n비밀번호 : \(userPassword)&quot;
            }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>iOS 개발/SwiftUI</category>
      <category>ㅠ</category>
      <author>민궝</author>
      <guid isPermaLink="true">https://todayapp.tistory.com/32</guid>
      <comments>https://todayapp.tistory.com/32#entry32comment</comments>
      <pubDate>Thu, 6 Jul 2023 16:49:58 +0900</pubDate>
    </item>
    <item>
      <title>[Swift] 프로퍼티 옵저버</title>
      <link>https://todayapp.tistory.com/31</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;프로퍼티 옵저버(Property Observer) 란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: start;&quot;&gt;프로퍼티의 값이 변경될 때 특정 동작을 수행하는 기능으로 '&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;저장 프로퍼티&lt;/span&gt;&lt;/b&gt;'에 추가할 수 있다.&lt;/span&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f7f7f8; color: #111827; text-align: left;&quot;&gt;1. willSet : &lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: left;&quot;&gt;프로퍼티의 값이 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;변경되기 직전&lt;/span&gt;에 호출되는 옵저버 (주로 newValue와 함께 사용)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f7f7f8; color: #111827; text-align: left;&quot;&gt;2. didSet :&amp;nbsp; &lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: left;&quot;&gt;프로퍼티의 값이 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;변경된 후&lt;/span&gt;에 호출되는 옵저버 (주로 oldValue와 함께 사용)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1687172741977&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Counter {
    var value: Int {
        willSet(newValue) {
            print(&quot;값이 변경될 예정입니다: 현재 값: \(value), 변경될 값: \(newValue)&quot;)
        }
        didSet(oldValue) {
            print(&quot;값이 변경되었습니다: \(value), 변경되기 전 값: \(oldValue)&quot;)
        }
    }
    
    init() {
        self.value = 0
    }
    
    func increment() {
        value += 1
    }
}

let counter = Counter()
counter.increment()

// 값이 변경될 예정입니다: 현재 값: 0, 변경될 값: 1
// 값이 변경되었습니다: 1, 변경되기 전 값: 0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;순서&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;list-style-type: decimal; color: #000000;&quot;&gt;willSet 실행&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal; color: #000000;&quot;&gt;저장 프로퍼티 name 값 변경&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal; color: #000000;&quot;&gt;didSet 실행&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>Swift 이해/Swift 문법</category>
      <author>민궝</author>
      <guid isPermaLink="true">https://todayapp.tistory.com/31</guid>
      <comments>https://todayapp.tistory.com/31#entry31comment</comments>
      <pubDate>Mon, 19 Jun 2023 20:06:21 +0900</pubDate>
    </item>
    <item>
      <title>[SwiftUI] VStack</title>
      <link>https://todayapp.tistory.com/28</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: start;&quot;&gt;SwiftUI에서 VStack은 &lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;세로로 정렬된 뷰의 컨테이너&lt;/span&gt;&lt;/b&gt;입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: start;&quot;&gt;VStack은 &lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;Vertical Stack&lt;/span&gt;&lt;/b&gt;의 약자로, 포함된 뷰들을 위에서 아래로 쌓아 올리는 방식으로 레이아웃을 구성합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-18 오전 12.58.43.png&quot; data-origin-width=&quot;1674&quot; data-origin-height=&quot;674&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4MLbI/btskgHgF1c9/G0DkXKXMazXRqDmyKkbk3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4MLbI/btskgHgF1c9/G0DkXKXMazXRqDmyKkbk3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4MLbI/btskgHgF1c9/G0DkXKXMazXRqDmyKkbk3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4MLbI%2FbtskgHgF1c9%2FG0DkXKXMazXRqDmyKkbk3K%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;636&quot; height=&quot;256&quot; data-filename=&quot;스크린샷 2023-06-18 오전 12.58.43.png&quot; data-origin-width=&quot;1674&quot; data-origin-height=&quot;674&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SwiftUI 공식문서에 따르면 VStack은 &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;alignment&lt;/b&gt;&lt;/span&gt; , &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;spacing&lt;/b&gt;&lt;/span&gt; , &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;content&lt;/b&gt;&lt;/span&gt; 의 매개변수를 받을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1. alignment&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: left;&quot;&gt;기본적으로 VStack은 뷰들을 중앙 정렬합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: left;&quot;&gt;하지만 alignment 매개변수를 사용하여 다른 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;정렬 방식&lt;/span&gt;으로 변경할 수 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: left;&quot;&gt;예를 들어, &lt;b&gt;.leading, .trailing&lt;/b&gt;&amp;nbsp;등의 alignment 값을 지정할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #f7f7f8; color: #374151; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;.center&lt;/span&gt;: 뷰를 수직 방향으로 중앙 정렬합니다. 이는 &lt;b&gt;VStack의 기본 정렬 옵션&lt;/b&gt;입니다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;.leading&lt;/span&gt;: 뷰를 수직 방향으로 왼쪽 정렬합니다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;.trailing&lt;/span&gt;: 뷰를 수직 방향으로 오른쪽 정렬합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;코드를 통해 쉽게 알아보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatRight&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-19 오전 1.54.42.png&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;1004&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxAvOk/btskiABiFxw/7pWIlwFpVBcdP1ICnZhb9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxAvOk/btskiABiFxw/7pWIlwFpVBcdP1ICnZhb9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxAvOk/btskiABiFxw/7pWIlwFpVBcdP1ICnZhb9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxAvOk%2FbtskiABiFxw%2F7pWIlwFpVBcdP1ICnZhb9K%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;210&quot; height=&quot;412&quot; data-filename=&quot;스크린샷 2023-06-19 오전 1.54.42.png&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;1004&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1687107265716&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ContentView: View {
    var body: some View {
        VStack {
            VStack(alignment: .leading){
                Text(&quot;This&quot;)
                Text(&quot;leading&quot;)
            }.padding()  //왼쪽 정렬
            
            VStack(alignment: .trailing){
                Text(&quot;This&quot;)
                Text(&quot;trailing&quot;)
            }.padding()  //오른쪽 정렬
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2. spacing&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;spacing&lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: start;&quot;&gt;은 포함된 뷰 사이의 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;수직 간격&lt;/span&gt;을 포인트 단위로 정의합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: start;&quot;&gt;양수 값이면 뷰들 사이에 간격이 생성되고, 음수 값이면 뷰들이 서로 겹쳐질 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;코드를 통해 쉽게 알아보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatRight&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-19 오전 2.01.28.png&quot; data-origin-width=&quot;488&quot; data-origin-height=&quot;974&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbKiHw/btskgu9If4K/4ouM0fDUprtZ7Kw5u7c3OK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbKiHw/btskgu9If4K/4ouM0fDUprtZ7Kw5u7c3OK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbKiHw/btskgu9If4K/4ouM0fDUprtZ7Kw5u7c3OK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdbKiHw%2Fbtskgu9If4K%2F4ouM0fDUprtZ7Kw5u7c3OK%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;227&quot; height=&quot;453&quot; data-filename=&quot;스크린샷 2023-06-19 오전 2.01.28.png&quot; data-origin-width=&quot;488&quot; data-origin-height=&quot;974&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1687107767219&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ContentView: View {
    var body: some View {
        VStack(spacing: 0) { 
            Text(&quot;View 1&quot;)
                .padding()
                .background(Color.blue)
            
            Text(&quot;View 2&quot;)
                .padding()
                .background(Color.red)
            
            Text(&quot;View 3&quot;)
                .padding()
                .background(Color.green)
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;spacing값이&amp;nbsp;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;0 일땐 뷰들이 간격없이 붙어있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatRight&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-19 오전 2.01.48.png&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;962&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/euMtJw/btskrczC5EW/aZCoqBuyEvfork4L0Yc9YK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/euMtJw/btskrczC5EW/aZCoqBuyEvfork4L0Yc9YK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/euMtJw/btskrczC5EW/aZCoqBuyEvfork4L0Yc9YK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeuMtJw%2FbtskrczC5EW%2FaZCoqBuyEvfork4L0Yc9YK%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;109&quot; height=&quot;216&quot; data-filename=&quot;스크린샷 2023-06-19 오전 2.01.48.png&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;962&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1687107830626&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; VStack(spacing: 50)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: right;&quot; data-ke-size=&quot;size16&quot;&gt;-spacing값이 50일때&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatRight&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-19 오전 2.02.08.png&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;986&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNoaSJ/btsknughOoD/8NGB0o41k95y2BbEXUskMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNoaSJ/btsknughOoD/8NGB0o41k95y2BbEXUskMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNoaSJ/btsknughOoD/8NGB0o41k95y2BbEXUskMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNoaSJ%2FbtsknughOoD%2F8NGB0o41k95y2BbEXUskMK%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;109&quot; height=&quot;215&quot; data-filename=&quot;스크린샷 2023-06-19 오전 2.02.08.png&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;986&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1687107914274&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; VStack(spacing: -30)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: right;&quot; data-ke-size=&quot;size16&quot;&gt;-spacing값이 -30일때&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;3. content&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt; content는&lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: start;&quot;&gt; View &lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: start;&quot;&gt;를 포함하고 배치하는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;컨테이너 역할&lt;/span&gt;을 합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: start;&quot;&gt;alignment의 .center처럼 기본으로 설정돼있어 써주지 않아도 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: start;&quot;&gt;코드로 알아보겠습니다.&lt;/span&gt;&lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatRight&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-19 오전 2.17.25.png&quot; data-origin-width=&quot;488&quot; data-origin-height=&quot;980&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byql0i/btskuXWuaHA/NiplyMOtss3fKiHiqpqtmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byql0i/btskuXWuaHA/NiplyMOtss3fKiHiqpqtmK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byql0i/btskuXWuaHA/NiplyMOtss3fKiHiqpqtmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbyql0i%2FbtskuXWuaHA%2FNiplyMOtss3fKiHiqpqtmK%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;241&quot; height=&quot;484&quot; data-filename=&quot;스크린샷 2023-06-19 오전 2.17.25.png&quot; data-origin-width=&quot;488&quot; data-origin-height=&quot;980&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1687108616998&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ContentView: View {
    var body: some View {
        VStack {
            Text(&quot;Hello, world!&quot;)
            .padding()
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1687108690330&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ContentView: View {
    var body: some View {
        VStack(alignment: .center, content: {
            Text(&quot;Hello, world!&quot;)
                .padding()
        })
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드는 결과적으로 아래코드랑 같은 코드입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VStack에 기본으로 설정돼있기 때문에 굳이 써주지 않아도 되기 때문입니다.&amp;nbsp;&lt;/p&gt;</description>
      <category>iOS 개발/SwiftUI</category>
      <author>민궝</author>
      <guid isPermaLink="true">https://todayapp.tistory.com/28</guid>
      <comments>https://todayapp.tistory.com/28#entry28comment</comments>
      <pubDate>Mon, 19 Jun 2023 02:21:33 +0900</pubDate>
    </item>
    <item>
      <title>[Swift] instance , type 메서드 차이와 class , struct , enum 차이</title>
      <link>https://todayapp.tistory.com/27</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  &lt;b&gt;instance, class , static 메서드&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1686475555251&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class ExampleClass{

  func instanceMethod(){
    print(&quot;instance 메서드&quot;)
  }   // instance 메서드
  
  class func classMethod(){
     print(&quot;class 메서드&quot;)
  } // class 메서드 
  
  static func staticMethod(){
     print(&quot;static 메서드&quot;)
  } // static 메서드 
  
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;  class메서드와 instance메서드 차이&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1686476293513&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let instance: ExampleClass = ExampleClass()
instance.instanceMethod() // Result : instance 메서드

ExampleClass.classMethod() // Result : class 메서드&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;instance메서드&lt;/span&gt;:&amp;nbsp; 실체화 즉, 인스턴스를 생성해야 사용 가능합니다&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;class메서드&lt;/span&gt; :&amp;nbsp; 인스턴스 생성하지 않고 직접 호출 가능합니다&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;  &lt;b&gt;class메서드와  static메서드 차이&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1686476874203&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ExampleClass.classMethod() // Result : class 메서드
ExampleClass.staticMethod()// Result : static 메서드&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;class메서드와 static메서드는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;타입 메서드&lt;/span&gt;라 부릅니다&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;타입 메서드는 위 코드처럼&amp;nbsp;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;인스턴스 생성하지 않고 직접 호출 가능&lt;/span&gt;합니다&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;그래서 이 코드에선 둘의 차이점을 찾을 수 없습니다&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;class메서드&lt;/span&gt; : sub class에서 override가 가능합니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;static메서드&lt;/span&gt; : sub class에서 override 할 수 없습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ZMGNdrZaN1g&amp;amp;list=PLgOlaPUIbynoqbQw_erl3L2w7vfOTCtFD&amp;amp;index=34&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.youtube.com/watch?v=ZMGNdrZaN1g&amp;amp;list=PLgOlaPUIbynoqbQw_erl3L2w7vfOTCtFD&amp;amp;index=34&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=ZMGNdrZaN1g&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/znk2w/hySW0GtV2W/4kkvHTXBWGpPU3CjZryBdK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-original-url=&quot;&quot; data-video-title=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/ZMGNdrZaN1g&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #0f0f0f; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;공통점&lt;/span&gt; : 메모리에 올리지 않고 사용할 수 있다&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #0f0f0f; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;차이점&lt;/span&gt; : static에는 final이라는 의미가 포함되어있어 오버라이드가 불가능함&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;  struct란?&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0f0f0f; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;class&lt;/span&gt; : 공유해서 사용하는 개념. 참조하는 값이 바뀌면 기존 값도 바뀜!&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0f0f0f; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;struct&lt;/span&gt; : 복사해서 사용하는 개념. 참조하는 값이 바뀌어도 기존 값에는 영향이 없음! &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0f0f0f; text-align: start;&quot;&gt;사용처 : 데이터 모델에 주로 사용!&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #0f0f0f; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1686561126207&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* Value Type */
struct testStruct {
  var name = &quot;&quot;
  var age = 0
}

/* Reference Type */
class testClass {
  var name = &quot;&quot;
  var age = 0
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;878&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFb16J/btsjx3ZDBSN/5YBdzTNqJ55b01JJBiqpY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFb16J/btsjx3ZDBSN/5YBdzTNqJ55b01JJBiqpY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFb16J/btsjx3ZDBSN/5YBdzTNqJ55b01JJBiqpY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFb16J%2Fbtsjx3ZDBSN%2F5YBdzTNqJ55b01JJBiqpY0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;727&quot; height=&quot;499&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;878&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &amp;nbsp;&lt;b&gt;class , struct , enum 의 차이&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 169px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;class&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;struct&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;enum&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;확장(extention)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;O&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;O&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;O&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;프로퍼티,메소드&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;O&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;O&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;O&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;상속&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;O&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;X&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;X&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;저장 프로퍼티&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;O&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;O&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;X&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;초기화(init) 함수&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;O&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;O&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;X&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; text-align: center; height: 19px;&quot;&gt;&lt;b&gt;타입 메소드&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; text-align: center; height: 19px;&quot;&gt;&lt;b&gt;O&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; text-align: center; height: 19px;&quot;&gt;&lt;b&gt;X&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; text-align: center; height: 19px;&quot;&gt;&lt;b&gt;X&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;타입(Type)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;reference&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;value&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;value&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; text-align: center; height: 19px;&quot;&gt;&lt;b&gt;메모리(Memory)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; text-align: center; height: 19px;&quot;&gt;&lt;b&gt;heap&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; text-align: center; height: 19px;&quot;&gt;&lt;b&gt;stack&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; text-align: center; height: 19px;&quot;&gt;&lt;b&gt;stack&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;코드로 보는 reference타입과 value타입의 차이&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1686475020570&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//구초체 예제
struct exStruct {
    var name: String = &quot;구조체&quot;
    
    func hello() {
        print(&quot;\(name)&quot;)
    }
    
}
//구조체는 값 타입이기 때문에 let으로 하면 프로퍼티값 변경 불가
var stc: exStruct = exStruct() 
stc.name = &quot;구조체 입니다&quot;
stc.hello()


//클래스 예제
class exClass {
    var name: String = &quot;클래스&quot;
    
    
    func hello() {
        print(&quot;\(name)&quot;)
    }
    
}

//클래스는 참조 타입이기 때문에 let으로 해도 프로퍼티값 변경 가능
let cls: exClass = exClass()
cls.name = &quot;클래스 입니다&quot;
cls.hello()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Swift 이해/Swift 이해하기</category>
      <author>민궝</author>
      <guid isPermaLink="true">https://todayapp.tistory.com/27</guid>
      <comments>https://todayapp.tistory.com/27#entry27comment</comments>
      <pubDate>Sun, 11 Jun 2023 16:42:37 +0900</pubDate>
    </item>
    <item>
      <title>[CS] 교착상태와 기아상태</title>
      <link>https://todayapp.tistory.com/26</link>
      <description>&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;  &lt;span style=&quot;color: #000000;&quot;&gt;교착상태 (DeadLock)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;교착상태와-교착상태-해결방법에-대해서-설명해주세요&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;면접 질문&lt;/b&gt; :&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;교착상태&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;와&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;교착상태 해결방법&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;에 대해서 설명해주세요.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;교착상태 발생조건&lt;/b&gt;&lt;/span&gt;에 무엇이 있는지 얘기해주세요.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&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 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;1. 두 개 이상의 프로세스가 자원을 점유한 상태(멀티 프로그래밍 환경)에서 서로 원하는 자원을 얻기 위해 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;무한정한 기다림 상태&lt;/b&gt;&lt;/span&gt;에 빠지는 것입니다. &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;이에 대한 해결방법은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;예방&lt;span style=&quot;color: #212529; text-align: left;&quot;&gt;,&amp;nbsp;&lt;/span&gt;회피&lt;span style=&quot;color: #212529; text-align: left;&quot;&gt;,&amp;nbsp;&lt;/span&gt;탐지&lt;span style=&quot;color: #212529; text-align: left;&quot;&gt;&amp;nbsp;및&amp;nbsp;&lt;/span&gt;회복&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;이 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;상호배제&lt;/b&gt;&lt;/span&gt; , &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;점유와 대기&lt;/b&gt;&lt;/span&gt; , &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;비선점&lt;/b&gt;&lt;/span&gt; , &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;순환대기&lt;/b&gt;&lt;/span&gt;가 있으며 &lt;b&gt;4가지 조건 모두 성립&lt;/b&gt;해야 교착상태가 발생 할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  교착상태란 ?&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;두 개 이상의 프로세스가 서로의 작업이 끝나기만을 기다리고 있어 둘 다 영원히 끝나지 않는 상황&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;= &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;데드락(DeadLock)&lt;/b&gt;&lt;/span&gt; 이라고도 함&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;806&quot; data-origin-height=&quot;398&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3Nmsi/btsjmwmd1Fc/x8NynkOrYmwOkyDxuINEB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3Nmsi/btsjmwmd1Fc/x8NynkOrYmwOkyDxuINEB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3Nmsi/btsjmwmd1Fc/x8NynkOrYmwOkyDxuINEB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3Nmsi%2Fbtsjmwmd1Fc%2Fx8NynkOrYmwOkyDxuINEB0%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;617&quot; height=&quot;305&quot; data-origin-width=&quot;806&quot; data-origin-height=&quot;398&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  교착상태 발생조건&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아래 4가지 조건이 모두 만족되는 경우 데드락이&amp;nbsp;&lt;b&gt;발생할 가능성&lt;/b&gt;이 있다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;rarr; &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;하나라도 만족하지 않으면 발생하지 않음&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;상호 배제 (Mutual exclusion)&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;한 번에 프로세스 하나만 해당 자원을 사용할 수 있다 (자원 = 임계영역)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용 중인 자원을 다른 프로세스가 사용하려면 요청한 자원이 해제될 때까지 기다려야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ex) &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;한 개의 화장실을 한 개의 키를 갖고 여러명이서 사용하려 할 때&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;점유와 대기(Hold and wait)&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자원을 최소한 하나 보유하고, 다른 프로세스에 할당된 자원을 점유하기 위해 대기하는 프로세스가 존재해야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ex) &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;인원이 한정된 오마카세를 먹고 있음과 동시에 유명 카페를 테이블링 할 때&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비선점 (No preemption)&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이미 할당된 자원을 강제로 빼앗을 수 없다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로세스가 작업을 마친 후 자원을 자발적으로 반환할 때까지 기다려야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ex) &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;가득 찬 피팅룸을 사용하려 할 때&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;순환대기 (Circular wait)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: left;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;대기 프로세스의 집합이 순환 형태로 자원을 대기하고 있어야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;Hold and wait 관계의 프로세스들이 서로를 기다림&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;ex) &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;4개의 교차로의 좌회전 신호 대기 중인 차들&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  교착상태 해결방법&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데드락이 발생하지 않도록&amp;nbsp;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;예방&lt;/b&gt;(prevention)&lt;/span&gt; 하기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데드락 발생 가능성을 인정하면서도 적절하게&amp;nbsp;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;회피&lt;/b&gt;(avoidance)&lt;/span&gt; 하기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데드락 발생을 허용하지만 데드락을&amp;nbsp;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;탐지&lt;/b&gt;(detection)&lt;/span&gt;하여,&amp;nbsp;데드락에서&lt;b&gt; &lt;span style=&quot;background-color: #9feec3;&quot;&gt;회복&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;(Recovery)&lt;/span&gt;하기&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;1️⃣-예방-prevention&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1️⃣&amp;nbsp; &lt;b&gt;예방 (Prevention)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f8f9fa; color: #000000; text-align: start;&quot;&gt;교착 상태가 발생하기 전에 미리 조치를 취하는 방식으로, 교착 상태 발생 조건 중 하나를 제거함으로써 해결한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;상호 배제 조건 방지&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 자원을 공유 허용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;점유와 대기 조건 방지&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 자원에 대해 선점 허용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비선점 조건 방지&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;필요 자원을 한번에 할당&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;순환 대기 조건 방지&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자원에게 순서 부여를 통해 프로세스 순서의 증가 방향으로만 자원 요청&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; background-color: #c1bef9;&quot;&gt;&lt;b&gt;단점 : 자원낭비가 심함&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;2️⃣-회피-avoidance&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2️⃣&lt;span&gt; &amp;nbsp;&lt;/span&gt;&lt;b&gt;회피 (Avoidance)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f8f9fa; color: #212529; text-align: start;&quot;&gt;프로세스가 자원을 요구할 때, 시스템은 자원을 할당한 후에도 안정 상태로 남아있는가를 확인하여 교착 상태를 회피하는 방법&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;546&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bATeqe/btsjwqZybgE/RJpPwtnuFwH5zSe8Ae0puk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bATeqe/btsjwqZybgE/RJpPwtnuFwH5zSe8Ae0puk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bATeqe/btsjwqZybgE/RJpPwtnuFwH5zSe8Ae0puk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbATeqe%2FbtsjwqZybgE%2FRJpPwtnuFwH5zSe8Ae0puk%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;401&quot; height=&quot;313&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;546&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;교착상태가 발생할 가능성을 배제하지 않고 교착상태가 발생하면 적절히 피해나가는 방법이다.&lt;/li&gt;
&lt;li&gt;리소스 할당의 측면에서, 교착상태가 발생할 가능성이 있는 자원 할당(unsafe allocation)을 하지 않는다.&lt;/li&gt;
&lt;li&gt;주로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;은행원 알고리즘(Banker's Algorithm)&lt;/b&gt;&lt;/span&gt;이 사용된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #c1bef9; color: #000000;&quot;&gt;&lt;b&gt;단점 : 오버헤드 발생&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;은행원 알고리즘&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;은행원 알고리즘은 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;다익스트라&lt;/span&gt;가 제안한 기법으로, 은행에서 모든 고객의 요구가 충족되도록 현금을 할당하는데서 유래한 기법&lt;/li&gt;
&lt;li&gt;각 프로세스에게 자원을 할당하여 교착상태가 발생하지 않으며 모든 프로세스가 완료될 수 있는 상태는&lt;span&gt;&amp;nbsp;&lt;/span&gt;안전상태, 교착상태가 발생할 수 있는 상태는&lt;span&gt;&amp;nbsp;&lt;/span&gt;불안전 상태&lt;span&gt;&amp;nbsp;&lt;/span&gt;라고 한다.&lt;/li&gt;
&lt;li&gt;은행원 알고리즘을 적용하기 위해서는 자원의 양과 사용자(프로세스) 수가 일정해야 한다.&lt;/li&gt;
&lt;li&gt;은행원 알고리즘은 프로세스의 모든 요구를 유한한 시간안에 할당하는 것을 보장한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1686466853896&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import Foundation

class Bank {
    var available: Bool = true // 은행원의 사용 가능 여부
    
    let queue: DispatchQueue = DispatchQueue(label: &quot;bankQueue&quot;) // 공유 자원에 대한 동시 액세스를 관리하기 위한 큐
    
    func deposit(amount: Int) {
        queue.sync {
            guard available else {
                print(&quot;은행원이 사용 중입니다. 대기해주세요.&quot;)
                return
            }
            
            available = false
            print(&quot;입금 처리 중...&quot;)
            // 입금 작업 수행
            Thread.sleep(forTimeInterval: 2)
            print(&quot;입금 완료.&quot;)
            
            available = true
        }
    }
    
    func withdraw(amount: Int) {
        queue.sync {
            guard available else {
                print(&quot;은행원이 사용 중입니다. 대기해주세요.&quot;)
                return
            }
            
            available = false
            print(&quot;인출 처리 중...&quot;)
            // 인출 작업 수행
            Thread.sleep(forTimeInterval: 2)
            print(&quot;인출 완료.&quot;)
            
            available = true
        }
    }
}

// 테스트
let bank = Bank()

DispatchQueue.concurrentPerform(iterations: 10) { index in
    let randomAmount = Int.random(in: 100...1000)
    
    if index % 2 == 0 {
        print(&quot;프로세스 \(index): \(randomAmount)원 입금 시도&quot;)
        bank.deposit(amount: randomAmount)
    } else {
        print(&quot;프로세스 \(index): \(randomAmount)원 인출 시도&quot;)
        bank.withdraw(amount: randomAmount)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 id=&quot;1️⃣-예방-prevention&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3️⃣&amp;nbsp;&lt;span&gt; &lt;b&gt;탐지&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;(Detection)&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f8f9fa; color: #212529; text-align: start;&quot;&gt;데드락이 발생하면 빠르게 발견하고 문제를 해결하는 것&lt;/span&gt;&lt;span style=&quot;background-color: #f8f9fa; color: #212529; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템에 교착상태가 발생했는지 점검하여 교착상태에 있는 프로세스와 자원을 발견한다.&lt;/li&gt;
&lt;li&gt;교착상태 발견 알고리즘과 자원 할당 그래프 등을 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;263&quot; data-origin-height=&quot;338&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r1l6T/btsjna4nteC/lTySUhqbMrfwmqI29ypAy1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r1l6T/btsjna4nteC/lTySUhqbMrfwmqI29ypAy1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r1l6T/btsjna4nteC/lTySUhqbMrfwmqI29ypAy1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr1l6T%2Fbtsjna4nteC%2FlTySUhqbMrfwmqI29ypAy1%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;181&quot; height=&quot;233&quot; data-origin-width=&quot;263&quot; data-origin-height=&quot;338&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #c1bef9; color: #000000;&quot;&gt;&lt;b&gt;단점 : &lt;span style=&quot;background-color: #c1bef9; text-align: left;&quot;&gt;자원을 요청할 때마다 탐지 알고리즘을 실행하면, 오버헤드가 발생&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;1️⃣-예방-prevention&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;4️⃣ &lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;회복&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;(&lt;b&gt;Recovery&lt;/b&gt;)&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f8f9fa; color: #212529; text-align: start;&quot;&gt;교착 상태를 일으킨 프로세스를 종료하거나 할당된 자원을 해제하면서 회복&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 프로세스 종료 방법&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;교착 상태의 프로세스 모두 중지&lt;/li&gt;
&lt;li&gt;교착 상태가 제거될 때까지 한 프로세스씩 중지&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 자원 선점 방법&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자원을 빼앗긴 프로세스는 강제 종류 이후 재시작&lt;/li&gt;
&lt;li&gt;교착 상태에 빠진 프로세스가 필요로 하는 자원을 강제로 가져옴&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기아상태 (Starvation)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;면접 질문&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;:&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;교착상태&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;와&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;기아상태의 차이점&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;에 대해서 설명해주세요.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&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;size16&quot;&gt;&lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: start;&quot;&gt;교착상태와 기아상태는 둘 다 다중 프로세스 환경에서 발생하는 문제지만, &lt;span style=&quot;background-color: #f7f7f8; color: #374151; text-align: start;&quot;&gt;교착상태는 자원의 순환 대기와 관련된 조건을 충족하며 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;시스템 전체적으로 발생하는 문제&lt;/b&gt;&lt;/span&gt;이며, 기아상태는 특정 프로세스가 &lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;자원에 접근할 수 없는 상태&lt;/span&gt;&lt;/b&gt;로 인해 발생하는 문제입니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  기아상태란 ?&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;특정 프로세스보다 우선순위가 낮아 원하는 자원을 계속 할당받지 못해 &lt;/span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;자원을 무기한으로 기다리는 상황&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  기아상태 발생조건&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;교착상태의 비선점 현상이 계속된다면 기아상태가 된다. (내피셜)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  기아상태 해결방법&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; background-color: #f6e199;&quot;&gt;에이징(Aging) 기법&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #000000; text-align: left;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기아상태를 회피하기 위해 낮은 우선순위를 가진 프로세스들을 기다린 만큼 우선순위를 높여주는 방법이다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;아무리 우선순위가 낮은 대상이라도 그 대상을 기다리는 다른 대상이 있을 수 있으니 늦게라도 자원이 할당되어 처리되도록 해야 한다. &lt;span style=&quot;background-color: #9feec3;&quot;&gt;대기시간에 비례하여 우선순위를 부여함&lt;/span&gt;으로써 기아 현상을 방지한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;ex) 피팅룸 사용시 자리가 꽉 찼을 때 직원이 먼저 온 사람들 순서대로 대기표를 부여하는 것&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS</category>
      <author>민궝</author>
      <guid isPermaLink="true">https://todayapp.tistory.com/26</guid>
      <comments>https://todayapp.tistory.com/26#entry26comment</comments>
      <pubDate>Sun, 11 Jun 2023 14:46:21 +0900</pubDate>
    </item>
    <item>
      <title>[CS] 세마포어와 뮤텍스</title>
      <link>https://todayapp.tistory.com/25</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;여러 개의 프로세스가 동시에 실행할 수 있는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;멀티 코어 시스템&lt;/span&gt;은 시스템의 성능 향상을 가져왔지만 동시에 &quot;프로세스 간의 공유 자원 접근 관리&quot;라는 문제를 가져왔습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;즉, 공유된 자원에 여러 프로세스 혹은 쓰레드가 동시에 접근하면서 문제가 발생하는데 이렇게 다수의 컴포넌트가 공유 중인 자원을 동시에 읽거나 수정할 때 생기는 문제를 &quot;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;동기화 문제&lt;/span&gt;&quot;라고 하며 이러한 문제는 스핀락, 뮤텍스, 세마포어를 통해서 해결할 수 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;동기화(Synchronization)&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 프로세스나 쓰레드가 공유하는&amp;nbsp;&lt;b&gt;자원의 일관성을 유지&lt;/b&gt;하는 것&lt;/li&gt;
&lt;li&gt;여러 프로스세나 쓰레드가 동시에 하나의 자원에 접근할 때 접근 순서를 정해 일관성을 유지해준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;&lt;b&gt;&lt;b&gt;임계 영역(Critical Section)&lt;/b&gt;&lt;/b&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 프로세스가 데이터를 공유하며 수행될 때,&amp;nbsp;&lt;b&gt;각 프로세스에서 공유 데이터를 접근하는 프로그램 코드 블록&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;임계 영역은 작업들이 리소스를 같이 사용할 수 있는 공유 자원이 있는 곳이므로 한 작업이 자원을 점유하면, 다른 자원은 리소스를 점유한 작업이 종료될 때까지 기다려야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;203&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uJ9Lt/btsi2f6I91u/o1IuA0loOOWQzaJb4CnLKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uJ9Lt/btsi2f6I91u/o1IuA0loOOWQzaJb4CnLKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uJ9Lt/btsi2f6I91u/o1IuA0loOOWQzaJb4CnLKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuJ9Lt%2Fbtsi2f6I91u%2Fo1IuA0loOOWQzaJb4CnLKK%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;400&quot; height=&quot;203&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;203&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;&lt;b&gt;교착 상태(Dead Lock)&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; 두 가지 이상의 작업이 서로 상대방의 작업이 끝나기를 하염없이 기다리는 상태를 말한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;교착 상태가 발생하려면 아래의 4가지 조건을 모두 만족해야만 한다
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;상호 배제&lt;/b&gt;&lt;/span&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;li&gt;&lt;b&gt;순환 대기&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled (1).png&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;457&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5WrLm/btsi5sDubu4/gysZhG5wbtP89fQfSJ1fX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5WrLm/btsi5sDubu4/gysZhG5wbtP89fQfSJ1fX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5WrLm/btsi5sDubu4/gysZhG5wbtP89fQfSJ1fX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5WrLm%2Fbtsi5sDubu4%2FgysZhG5wbtP89fQfSJ1fX1%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;728&quot; height=&quot;457&quot; data-filename=&quot;Untitled (1).png&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;457&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;&lt;b&gt;&lt;b&gt;상호 배제 (Mutal Exclusion)&lt;/b&gt;&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; 임계 구역을 어느 시점에서 단지 한 개의 프로세스만이 사용할 수 있도록 하며, 다른 프로세스가 현재 사용 중인 임계 구역에 대해 접근하려고 할 때 이를 금지하는 행위&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled (2).png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;493&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFM9zh/btsi5tvBRfJ/lOQ3kCp46NuqHlp9peBb0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFM9zh/btsi5tvBRfJ/lOQ3kCp46NuqHlp9peBb0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFM9zh/btsi5tvBRfJ/lOQ3kCp46NuqHlp9peBb0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFM9zh%2Fbtsi5tvBRfJ%2FlOQ3kCp46NuqHlp9peBb0K%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;1280&quot; height=&quot;493&quot; data-filename=&quot;Untitled (2).png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;493&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled (3).png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;531&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PNPOE/btsi3YbNzda/2geWJcCKKnD2DKnYviJRuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PNPOE/btsi3YbNzda/2geWJcCKKnD2DKnYviJRuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PNPOE/btsi3YbNzda/2geWJcCKKnD2DKnYviJRuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPNPOE%2Fbtsi3YbNzda%2F2geWJcCKKnD2DKnYviJRuk%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;1280&quot; height=&quot;531&quot; data-filename=&quot;Untitled (3).png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;531&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 중에서 상호 배제 조건을 해결하기 위해 등장한 방법이 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;뮤텍스(Mutex)와 세마포어(Semaphore)&lt;/span&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;세마포어(Semaphore)&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;멀티프로그래밍 환경에서 다수의 프로세스나 스레드의 여러 개의 공유 자원에 대한 접근을 제한하기 위해 사용되는 동기화 기법&lt;/li&gt;
&lt;li&gt;공유된 자원의 데이터&amp;nbsp;혹은 임계영역등에&amp;nbsp;&lt;b&gt;여러&lt;/b&gt;&amp;nbsp;&lt;b&gt;프로세스 혹은 스레드&lt;/b&gt;가 접근하는 것을&amp;nbsp;막아줌(즉, 동기화 대상이 하나 이상)&lt;/li&gt;
&lt;li&gt;세마포어에서 잠금이 해제되길 기다리는 프로세스는 세마포어 큐에 저장되어 있다가, 신호를 받으면 큐에서 나와 임계 구역에 진입한다&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled (4).png&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;628&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQ48gy/btsi4bWuuNW/0TqWXHSpnkAdujkfwEzLy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQ48gy/btsi4bWuuNW/0TqWXHSpnkAdujkfwEzLy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQ48gy/btsi4bWuuNW/0TqWXHSpnkAdujkfwEzLy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQ48gy%2Fbtsi4bWuuNW%2F0TqWXHSpnkAdujkfwEzLy1%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;882&quot; height=&quot;628&quot; data-filename=&quot;Untitled (4).png&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;628&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버에 프린터기 다섯대가 물려있다고 치자. 사용자가 프린트를 사용하려고 서버에 요청을 보냈다. 그러면 공유자원 즉 프린터가 5개 있으니까 세마포어는 처음에 5로 설정된다. 그리고 프린터를 사용자가 사용할 때마다 하나씩 세마포어가 감소된다. 그러다가 사용할 프린터가 없어지면 세마포어는 조만간 0이 되고, 다 쓰고 반환하면 세마포어는 다시 +1 증가한다. 이런식으로 생각하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  세마포어(Semaphore) 접근 함수 : wait(), signal()&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 위해 제공되는 함수가 wait()과 signal() 이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;  P(wait)&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;/li&gt;
&lt;li&gt;세마포어 값을 감소시킨다&lt;/li&gt;
&lt;li&gt;세마포어 값이 0보다 작으면 기다린다 -&amp;gt; wait&lt;/li&gt;
&lt;li&gt;세마포어 값이 0보다 크거나 같으면 리턴한다 -&amp;gt; 프로세스가 임계 구역에 진입 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;  V(signal)&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;/li&gt;
&lt;li&gt;세마포어 값을 증가시킨다&lt;/li&gt;
&lt;li&gt;대기 중인 프로세스를 깨운다&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;뮤텍스(Mutex)&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한 쓰레드 또는 프로세스에 의해 소유될 수 있는 Key를 기반으로 한 상호 배제 기법&lt;/li&gt;
&lt;li&gt;공유된 자원의 데이터 혹은 임계영역등에&amp;nbsp;&lt;b&gt;하나의&lt;/b&gt;&amp;nbsp;&lt;b&gt;프로세스 혹은 스레드&lt;/b&gt;가 접근하는 것을 막아줌(즉, 동기화 대상이 하나)&lt;/li&gt;
&lt;li&gt;임계구역을 가진 쓰레드들의 실행시간이 서로 겹치지 않고 각각 단독으로 실행 (상호배제) 되도록 하는 기술&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled (5).png&quot; data-origin-width=&quot;986&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coApkD/btsi3p8y9Js/vaL1uOp8QbA1UPAjPmkFM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coApkD/btsi3p8y9Js/vaL1uOp8QbA1UPAjPmkFM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coApkD/btsi3p8y9Js/vaL1uOp8QbA1UPAjPmkFM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoApkD%2Fbtsi3p8y9Js%2FvaL1uOp8QbA1UPAjPmkFM0%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;986&quot; height=&quot;426&quot; data-filename=&quot;Untitled (5).png&quot; data-origin-width=&quot;986&quot; data-origin-height=&quot;426&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  뮤텍스(&lt;b&gt;Mutex&lt;/b&gt;) 접근 함수 : lock(), unlock()&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;  lock()&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;/li&gt;
&lt;li&gt;만약 다른 프로세스/스레드가 lock을 잡고 있다면 lock을 놓아줄 때까지 대기한다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;  unlock()&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;/li&gt;
&lt;li&gt;unlock을 호출하면 lock을 기다리던 다른 프로세스/스레드 들이 lock을 잡을 수 있다&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;size16&quot;&gt;뮤텍스와 세마포어의 이해하기 쉬운 예시&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://worthpreading.tistory.com/90&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://worthpreading.tistory.com/90&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1686135305734&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;뮤텍스(Mutex)와 세마포어(Semaphore)의 차이&quot; data-og-description=&quot;이 글은 Medium에 개시된 글입니다. Medium에서 보시면 좀 더 유쾌한 환경에서 글을 보실 수 있습니다. 뮤텍스(Mutex)와 세마포어(Semaphore)의 차이 Toilet problem 동시성 프로그래밍의 가장 큰 숙제는 &amp;lsquo;공&quot; data-og-host=&quot;worthpreading.tistory.com&quot; data-og-source-url=&quot;https://worthpreading.tistory.com/90&quot; data-og-url=&quot;https://worthpreading.tistory.com/90&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bINkTS/hySVEol6nA/Jd9CsRlAm8Kkh2WPjrYOz0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bSQXj4/hySTL3I3HY/gdUQpJjbMLnpuobXG3um2k/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bNhyMG/hySTSV4FIt/XYHcNfbJkfY1nMGnZkMfqk/img.png?width=1150&amp;amp;height=726&amp;amp;face=0_0_1150_726&quot;&gt;&lt;a href=&quot;https://worthpreading.tistory.com/90&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://worthpreading.tistory.com/90&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bINkTS/hySVEol6nA/Jd9CsRlAm8Kkh2WPjrYOz0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bSQXj4/hySTL3I3HY/gdUQpJjbMLnpuobXG3um2k/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bNhyMG/hySTSV4FIt/XYHcNfbJkfY1nMGnZkMfqk/img.png?width=1150&amp;amp;height=726&amp;amp;face=0_0_1150_726');&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;뮤텍스(Mutex)와 세마포어(Semaphore)의 차이&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 글은 Medium에 개시된 글입니다. Medium에서 보시면 좀 더 유쾌한 환경에서 글을 보실 수 있습니다. 뮤텍스(Mutex)와 세마포어(Semaphore)의 차이 Toilet problem 동시성 프로그래밍의 가장 큰 숙제는 &amp;lsquo;공&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;worthpreading.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;&lt;b&gt;  뮤텍스와 세마포어 차이점&lt;/b&gt;&lt;/h1&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1️⃣ 동기화 대상의 개수&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Mutex는 동기화 대상이 only 1개 일 때 사용한다.&lt;/li&gt;
&lt;li&gt;Semaphore는 동기화 대상이 1개 이상일 때 사용한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;세마포어는 세마포어의 변수 개수만큼의 프로세스/스레드가 공유 자원에 접근할 수있다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;세마포어는 세마포어 변수 값만큼의 공유자원이 존재하고, 각 공유자원 당 하나의 스레드가 접근이 가능하다&lt;/li&gt;
&lt;li&gt;즉, 한 번에 세마포어 변수 개수만큼 각 공유자원에 스레드가 접근이 가능하다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;반면, 뮤텍스는 오직 1개의 프로세스 또는 스레드만 공유자원에 접근할 수 있다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;뮤텍스는 공유 자원이 1개이다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2️⃣ 세마포어는 뮤텍스가 될 수 있지만, 뮤텍스는 세마포어가 될 수 없다.&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;Mutex는 0, 1로 이루어진 이진 상태를 가지므로, Binary Semaphore이라고도 불린다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3️⃣ 자원 소유에 차이가 있다.&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;뮤텍스는 자원 소유가 가능하고 책임을 갖는다. (상태가 0과 1뿐이므로 Lock 가질 수 있음)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;lock : 현재 임계구역에 들어갈 권한을 얻어옴 (만약 다른 쓰레드/프로세스가 임계구역 수행중이면, 종료할때까지 대기한다.)&lt;/li&gt;
&lt;li&gt;unlock : 현재 임계구역을 모두 사용했음을 알림. (대기중인 다른 쓰레드/프로세스가 임계구역에 진입할 수 있음)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;세마포어는 자원을 소유하지 못한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4️⃣ 뮤텍스는 소유하고 있는 쓰레드만이 이 뮤텍스를 해제할 수 있다.&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;반면, semaphore는 semaphore를 소유하지 않는 쓰레드가 semaphore를 해제할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5️⃣ Semaphore는 시스템 범위에 걸쳐 있고, 파일 시스템 상의 파일로 존재한다.&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;반면 뮤텍스는, 프로세스의 범위를 가지며, 프로세스가 종료될 때 자동으로 clean up 된다.&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;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;면접 예상 질문&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1.세마포어와 뮤텍스의 차이점은 무엇인가요?&lt;/li&gt;
&lt;/ul&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;size16&quot;&gt;세마포어는 여러 스레드가 동시에 접근할 수 있는 상황에서 사용될 수 있으며, 뮤텍스는 임계 영역에 단 하나의 스레드만이 접근해야 하는 상황에서 사용됩니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2.세마포어와 뮤텍스를 사용하는 이유는 무엇인가요?&lt;/li&gt;
&lt;/ul&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;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;/div&gt;
&lt;/div&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;3.세마포어와 뮤텍스의 구현 방식은 어떻게 되나요?&lt;/li&gt;
&lt;/ul&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;size16&quot;&gt;세마포어는 일반적으로 정수 값과 대기 큐를 사용하여 구현됩니다. 세마포어의 값을 증가시키거나 감소시키는 연산은 원자적으로 처리되어야 하며, 대기 큐에서 스레드를 깨우거나 대기시키는 동작도 조절되어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뮤텍스는 일반적으로 상태 변수와 스레드 대기 큐를 사용하여 구현됩니다. 뮤텍스는 잠금 상태와 잠금 해제 상태의 두 가지 상태를 가지며, 잠금 상태에 있는 뮤텍스를 획득하려는 스레드는 대기 큐에 들어가고, 잠금 해제 상태가 되면 다음 스레드가 뮤텍스를 획득할 수 있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>CS</category>
      <author>민궝</author>
      <guid isPermaLink="true">https://todayapp.tistory.com/25</guid>
      <comments>https://todayapp.tistory.com/25#entry25comment</comments>
      <pubDate>Wed, 7 Jun 2023 19:58:43 +0900</pubDate>
    </item>
  </channel>
</rss>