<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>JSPT</title>
    <link>https://devnuts.tistory.com/</link>
    <description>나는 천천히 걸어가는 사람입니다.
그러나  뒤로는 가지 않습니다.

- Abraham Lincoln -</description>
    <language>ko</language>
    <pubDate>Tue, 13 Oct 2026 05:10:34 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>후추부</managingEditor>
    <image>
      <title>JSPT</title>
      <url>https://tistory1.daumcdn.net/tistory/5241252/attach/3e71ecda9f454f049050828c68d94f2a</url>
      <link>https://devnuts.tistory.com</link>
    </image>
    <item>
      <title># 인테리어 리뷰 - 주방 가구 (feat. 마드주와 함께 1주일만에 완성)</title>
      <link>https://devnuts.tistory.com/265</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; letter-spacing: 0px;&quot;&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;div id=&quot;SE-82562fba-36db-11f1-988c-23bf7a51cdc5&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;p id=&quot;SE-44f80c37-5233-4145-95b7-bd5638b46445&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;급하게 주방 공사를 할 일이 생겼다.&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;SE-b9e8b17f-44aa-4379-972c-86e1a6453a5a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-1b815dac-f9e4-4783-9087-413d63c98433&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이미 인테리어 공사를 몇번 해봐서 알고는 있었지만,&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-da5f6ff8-a684-4cb1-b761-345d7c6f98c3&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;11일 이라는 시간은 너무나 촉박했고 &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-2f00f87a-cc33-47e5-8aca-385e581083ec&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;주방 뿐 아니라 다른 공정들도 있었기 떄문에 11일 안에 끝나야 하는 상황이었다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-6e396680-d746-4deb-b5ff-8ffeea765c14&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-df2ee62d-4510-4114-9cdb-e91abe6a4316&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이전에 거래했던 싱크공장 &amp;amp; 여기저기 다른 업체에 여럿 문의를 했으나 촉박한 일정에 맞춰줄 수 없다는 답변만 받았다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-f21e4e7b-d81a-4a07-a31b-209cd1ab214c&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c1712131-6e09-4352-9216-350d608fb9ba&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그런데 전화 한통을 받았다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-fff37fbf-e34b-43d3-880f-6da423d918d8&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&quot;마드주&quot;에서 온 전화였다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-8a1ad862-50fc-4ece-a0c6-fbeaf074f689&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-460b1847-5e34-40f2-993b-4292f7b85efb&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 곳은 싱크 업체와 소비자를 연결해주는 플랫폼이었기 때문에 여러 업체가 확보되어있다고 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-fb4d5084-7c9a-4397-8cde-557b796f672d&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그리고 그 중 한 곳에서 해당 일정에 가능하다는 확인을 받고 연락을 주는것이라고 들었다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-cd94b31a-8039-42a5-a8e2-f4ffa07408d5&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;(나중에 통화하면서 알게된게 서울 경기권은 거의 다 가능하고 충청도도 천안까지는 가능하다고 한다)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-sds-comp=&quot;Profile&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div style=&quot;color: #737373;&quot;&gt;&lt;a style=&quot;background-color: #ffffff; color: #0c43b7; text-align: start;&quot; href=&quot;https://www.madju.co.kr/&quot; data-heatmap-target=&quot;.link&quot;&gt;&lt;span&gt;&lt;br /&gt;www.madju.co.kr&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;514&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIv848/dJMcadBy2Wk/KXkhMR2Js9CZNQqgqocECk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIv848/dJMcadBy2Wk/KXkhMR2Js9CZNQqgqocECk/img.png&quot; data-alt=&quot;마드주 사이트 - 깔끔한 UI로 빠르게 견적 신청을 할 수 있었음.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIv848/dJMcadBy2Wk/KXkhMR2Js9CZNQqgqocECk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIv848%2FdJMcadBy2Wk%2FKXkhMR2Js9CZNQqgqocECk%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;514&quot; height=&quot;1125&quot; data-origin-width=&quot;514&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;마드주 사이트 - 깔끔한 UI로 빠르게 견적 신청을 할 수 있었음.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;SE-c1eedff5-ec79-4d18-948b-e0ef04b1cc7f&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;지체할 수 없었다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-658e6e29-c252-4a10-b8b1-8062cc6b01ff&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;일단 일정 되는 곳으로 무조건 확정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-eac58816-476c-49a7-9503-0a0438e4cede&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-a8be7b94-62c9-48da-a601-e9ccee7a7898&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;전화를 준 상담원은 알고보니 마드주의 대표님이었고 덕분에 여러가지 사항을 빠르게 고민하고 컨펌받을 수 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-30537ce1-3766-442b-beef-b81e24316750&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;514&quot; data-origin-height=&quot;565&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nWOPQ/dJMcabKDjyX/TkrAcKhs5eH84hRXwnSaqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nWOPQ/dJMcabKDjyX/TkrAcKhs5eH84hRXwnSaqk/img.png&quot; data-alt=&quot;마드주에서 받았던 시안&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nWOPQ/dJMcabKDjyX/TkrAcKhs5eH84hRXwnSaqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnWOPQ%2FdJMcabKDjyX%2FTkrAcKhs5eH84hRXwnSaqk%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;514&quot; height=&quot;565&quot; data-origin-width=&quot;514&quot; data-origin-height=&quot;565&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;마드주에서 받았던 시안&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p id=&quot;SE-abc51e71-0da8-4621-9019-c7b817d2840a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;lt;자재&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-2270b2a5-4afa-4496-94c2-68909c5ab068&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;-상부장&amp;amp;하부장 = 한샘 (콘크리트화이트 상부장 &amp;amp; 조슈아라이트 품절 이슈로 선택한 메종라이트오크 하부장)&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-7df5fe35-b4db-443c-a8b8-85869db654b8&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;-대리석=LG 인조대리석&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-8b5d1fad-fb02-4745-abda-34d9a492e36a&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;*후드와 인덕션, 싱크볼과 수전은 기존 사용하던 것 또는 내가 개별적으로 준비했다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-784c6395-72c6-41ef-bf00-d8ebaf3173cf&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-9c371547-a2ea-4bd7-a11d-658fd0e5cd7f&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;상담 과정에서 빠른 답변을 주셨고 소통도 원활했다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-28e55f50-9a91-4ed8-8933-f4fe15301ec7&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-1f674ece-80f5-4a02-aada-61a5a6e2649d&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;lt;철거&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-9ed19066-e9ba-4632-a6e8-b77f99fb1cb2&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;설치 하루 전 철거작업이 들어갔고 깔끔하게 정리됐다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;SE-46396f2a-36dc-11f1-988c-3158a353676f&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;lt;설치&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-9cdd185d-b9c3-4f24-9f0a-bc69a2dfb4f8&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;오전 8시 ~ 오후 5시&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-9bce3a79-2cef-4146-bc74-337e79adb748&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;하루종일 설치가 진행되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-8eade739-c570-45eb-886e-420eb006d5d2&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-531261ec-7156-40a6-8b24-95e6f62727b9&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;가구가 먼저 들어왔고 그 뒤에 대리석이 올라왔다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 모든게 2일에 걸쳐 마무리 된 내용.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-e4626ff3-36db-11f1-988c-25b0abd7991e&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/udWAk/dJMcag6dfG6/ERiNvC1QHlHBTWWWc8i5fk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/udWAk/dJMcag6dfG6/ERiNvC1QHlHBTWWWc8i5fk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/udWAk/dJMcag6dfG6/ERiNvC1QHlHBTWWWc8i5fk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FudWAk%2FdJMcag6dfG6%2FERiNvC1QHlHBTWWWc8i5fk%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;900&quot; height=&quot;1200&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-e46e2f38-36db-11f1-988c-fbdd089f3e11&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;상부장 콘크리트화이트&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-e4641da4-36db-11f1-988c-13bb6f14beba&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AMQjL/dJMcag6dfG9/DcY1jRGXKtCZJP5zJHMT81/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AMQjL/dJMcag6dfG9/DcY1jRGXKtCZJP5zJHMT81/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AMQjL/dJMcag6dfG9/DcY1jRGXKtCZJP5zJHMT81/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAMQjL%2FdJMcag6dfG9%2FDcY1jRGXKtCZJP5zJHMT81%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;900&quot; height=&quot;1200&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-e46ef28a-36db-11f1-988c-bd2b753ffb8b&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;오른쪽 밖으로 수납공간 확보 -스낵창고&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-e4657d35-36db-11f1-988c-2f17e2074668&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckocgV/dJMcagd46BH/dDJBNJIQInlCbE7O4FkJnk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckocgV/dJMcagd46BH/dDJBNJIQInlCbE7O4FkJnk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckocgV/dJMcagd46BH/dDJBNJIQInlCbE7O4FkJnk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckocgV%2FdJMcagd46BH%2FdDJBNJIQInlCbE7O4FkJnk%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;900&quot; height=&quot;1200&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-e46fdcec-36db-11f1-988c-914ebbffcde2&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;상하부장만 먼저 완료&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-e467c776-36db-11f1-988c-f3c0794637e5&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-46396f2b-36dc-11f1-988c-e9d333744acc&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;수전과 싱크볼, 인덕션을 미리 준비해서 현장에 두었고 &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-3adbf1da-e671-4762-a8b0-9461c9f51552&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이에맞게 재단해서 설치까지 마무리 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-f4338263-36db-11f1-988c-bf3d42e4ee76&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTNQur/dJMcaakCkjL/iImGL23EAaHGVteO8ZcCsk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTNQur/dJMcaakCkjL/iImGL23EAaHGVteO8ZcCsk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTNQur/dJMcaakCkjL/iImGL23EAaHGVteO8ZcCsk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTNQur%2FdJMcaakCkjL%2FiImGL23EAaHGVteO8ZcCsk%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;900&quot; height=&quot;1200&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-f43c0e05-36db-11f1-988c-3faa40c612cb&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;상판 설치 모습&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-f435f364-36db-11f1-988c-d91009dd7d6e&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjQ6FS/dJMcacvZFqk/7DwR6k7OD6n600earvq3DK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjQ6FS/dJMcacvZFqk/7DwR6k7OD6n600earvq3DK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjQ6FS/dJMcacvZFqk/7DwR6k7OD6n600earvq3DK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjQ6FS%2FdJMcacvZFqk%2F7DwR6k7OD6n600earvq3DK%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;900&quot; height=&quot;1200&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-f43d6d97-36db-11f1-988c-7fe72520a727&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;청소 전 보호필름 떼어낸 모습&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;SE-f437c829-36db-11f1-988c-7fcd6bf44c5b&quot; style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p id=&quot;SE-46396f2c-36dc-11f1-988c-67ad0845af10&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-1baf9976-24ce-48ff-88e7-2cf371acc32d&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;조슈아라이트가 없어 아쉬운 마음으로 메종라이트오크로 진행했지만 &lt;/span&gt;&lt;span&gt;공사를 마치고 보니 아주 대만족.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-f3faf785-85f3-4c5d-85ec-a47f63aaf9b9&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;상담할때 대표님이 추천해준 색상이었는데 좋은 추천이었다고 생각한다. 아주 감사하는 중.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-b4601df8-a8ea-45aa-b1d1-d2cbe4da6b17&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-d9b726bd-3c80-4503-83fa-7f3e86486e24&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c39a3098-9b35-40f8-b204-c0f273a9f3af&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;무엇보다 빠듯한 일정, 단 일주일의 말미안에 설치까지 마무리 되었다는 점이 너무 만족스러웠다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-4c78bb97-1c32-4cdf-a0d6-56ea77b5379d&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;마음에드는주방, 마드주 &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c3f069b6-2390-4631-85e7-7a84b89e32dd&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;주방공사를 고민하고있다면 추천할만 하다 !! &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-db50c83a-4560-4a3e-a75f-a4b6ee1c418c&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-5bbca874-b6fd-4437-9cf6-b290197172ad&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;​* 업체로부터 블로그 리뷰 작성에 따른 비용 할인 혜택을 제공받았으나, 실제 공사 과정과 결과물을 바탕으로 직접 느낀 점을 솔직하게 작성하였습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-7db064dc-29de-4a36-ad18-e7af1d59b2fc&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-93f28053-e27a-4eee-9b98-992f358944f2&quot; style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #387cbb;&quot;&gt;#마드주&lt;/span&gt;#마음에드는주방#주방인테리어#인테리어후기#한솔주방&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>마드주</category>
      <category>마드주후기</category>
      <category>마음에드는주방</category>
      <category>인테리어후기</category>
      <category>주방가구</category>
      <category>주방인테리어</category>
      <category>한솔주방</category>
      <author>후추부</author>
      <guid isPermaLink="true">https://devnuts.tistory.com/265</guid>
      <comments>https://devnuts.tistory.com/265#entry265comment</comments>
      <pubDate>Mon, 13 Apr 2026 15:54:21 +0900</pubDate>
    </item>
    <item>
      <title>[안드로이드] 앱 배포 시 발견한 문제1개. 앱에서 광고 ID를 사용하나요? (광고 ID 선언이 불완전함) com.google.android.gms.permission.AD_ID</title>
      <link>https://devnuts.tistory.com/259</link>
      <description>&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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;어? &lt;span style=&quot;color: #ee2323;&quot;&gt;발견한 문제 1개&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock style1&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_9223.jpeg&quot; data-origin-width=&quot;3264&quot; data-origin-height=&quot;1514&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Jg95R/btsKdGvi6fg/WaCJvBOyVqTZj8S9KLSBh0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Jg95R/btsKdGvi6fg/WaCJvBOyVqTZj8S9KLSBh0/img.jpg&quot; data-alt=&quot;이슈 발생 어???&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Jg95R/btsKdGvi6fg/WaCJvBOyVqTZj8S9KLSBh0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJg95R%2FbtsKdGvi6fg%2FWaCJvBOyVqTZj8S9KLSBh0%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;3264&quot; height=&quot;1514&quot; data-filename=&quot;IMG_9223.jpeg&quot; data-origin-width=&quot;3264&quot; data-origin-height=&quot;1514&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이슈 발생 어???&lt;/figcaption&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제를 자세히 확인해보면, 정책 선언 업데이트를 하라고 나온다.&lt;/b&gt;&lt;b&gt;&lt;/b&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 style1&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_9699.jpeg&quot; data-origin-width=&quot;3652&quot; data-origin-height=&quot;638&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BB99I/btsKbSxf253/abcKRchqZCPkNjbKLkSZMk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BB99I/btsKbSxf253/abcKRchqZCPkNjbKLkSZMk/img.jpg&quot; data-alt=&quot;이슈 발생&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BB99I/btsKbSxf253/abcKRchqZCPkNjbKLkSZMk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBB99I%2FbtsKbSxf253%2FabcKRchqZCPkNjbKLkSZMk%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;3652&quot; height=&quot;638&quot; data-filename=&quot;IMG_9699.jpeg&quot; data-origin-width=&quot;3652&quot; data-origin-height=&quot;638&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이슈 발생&lt;/figcaption&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;앱에서 광고 ID 를 사용하냐는 물음에 의아한 생각이 들었다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;현재 배포 중인 앱은 광고 sdk 를 사용하지 않는데 왜 저런 이슈가 발생할까?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그리고 매니페스트에 com.google.android.gms.permission.AD_ID 를 추가하지도 않았다.&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: #ee2323;&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock style1&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_7942.jpeg&quot; data-origin-width=&quot;1988&quot; data-origin-height=&quot;1892&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dXsxhR/btsKbIaw97h/4iFs3tQDMt0ZwnVkkKfh00/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dXsxhR/btsKbIaw97h/4iFs3tQDMt0ZwnVkkKfh00/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dXsxhR/btsKbIaw97h/4iFs3tQDMt0ZwnVkkKfh00/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdXsxhR%2FbtsKbIaw97h%2F4iFs3tQDMt0ZwnVkkKfh00%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;687&quot; height=&quot;654&quot; data-filename=&quot;IMG_7942.jpeg&quot; data-origin-width=&quot;1988&quot; data-origin-height=&quot;1892&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그런데도.. 왜 동일하지?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜 발견한 문제1개 가 사라지지 않지?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;아래 이미지를 보면 앱 콘텐츠 조치된 선언에서 사용하지 않는다고 지정했다고 정책 업데이트를 했다고 나오는데&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock style1&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_2232.jpeg&quot; data-origin-width=&quot;3348&quot; data-origin-height=&quot;988&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7DTSg/btsKcN9RXx3/vY5yhYAM4xTQVlFoX1VkoK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7DTSg/btsKcN9RXx3/vY5yhYAM4xTQVlFoX1VkoK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7DTSg/btsKcN9RXx3/vY5yhYAM4xTQVlFoX1VkoK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7DTSg%2FbtsKcN9RXx3%2FvY5yhYAM4xTQVlFoX1VkoK%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;3348&quot; height=&quot;988&quot; data-filename=&quot;IMG_2232.jpeg&quot; data-origin-width=&quot;3348&quot; data-origin-height=&quot;988&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그래서 고민했던건&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;현재 이 앱은 웹뷰가 90%를 차지하는 앱이다보니, 웹뷰 담당 팀 쪽에서 광고를 붙혔나? 생각이 들었다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;하지만......&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;역시나 내가 놓치고 있던 부분이 있었다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;우리 팀원 중 한 명이 이번에 Firebase Analytics 를 추가했다는 걸 새까맣게 잊고 있었다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;애널리틱스 관련 sdk 를 추가하면서 광고 ID 정책 업데이트 시, &lt;span style=&quot;color: #006dd7;&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock style1&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_6815.jpeg&quot; data-origin-width=&quot;2050&quot; data-origin-height=&quot;1920&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFKBDt/btsKdfkyedV/la6S7TyciBWrYMHm6Ec3ok/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFKBDt/btsKdfkyedV/la6S7TyciBWrYMHm6Ec3ok/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFKBDt/btsKdfkyedV/la6S7TyciBWrYMHm6Ec3ok/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFKBDt%2FbtsKdfkyedV%2Fla6S7TyciBWrYMHm6Ec3ok%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;708&quot; height=&quot;663&quot; data-filename=&quot;IMG_6815.jpeg&quot; data-origin-width=&quot;2050&quot; data-origin-height=&quot;1920&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;b&gt;위 이미지 사진과 동일하게 '애널리틱스' 체크 박스를 체크를 했더니....&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;'발견한 1개 문제'&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;차징데이라 일찍 퇴근한다는 생각에 내가 제대로 보지 못했던 게 한탄스러웠다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;꼼꼼히 보자.....&lt;/b&gt;&lt;/p&gt;</description>
      <category>Mobile App/Android</category>
      <category>Android</category>
      <category>release</category>
      <category>광고 id</category>
      <category>구글콘솔</category>
      <category>발견한 1개 문제</category>
      <category>배포</category>
      <author>후추부</author>
      <guid isPermaLink="true">https://devnuts.tistory.com/259</guid>
      <comments>https://devnuts.tistory.com/259#entry259comment</comments>
      <pubDate>Sun, 20 Oct 2024 11:52:02 +0900</pubDate>
    </item>
    <item>
      <title>[안드로이드] 앱 위변조 방지 (루팅, 탈옥, 패킷탈취, 디버깅툴 탐지 등)</title>
      <link>https://devnuts.tistory.com/258</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서 상반기 하반기를 나누어 사내 보안팀이 '모의해킹' 팀을 고용하여 회사 내 자체 서비스 App을 모의해킹 한다.&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;가장 좋은 건 보안업체 SDK 를 사용하여 보안취약점 대응을 하는게 좋다. (우리 회사는 당연히 외부 라이브러리 보안 SDK 사용 중)&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;우리 회사에서 사용하고 있는 보안 관련 SDK 업체는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;라온시큐어&lt;/b&gt;, &lt;b&gt;시큐센&lt;/b&gt;, &lt;b&gt;스틸리언&lt;/b&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;위와 같은 보안 관련 SDK 없이 어떤 방법으로 앱 보안 취약점에 대응할 수 있을지 몇 가지 소개하겠다.&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;TL;DR&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1.  루팅 탐지&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 'Su' 루트 실행 권한 있는지 확인&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 루팅 우회 탐지(프리다)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 디버깅 툴 탐지&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. 타 스토어에서 설치된 앱 체크&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;&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;#1. 루팅 탐지&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;/system/build.prop 파일에 test-keys 값이 존재하는 지 확인&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1713179416268&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private static Boolean checkTestKey() {
    String tag = android.os.Build.TAGS;
    return tag != null &amp;amp;&amp;amp; tag.contains(&quot;test-keys&quot;);
}&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;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;바이너리 파일 경로에 루팅탐지 관련 텍스트 확인&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1713179485316&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    /**
     * 루팅된 기기에서 사용되는 바이너리 파일 경로
     */
    private static final String[] binaryPaths = {
            &quot;/data/local/&quot;,
            &quot;/data/local/bin/&quot;,
            &quot;/data/local/xbin/&quot;,
            &quot;/sbin/&quot;,
            &quot;/su/bin/&quot;,
            &quot;/system/bin/&quot;,
            &quot;/system/bin/.ext/&quot;,
            &quot;/system/bin/failsafe/&quot;,
            &quot;/system/sd/xbin/&quot;,
            &quot;/system/usr/we-need-root/&quot;,
            &quot;/system/xbin/&quot;,
            &quot;/system/app/Superuser.apk&quot;,
            &quot;/cache&quot;,
            &quot;/data&quot;,
            &quot;/dev&quot;
    };
    

    private static Boolean checkForBinary(String fileName) {
        for (String path : binaryPaths) {
            File f = new File(path, fileName);
            if (f.exists()) {
                return true;
            }
        }
        return false;
    }
    
	/**
     * 비지박스 루팅 탐지
     */
    private static Boolean checkForBusyBoxBinary() {
        return checkForBinary(&quot;busybox&quot;);
    }

    /**
     * Su 루팅 탐지
     */
    private static Boolean checkForSuBinary() {
        return checkForBinary(&quot;su&quot;);
    }

    /**
     * 매지스크 루팅 탐지
     */
    private static Boolean checkForMagiskBinary() {
        return checkForBinary(&quot;magisk&quot;);
    }&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#2. 'Su' 루트 실행 권한이 있는지 확인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앱을 루팅하게 되면, Su 실행 권한이 등록이 되어있다.&lt;/p&gt;
&lt;pre id=&quot;code_1713179746531&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private static Boolean checkSuExecAuthority() {
    Process process = null;
    try {
        process = Runtime.getRuntime().exec(new String[]{&quot;/system/xbin/which&quot;, &quot;su&quot;});
        BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line = in.readLine();
        process.destroy();
        return line != null;
    } catch (Exception e) {
        if (process != null) {
            process.destroy();
        }
        return false;
    }
}&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#3. 루팅 우회 탐지(프리다) 확인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;탐지 우회 Hooking 을 하게 되는 경우를 막는 로직이다.&lt;/p&gt;
&lt;pre id=&quot;code_1713179889827&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/**
 * 프리다 탐지 (탐지 우회 Hooking 막기)
 */
private static boolean checkFrida() {
    int pid = android.os.Process.myPid();

    try {
        String mapsFileContents = null;
        if (android.os.Build.VERSION.SDK_INT &amp;gt;= android.os.Build.VERSION_CODES.O) {
            mapsFileContents = new String(Files.readAllBytes(Paths.get(&quot;/proc/&quot;+pid+&quot;/maps&quot;)), Charset.defaultCharset());
        }

        if (mapsFileContents == null) return false;

        return mapsFileContents.contains(&quot;frida&quot;);
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
}&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#4. 디버깅 툴 탐지&lt;/h2&gt;
&lt;pre id=&quot;code_1713179962146&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; /**
  * 디버깅 툴 탐지
  */
private static boolean checkDebugger() {
    int pid = android.os.Process.myPid();
    String status = &quot;proc/&quot; + pid + &quot;/status&quot;;
    File file = new File(status);

    try {
        FileReader fr = new FileReader(file);
        BufferedReader br = new BufferedReader(fr);

        String line = br.readLine();
        while (line != null) {
            if (line.contains(&quot;TracerPid&quot;)) {
                String[] split = line.split(&quot;\t&quot;);
                int tracerPid = Integer.parseInt(split[1]);
                if (tracerPid != 0) { // '디버깅 툴' 존재.
                    return true;
                }
            }
            line = br.readLine();
        }
    } catch (FileNotFoundException e) {
        throw new RuntimeException(e);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    return false;
}&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#5. 타 스토어에서 앱 설치 확인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글 스토어에만 올렸는데, 내 앱을 다른 누군가 타 스토어에 올려 악용하는 사례가 있으니 확인한다.&lt;/p&gt;
&lt;pre id=&quot;code_1713180397368&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static List&amp;lt;String&amp;gt; registeredStores = new ArrayList&amp;lt;String&amp;gt;() {
    {
        add(&quot;com.android.vending&quot;); // 구글스토어   
    }
};


String installer = getPackageManager().getInstallerPackageName(getPackageName());

if (!registeredStores.contains(installer)) {
    showAlertMessage(getString(R.string.dialog_forgery));
    return;
}&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;추가로 다양한 스토어 패키지 명을 정리하자면 아래와 같다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;각종 스토어 패키지명&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. Google Play Store (구글 플레이 스토어)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: com.android.vending&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;2. ONE Store (원스토어)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: SKT / com.skt.skaf.A000Z00040&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: KT / com.kt.olleh.storefront&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: LG U+ / android.lgt.appstore 또는 comlguplus.appstore&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;3. Galaxy Apps (갤럭시 앱스)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: com.sec.android.app.samsungapps&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;4. Samsung Smart Switch (삼성 스마트 스위치)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: com.sec.android.easyMover.Agent&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;5. Android Package Installer&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: com.google.android.packageinstaller&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;6. Samsung Mate Agent&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: com.samsung.android.mateagent&lt;/p&gt;</description>
      <category>Mobile App/Android</category>
      <author>후추부</author>
      <guid isPermaLink="true">https://devnuts.tistory.com/258</guid>
      <comments>https://devnuts.tistory.com/258#entry258comment</comments>
      <pubDate>Mon, 15 Apr 2024 20:32:01 +0900</pubDate>
    </item>
    <item>
      <title>[안드로이드] AlarmManager 디버깅</title>
      <link>https://devnuts.tistory.com/257</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;알람을 등록하고 제대로 디바이스에 등록이 됐는지 확인하고 싶지 않는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;등록은 했지만, 울리지 않는 경우가 있는데 왜 안 울릴까? 정확하게 내가 원하는 시간에 등록이 됐는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;라는 궁금증에 디버깅하는 방법을 알아보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;디버깅은 &lt;b&gt;adb shell&lt;/b&gt; 을 이용하여, 등록된 알람, 만료된 알람 등 정보들을 확인해볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;adb 란 무엇인가?&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;adb 는 Android Debug Bridge 약자이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안드로이드 장치와 통신하여 디버깅 등의 작업을 진행할 수 있는 command line tool 이라고 생각하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;shell 명령어를 통해 시스템 로그 등 다양한 정보를 확인할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&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;a href=&quot;https://developer.android.com/tools/adb?hl=ko#directingcommands&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.android.com/tools/adb?hl=ko#directingcommands&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712729891815&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Android 디버그 브리지(adb) &amp;nbsp;|&amp;nbsp; Android Studio &amp;nbsp;|&amp;nbsp; Android Developers&quot; data-og-description=&quot;기기와 통신할 수 있도록 지원하는 다목적 명령줄 도구인 Android 디버그 브리지에 대해 알아보세요.&quot; data-og-host=&quot;developer.android.com&quot; data-og-source-url=&quot;https://developer.android.com/tools/adb?hl=ko#directingcommands&quot; data-og-url=&quot;https://developer.android.com/tools/adb?hl=ko&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dagpj9/hyVMYrFNHy/wy5pN82RkZeLMK3uLeKo50/img.png?width=1201&amp;amp;height=676&amp;amp;face=0_0_1201_676,https://scrap.kakaocdn.net/dn/bZ3ARL/hyVMLToCh2/AUJhwwzJauzBmlOtXAhQok/img.png?width=1174&amp;amp;height=988&amp;amp;face=0_0_1174_988,https://scrap.kakaocdn.net/dn/sgOEM/hyVMTKD3Oa/mTiKwtl7haAIHDSk4d7FTk/img.png?width=365&amp;amp;height=675&amp;amp;face=0_0_365_675&quot;&gt;&lt;a href=&quot;https://developer.android.com/tools/adb?hl=ko#directingcommands&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.android.com/tools/adb?hl=ko#directingcommands&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dagpj9/hyVMYrFNHy/wy5pN82RkZeLMK3uLeKo50/img.png?width=1201&amp;amp;height=676&amp;amp;face=0_0_1201_676,https://scrap.kakaocdn.net/dn/bZ3ARL/hyVMLToCh2/AUJhwwzJauzBmlOtXAhQok/img.png?width=1174&amp;amp;height=988&amp;amp;face=0_0_1174_988,https://scrap.kakaocdn.net/dn/sgOEM/hyVMTKD3Oa/mTiKwtl7haAIHDSk4d7FTk/img.png?width=365&amp;amp;height=675&amp;amp;face=0_0_365_675');&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;Android 디버그 브리지(adb) &amp;nbsp;|&amp;nbsp; Android Studio &amp;nbsp;|&amp;nbsp; Android Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;기기와 통신할 수 있도록 지원하는 다목적 명령줄 도구인 Android 디버그 브리지에 대해 알아보세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.android.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;p data-ke-size=&quot;size14&quot;&gt;adb 에 대해 궁금하다면 위 링크를 통해 공부해보면 좋을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;하지만, 오늘 우리는 adb shell 을 이용하여 AlarmManager 를 이용하여 등록한 알람을 디버깅하는 방법을 알아볼 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&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;1.&amp;nbsp; AlarmManager 에 등록된 것만이 아닌,&amp;nbsp; 안드로이드 내 Alarm 등록된 정보 보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot;&gt;등록된 알람 리스트 등 다양한 알람정보를 확인할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712730397272&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;adb shell dumpsys alarm | less

| less 를 추가로 작성을 해야 맨 처음부터 log 를 확인할 수 있따.&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Next alarm clock information: 다음으로 예약된 알림이 언제 발생할지와 이에 대한 세부정보 표시&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712833953428&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; ELAPSED #1: Alarm{be1fdee type 3 origWhen 865747386 whenElapsed 865747386 android}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tag=*alarm*:*CountQuotaTracker.cleanup*
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;type=ELAPSED origWhen=-2m4s949ms window=+7m35s905ms repeatInterval=0 count=0 flags=0x8
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;policyWhenElapsed: requester=-2m4s949ms app_standby=-12m2s675ms device_idle=-- battery_saver=-- tare=-12m12s814ms
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;whenElapsed=-2m4s949ms maxWhenElapsed=+5m30s956ms
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;listener=android.app.AlarmManager$ListenerWrapper@f7e5682


 RTC_WAKEUP #9: Alarm{5f4ff52 type 0 origWhen 1712791386153 whenElapsed 866145308 com.ktcs.whowho}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tag=*walarm*:com.ktcs.whowho.work_action_sdmlib_cycle_periodic
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;type=RTC_WAKEUP origWhen=2024-04-11 08:23:06.153 window=0 exactAllowReason=permission repeatInterval=0 count=0 flags=0x5
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;policyWhenElapsed: requester=+4m32s973ms app_standby=-10m27s24ms device_idle=-- battery_saver=-10m27s24ms tare=-10m27s24ms
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;whenElapsed=+4m32s973ms maxWhenElapsed=+4m32s973ms
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;operation=PendingIntent{a87e223: PendingIntentRecord{1cf7b06 com.ktcs.whowho broadcastIntent}}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;idle-options=Bundle[{android.pendingIntent.backgroundActivityAllowed=false, android:broadcast.temporaryAppAllowlistReasonCode=302, android:broadca
st.temporaryAppAllowlistDuration=10000, android:broadcast.temporaryAppAllowlistReason=, android:broadcast.temporaryAppAllowlistType=0}]&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Removal history: 이전에 제거된 알람에 대한 이력을 보여준다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712834083601&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Removal history:
    1000:
      [tag=*walarm*:WificondScannerImpl Scan Timeout H=L:53be729 reason=alarm_cancelled elapsed=865156753  rtc=2024-04-11 08:06:37.598]
      [tag=*walarm*:WificondScannerImpl Scan Timeout H=L:c085726 reason=alarm_cancelled elapsed=865171501  rtc=2024-04-11 08:06:52.346]
      [tag=*walarm*:WificondScannerImpl Scan Timeout H=L:2e6facf reason=alarm_cancelled elapsed=865181602  rtc=2024-04-11 08:07:02.448]
      [tag=*walarm*:WificondScannerImpl Scan Timeout H=L:2e8e2d reason=alarm_cancelled elapsed=865189548  rtc=2024-04-11 08:07:10.393]
      [tag=*walarm*:NLPOnceRequest H=L:e7b0c4e reason=alarm_cancelled elapsed=865189630  rtc=2024-04-11 08:07:10.475]
      [tag=*walarm*:WificondScannerImpl Scan Timeout H=L:edcf52e reason=alarm_cancelled elapsed=865194714  rtc=2024-04-11 08:07:15.560]
      [tag=*alarm*:cohttp://m.samsung.android.forest.promovence.NOTIFY_WEEKLY_REPORT H=PI:d1b1dc1 reason=alarm_cancelled elapsed=865209360  rtc=2024-04-11 08:0
7:30.205]&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;Addition history: 알람이 추가된 이력을 보여준다. 즉, 언제 추가되었는지도 확인이 가능하다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712834109901&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  [tag=*alarm*:cohttp://m.samsung.android.app.telephonyui.action.STATUS_ALL_SETTING_LOGGING T=1 F=9 AC=false H=PI:971756c OW=2024-04-02 10:28:58.122 elapse
d=144825 rtc=2024-04-01 07:49:45.671]
      [tag=*walarm*:com.android.internal.telephony.carrier_key_download_alarm T=0 F=8 AC=false H=PI:735e504 OW=2049-07-01 20:44:00.751 WL=3600000 elapse
d=1506508 rtc=2024-04-01 08:12:27.354]&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&amp;nbsp;Delivery history: 알람이 전달된 이력을 보여준다. 알람이 실제로 발생하여 처리됐는지 보여준다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712834131052&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[tag=*alarm*:DetectMovementSPListener origWhen=865339741 H=L:ad624e8 elapsed=865339742 rtc=2024-04-11 08:09:40.588]
[tag=*walarm*:cohttp://m.ktcs.whowho.work_action_sdmlib_cycle_periodic origWhen=1711928619468 H=PI:2b30e8d elapsed=3383628 rtc=2024-04-01 08:43:44.473]&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Expiration history: 알람이 만료된 이력을 보여준다. 예약된 작업이나 이벤트에 대한 알람이 만료되면 기록된다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712834157771&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[flag=8 wakeup=865896577 non-wakeup=865839155 elapsed=865839158 rtc=2024-04-11 08:18:00.003]&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;Alarm Stats: 알람 관련 통계&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712834219717&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  u0a1110:cohttp://m.ktcs.whowho +99ms running, 1 wakeups:
    +99ms 1 wakes 1 alarms, last -10m27s118ms:
      *walarm*:cohttp://m.ktcs.whowho.work_action_sdmlib_cycle_periodic&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/28742884/how-to-read-adb-shell-dumpsys-alarm-output&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://stackoverflow.com/questions/28742884/how-to-read-adb-shell-dumpsys-alarm-output&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712833722864&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;How to read &amp;quot;adb shell dumpsys alarm&amp;quot; output&quot; data-og-description=&quot;I'm struggling with setting an alarm properly, and understanding the mechanism of cancelling and rescheduling alarms. I have found, that there is an adb command to retrieve all alarms scheduled on&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/28742884/how-to-read-adb-shell-dumpsys-alarm-output&quot; data-og-url=&quot;https://stackoverflow.com/questions/28742884/how-to-read-adb-shell-dumpsys-alarm-output&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/4K4rX/hyVPKThpvP/fPGFymmi67pqzUKqnbUAMk/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/28742884/how-to-read-adb-shell-dumpsys-alarm-output&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://stackoverflow.com/questions/28742884/how-to-read-adb-shell-dumpsys-alarm-output&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/4K4rX/hyVPKThpvP/fPGFymmi67pqzUKqnbUAMk/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316');&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;How to read &quot;adb shell dumpsys alarm&quot; output&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;I'm struggling with setting an alarm properly, and understanding the mechanism of cancelling and rescheduling alarms. I have found, that there is an adb command to retrieve all alarms scheduled on&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;stackoverflow.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;h3 data-ke-size=&quot;size23&quot;&gt;2. 개발 중인 App 에 등록된 AlarmManager 디버깅 (특정 패키지)&lt;/h3&gt;
&lt;pre id=&quot;code_1712834546125&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;adb shell dumpsys alarm | grep &quot;특정 패키지명&quot;&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;size14&quot;&gt;위 명령어를 사용 시, 현재 디바이스에 등록된 특정 패키지 알람로그를 보여준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Mobile App/Android</category>
      <author>후추부</author>
      <guid isPermaLink="true">https://devnuts.tistory.com/257</guid>
      <comments>https://devnuts.tistory.com/257#entry257comment</comments>
      <pubDate>Thu, 11 Apr 2024 20:25:14 +0900</pubDate>
    </item>
    <item>
      <title>[깃허브] Git Clone 한 레포를 내 Github 에 올리기 (master main 병합)</title>
      <link>https://devnuts.tistory.com/256</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;어떤 상황인가?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 다른 원작자가 만든 Repository 에 원하는 Branch 를 Clone 하여, 내 Github 으로 올리기.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Github 에 연동하지 않은 내 프로젝트 폴더 Github 에 올리기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- remote master 와 remote main 이 두 개나 있는데, 하나로 합치려면?&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;아래 설명한대로 command line tool 명령어를 작성하면 분명 될 것이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Git Clone 한 Repository 내 Github 에 올리는 방법&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;1) 우선 Github 사이트 특정 레포로 들어가 초록색 &lt;b&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;Code&lt;/span&gt;&lt;/b&gt; 를 클릭해보면, 해당 레포 주소로 Clone 할 수 있게 주소 url 을 알려준다. 해당 url 을 복사해두자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;2) 내가 원하는 위치 로컬 디렉토리에서 터미널(&lt;b&gt;command line tool&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;size14&quot;&gt;3) 아래 명령어를 작성한다. 그러면 내가 원하는 레포의 파일들을 가져올 수 있다. &lt;span style=&quot;color: #ee2323; text-align: start;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #ee2323; text-align: start;&quot;&gt;아래 명령어 참고&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712826782447&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;특정 레포에 특정 브랜치를 가져오고(clone)싶다면?
git clone -b [특정 브랜치] [특정레포 주소]
    
    
특정 레포를 가져오고(clone)싶다면?
git clone -b [특정레포 주소]&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;4) 원작자의 Git Repository remote 연결 해제 하기 &lt;span style=&quot;color: #ee2323; text-align: start;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #ee2323; text-align: start;&quot;&gt;아래 명령어 참고&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712829503973&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[remote 해제]
git remote remove origin
[remote 해제 됐는지 확인]
git remove -v (연결된 remote 가 없어야 함)&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;size14&quot;&gt;5) 숨긴파일을 보이게 하여 &lt;b&gt;.git&lt;/b&gt; 관련 파일을 다 삭제한다. (없으면 pass)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;6) Github 사이트로 가서 새로운 repository 를 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;7) 내 Github remote 에 올릴 폴더 위치로 가서 터미널을 연다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;8) 터미널에 아래와 같은 명령어를 입력하여 git 초기화 작업을 한다. &lt;span style=&quot;color: #ee2323; text-align: start;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #ee2323; text-align: start;&quot;&gt;아래 명령어 참고&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712829864703&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;초기화 작업

1. 초기설정
git config --global user.name [유저이름]
git config --global user.email [유저 이메일]

2. github 에 올릴 파일 세팅하기
git init (.git 파일 생성)
git add . (commit 전 stage 에 올리기)
git commit -m [커밋 문구 작성]

3. github remote 에 올리는 작업
git remote add origin [내 깃헙 레포 주소]
git push -u origin master&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;size14&quot;&gt;9) main 으로 default 로 되어 있는 경우, main &amp;lt;-&amp;gt; master 합치기 &lt;span style=&quot;color: #ee2323;&quot;&gt;*아래 명령어 참고&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712830021937&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1. master 에 push 한 내용을 main 에도 push 하는 작업
git checkout master
git branch main master -f
git checkout main
git push origin main -f


2. main 이 default 로 만들고, master 브랜치 삭제
git config --global init.defaultBranch main
git push origin --delete master&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS/Other</category>
      <author>후추부</author>
      <guid isPermaLink="true">https://devnuts.tistory.com/256</guid>
      <comments>https://devnuts.tistory.com/256#entry256comment</comments>
      <pubDate>Thu, 11 Apr 2024 19:12:56 +0900</pubDate>
    </item>
    <item>
      <title>[안드로이드] networkOperatorName 3사 알뜰폰(MVNO)은 어떤 값이 들어올까?</title>
      <link>https://devnuts.tistory.com/255</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;IOS 와는 달리 AOS 즉, 안드로이드는 SIM 정보를 읽어올 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.android.com/reference/android/telephony/TelephonyManager&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.android.com/reference/android/telephony/TelephonyManager&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712145734171&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;TelephonyManager &amp;nbsp;|&amp;nbsp; Android Developers&quot; data-og-description=&quot;&quot; data-og-host=&quot;developer.android.com&quot; data-og-source-url=&quot;https://developer.android.com/reference/android/telephony/TelephonyManager&quot; data-og-url=&quot;https://developer.android.com/reference/android/telephony/TelephonyManager&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/H0M0u/hyVJSLdbDz/4Xq1nYbGWQR0d68QUE5VnK/img.png?width=1201&amp;amp;height=676&amp;amp;face=0_0_1201_676&quot;&gt;&lt;a href=&quot;https://developer.android.com/reference/android/telephony/TelephonyManager&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.android.com/reference/android/telephony/TelephonyManager&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/H0M0u/hyVJSLdbDz/4Xq1nYbGWQR0d68QUE5VnK/img.png?width=1201&amp;amp;height=676&amp;amp;face=0_0_1201_676');&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;TelephonyManager &amp;nbsp;|&amp;nbsp; Android Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.android.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;p data-ke-size=&quot;size16&quot;&gt;위 링크에 있는 TelephonyManager 객체를 이용하여 SIM 정보를 가져올 수 있고, 다양한 정보를 확인할 수 있다.&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;이번 개발 과제는 통신사를 뽑아서 전달을 해야했다. 일단 3사 망 사업자 데이터는 어떻게 들어올까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3사(MNO) 망사업자 추출 값&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SKT&lt;/b&gt; &amp;gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;SKTelecom&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;KT&lt;/b&gt; &amp;gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;KT&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;LG&lt;/b&gt; &amp;gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;LG U+&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;networkOperatorName 함수를 이용하여 '망사업자 정보'를 추출하면 위와 같이 정보가 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 블로그를 참고해보면, &lt;b&gt;KT&lt;/b&gt; 가 &lt;span style=&quot;color: #ee2323;&quot;&gt;olleh&lt;/span&gt; 라는 값을 추출됐던 적이 있던 거 같아. &lt;span style=&quot;color: #ee2323;&quot;&gt;olleh&lt;/span&gt; case 도 넣어두면 좋을 거 같다.&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;알뜰폰은 어떤 값들이 나오지?&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;일단, KT 알뜰폰(MVNO) 만 값을 뽑아 봤을 때, 동일한 &lt;span style=&quot;color: #ee2323;&quot;&gt;KT&lt;/span&gt; 값이 나왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 두 통신사 MVNO 를 테스트 해보진 않았지만, 유추하는 건 동일할 것이라고 본다.&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;결국 알뜰폰(MVNO) 는 3사 통신사(MNO) 망을 대여해서 사용하기 때문에 SIM 정보가 동일하지 않을까 라는 합리적 의심이다.&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;결국, networkOperatorName 함수를 가지고 총 6가지 (3사 통신사, 3사 알뜰폰 통신사) 통신사를 구분 지을 수 있게 값 추출이 안됐다.&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://source.android.com/docs/core/connect/carrierid?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://source.android.com/docs/core/connect/carrierid?hl=ko&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712146639789&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;이동통신사 ID &amp;nbsp;|&amp;nbsp; Android 오픈소스 프로젝트 &amp;nbsp;|&amp;nbsp; Android Open Source Project&quot; data-og-description=&quot;이동통신사 ID 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Android 9를 실행하는 기기는 ID 및 이동통신사 이름을 제공할 수 있도록 가입된 이동통신사 정보&quot; data-og-host=&quot;source.android.com&quot; data-og-source-url=&quot;https://source.android.com/docs/core/connect/carrierid?hl=ko&quot; data-og-url=&quot;https://source.android.com/docs/core/connect/carrierid?hl=ko&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://source.android.com/docs/core/connect/carrierid?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://source.android.com/docs/core/connect/carrierid?hl=ko&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;이동통신사 ID &amp;nbsp;|&amp;nbsp; Android 오픈소스 프로젝트 &amp;nbsp;|&amp;nbsp; Android Open Source Project&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이동통신사 ID 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Android 9를 실행하는 기기는 ID 및 이동통신사 이름을 제공할 수 있도록 가입된 이동통신사 정보&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;source.android.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;p data-ke-size=&quot;size16&quot;&gt;위 링크를 확인해보면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MVNO, MNO 를 MCC 와 MNC 및 MVNO 정보를 특정 이동통신사에 매핑을하여, 구성된 파일을 가지고 통신사 정보를 확인하는 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 이 정보는 지속적으로 추가되는 통신사가 생기면 파일관리가 필요하며, 신뢰할 수 있는 정보라고 확신할 수 없기에 좋은 방법은 아니다 라는 판단을 내렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 아직 MVNO와 MNO 구분이 어려워 어떤 방식으로 해야할 지 고민해봐야 할 거 같다.&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;추가로, 아래 링크를 확인하면, MCC + MNC 를 가지고 통신사 3사를 구분할 수 있으니 확인해보면 좋을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://shga.kr/archives/158&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://shga.kr/archives/158&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712147856476&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;LTE 망에서 사용되는 ID 체계(PLMN = MCC + MNC) &amp;ndash; 가석현&quot; data-og-description=&quot;&quot; data-og-host=&quot;shga.kr&quot; data-og-source-url=&quot;https://shga.kr/archives/158&quot; data-og-url=&quot;https://shga.kr/archives/158&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://shga.kr/archives/158&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://shga.kr/archives/158&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;LTE 망에서 사용되는 ID 체계(PLMN = MCC + MNC) &amp;ndash; 가석현&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;shga.kr&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;p data-ke-size=&quot;size16&quot;&gt;정리하자면,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3사 알뜰폰(MVNO)도 위에서 적어놓은 정보와 동일하게 값이 추출할 것으로 판단된다. &lt;span style=&quot;color: #9d9d9d;&quot;&gt;(KT 는 동일하다.)&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;</description>
      <category>Mobile App/Android</category>
      <category>AOS</category>
      <category>MNO</category>
      <category>MVNO</category>
      <category>networkOperatorName</category>
      <category>안드로이드</category>
      <category>이동통신사</category>
      <author>후추부</author>
      <guid isPermaLink="true">https://devnuts.tistory.com/255</guid>
      <comments>https://devnuts.tistory.com/255#entry255comment</comments>
      <pubDate>Wed, 3 Apr 2024 21:22:26 +0900</pubDate>
    </item>
    <item>
      <title>[안드로이드] SMS Retriever API 내부앱공유에서 안되는 이유 (Debug Hash 값, Release Hash 값)</title>
      <link>https://devnuts.tistory.com/254</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;SMS Retriever API 를 이용하여 본인인증 인증번호를 App 에서 Callback 받는 로직을 만든 적이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://devnuts.tistory.com/253&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://devnuts.tistory.com/253&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712140308312&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;[안드로이드] SMS Retriever API 자동입력하는 방법은? (*Android Hash Key 가져오기 *KMC 등 본인확인 기관 &quot; data-og-description=&quot;SMS Retriever API 를 이용하여 본인인증 인증번호를 App 에서 문자로 받은 인증번호를 Callback 받아 화면에 바로 노출시킬 수 있다. 아래 링크에 사용 방법이 잘 설명되어 있으니, 보면 좋을 것 같다. ht&quot; data-og-host=&quot;devnuts.tistory.com&quot; data-og-source-url=&quot;https://devnuts.tistory.com/253&quot; data-og-url=&quot;https://devnuts.tistory.com/253&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/c6LrPS/hyVJZKjMvA/KtumlwRQsBtfDjBTehDdrK/img.jpg?width=512&amp;amp;height=269&amp;amp;face=0_0_512_269,https://scrap.kakaocdn.net/dn/S84M1/hyVJQ7G6RN/xchPFBj2VY6UJefg8NaBoK/img.jpg?width=512&amp;amp;height=269&amp;amp;face=0_0_512_269&quot;&gt;&lt;a href=&quot;https://devnuts.tistory.com/253&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://devnuts.tistory.com/253&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/c6LrPS/hyVJZKjMvA/KtumlwRQsBtfDjBTehDdrK/img.jpg?width=512&amp;amp;height=269&amp;amp;face=0_0_512_269,https://scrap.kakaocdn.net/dn/S84M1/hyVJQ7G6RN/xchPFBj2VY6UJefg8NaBoK/img.jpg?width=512&amp;amp;height=269&amp;amp;face=0_0_512_269');&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;[안드로이드] SMS Retriever API 자동입력하는 방법은? (*Android Hash Key 가져오기 *KMC 등 본인확인 기관&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;SMS Retriever API 를 이용하여 본인인증 인증번호를 App 에서 문자로 받은 인증번호를 Callback 받아 화면에 바로 노출시킬 수 있다. 아래 링크에 사용 방법이 잘 설명되어 있으니, 보면 좋을 것 같다. ht&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;devnuts.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;p data-ke-size=&quot;size16&quot;&gt;위와 같이 만들었고, 테스트를 하려고 했는데 이상하게 내부 앱공유에서 수신문자 Text 가 콜백이 들어오질 않는다.&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;분명 나는 Android Studio 디버깅 모드에서도 잘 동작했고, Release 로 말아서 adb install 을 통해 앱 설치를 했을 때도 정상적을 콜백이 됐지만, Release 로 앱을 만 뒤, 사업팀에 테스트 목적으로 전달할 때 이러한 이슈가 발생했다.&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;일단, 내가 시도했던 방법은 이곳저곳 찾아보니 Debug 용 Hash 값과 Release 용 Hash 값이 다르다는 말을 보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 생각했던 건, 내가 뽑아낸 Hash 값이 Debug 모드라서 콜백으로 텍스트가 안 들어오는 걸까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;(e.g 나는 구글 Doc 에서 제공해준 AppSignatureHelper 를 이용하여 Hash 값을 추출했다.)&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;a href=&quot;https://stackoverflow.com/questions/51365778/how-to-generate-11-char-hash-key-for-sms-retriever-with-google-app-signing/55829661#55829661&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://stackoverflow.com/questions/51365778/how-to-generate-11-char-hash-key-for-sms-retriever-with-google-app-signing/55829661#55829661&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712140547547&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;How to generate 11 char hash key for Sms Retriever with Google App signing&quot; data-og-description=&quot;I had generated the 11 char hash using the AppSignatureHelper class. But after uploading the apk to play store, they hash doesn't work anymore. And I found out that Play replaces the key with anoth...&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/51365778/how-to-generate-11-char-hash-key-for-sms-retriever-with-google-app-signing/55829661#55829661&quot; data-og-url=&quot;https://stackoverflow.com/questions/51365778/how-to-generate-11-char-hash-key-for-sms-retriever-with-google-app-signing&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bnL9QC/hyVGI4xwEy/bbV5V0Arru5jRI36xail00/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316,https://scrap.kakaocdn.net/dn/b9AlWp/hyVJ19cLcB/eNymRnTWM7ykzOBIR2GbWK/img.png?width=2920&amp;amp;height=940&amp;amp;face=0_0_2920_940,https://scrap.kakaocdn.net/dn/k0x3Y/hyVJ1ajkmc/qNqUW0eN9BxbCvd9pl1se1/img.png?width=1363&amp;amp;height=652&amp;amp;face=0_0_1363_652&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/51365778/how-to-generate-11-char-hash-key-for-sms-retriever-with-google-app-signing/55829661#55829661&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://stackoverflow.com/questions/51365778/how-to-generate-11-char-hash-key-for-sms-retriever-with-google-app-signing/55829661#55829661&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bnL9QC/hyVGI4xwEy/bbV5V0Arru5jRI36xail00/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316,https://scrap.kakaocdn.net/dn/b9AlWp/hyVJ19cLcB/eNymRnTWM7ykzOBIR2GbWK/img.png?width=2920&amp;amp;height=940&amp;amp;face=0_0_2920_940,https://scrap.kakaocdn.net/dn/k0x3Y/hyVJ1ajkmc/qNqUW0eN9BxbCvd9pl1se1/img.png?width=1363&amp;amp;height=652&amp;amp;face=0_0_1363_652');&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;How to generate 11 char hash key for Sms Retriever with Google App signing&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;I had generated the 11 char hash using the AppSignatureHelper class. But after uploading the apk to play store, they hash doesn't work anymore. And I found out that Play replaces the key with anoth...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;stackoverflow.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;p data-ke-size=&quot;size16&quot;&gt;아래 stackoverflow.com 에서 알려준대로 하면 release Hash 값을 뽑아낼 수 있다고해서 내가 뽑아 놓은 Hash 값과 비교를 해보았다.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Release Hash 값 추출하는 순서 (구글스토어에 앱 출시가 된 상태)&lt;/b&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Google console 로 들어가 '앱 서명' 카테고리에 진입&lt;/li&gt;
&lt;li&gt;앱 서명 인증서(.der 파일) 다운로드&lt;/li&gt;
&lt;li&gt;.der 파일을 .jks 파일로 변환하는 작업을 거쳐야 함.&lt;/li&gt;
&lt;li&gt;.jks Keystore 를 가지고 앱 사이닝 작업&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;&lt;b&gt;.der file &amp;gt; .jks file 변환&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712141406573&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;keytool -importcert -alias YOUR_ALIAS -file deployment_cert.der -keystore certificate.jks -storepass YOUR_PASSWORD&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;.jks Keystore 로 사이닝 진행&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712141519871&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;keytool -exportcert -alias YOUR_ALIAS -keystore certificate.jks | xxd -p | tr -d &quot;[:space:]&quot; | xargs echo -n YOUR_APP_PACKAGE_NAME | shasum -a 256 | tr -d &quot;[:space:]-&quot; | xxd -r -p | base64 | cut -c1-11&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.jks Keystore 터미널 명령어가 다른 거랑 많이 다를 것이다. 몇 군데 수정해서 내가 다시 짠 코드니, 참고하면 좋을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 나는 Mac 유저이고, 다양한 블로그에서 안내해준 명령어를 쳐도 아래와 같이 나왔기 때문에 몇 군데 수정을 한 것이다.&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;Screenshot 2024-04-03 at 7.53.29 PM.png&quot; data-origin-width=&quot;414&quot; data-origin-height=&quot;113&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDI0ym/btsGmNrhUPF/TDAuKyBBczN6RKva5Ksyok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDI0ym/btsGmNrhUPF/TDAuKyBBczN6RKva5Ksyok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDI0ym/btsGmNrhUPF/TDAuKyBBczN6RKva5Ksyok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDI0ym%2FbtsGmNrhUPF%2FTDAuKyBBczN6RKva5Ksyok%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;414&quot; height=&quot;113&quot; data-filename=&quot;Screenshot 2024-04-03 at 7.53.29 PM.png&quot; data-origin-width=&quot;414&quot; data-origin-height=&quot;113&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;But? Hash 값이 동일하게 나오잖아?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Hash 값이 동일하게 나온다... 그러면 이게 문제가 아니잖아? 혼란에 빠졌다.&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;Google console 에 대한 지식이 많이 부족했다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 앱을 개발 후, 테스트를 위해 전달하는 방식이 여러가지라는 것을 알 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 비공개 테스트, 내부테스트, 내부앱공유, apk 로 전달, IDC 에 업로드하여 link 전달 등등&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;내부 앱공유는 앱 Signing 을 진행할 때, 새로운 keystore 를 이용하여 매번 사이닝을 진행할 때마다 Keystore 값이 달라진다는 사실&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blog_app.jpeg&quot; data-origin-width=&quot;1526&quot; data-origin-height=&quot;834&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cInfj5/btsGlzndVQd/Ugd1oENKZEEGHbtJ198kx1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cInfj5/btsGlzndVQd/Ugd1oENKZEEGHbtJ198kx1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cInfj5/btsGlzndVQd/Ugd1oENKZEEGHbtJ198kx1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcInfj5%2FbtsGlzndVQd%2FUgd1oENKZEEGHbtJ198kx1%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;547&quot; height=&quot;299&quot; data-filename=&quot;blog_app.jpeg&quot; data-origin-width=&quot;1526&quot; data-origin-height=&quot;834&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;위 사진을 보면 저렇게 나와있었고, Doc 을 꼼꼼히 읽어야한다는 사실을 이번에 또 느꼈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 내부 테스트를 IDC 에 업로드하여 Link 를 전달하는 방식을 택했고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상 동작하는 걸 확인했다.&lt;/p&gt;</description>
      <category>Mobile App/Android</category>
      <category>Android</category>
      <category>corotine</category>
      <category>debug hash</category>
      <category>Flow</category>
      <category>hash</category>
      <category>release hash</category>
      <category>SMS</category>
      <category>SMSRetriever</category>
      <category>모바일 개발자</category>
      <category>자동입력</category>
      <author>후추부</author>
      <guid isPermaLink="true">https://devnuts.tistory.com/254</guid>
      <comments>https://devnuts.tistory.com/254#entry254comment</comments>
      <pubDate>Wed, 3 Apr 2024 20:10:23 +0900</pubDate>
    </item>
    <item>
      <title>[안드로이드] SMS Retriever API 자동입력하는 방법은? (*Android Hash Key 가져오기 *KMC 등 본인확인 기관 문의 )</title>
      <link>https://devnuts.tistory.com/253</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SMS Retriever API&lt;/b&gt; 를 이용하여 본인인증 인증번호를 App 에서 문자로 받은 인증번호를 Callback 받아 화면에 바로 노출시킬 수 있다.&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;a href=&quot;https://developers.google.com/identity/sms-retriever/overview?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developers.google.com/identity/sms-retriever/overview?hl=ko&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1710641508201&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;SMS Retriever API를 사용한 자동 SMS 인증
  
 &amp;nbsp;|&amp;nbsp; Credential Verification &amp;nbsp;|&amp;nbsp; Google for Developers&quot; data-og-description=&quot;이 페이지는 Cloud Translation API를 통해 번역되었습니다. 의견 보내기 SMS Retriever API를 사용한 자동 SMS 인증 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. SMS Re&quot; data-og-host=&quot;developers.google.com&quot; data-og-source-url=&quot;https://developers.google.com/identity/sms-retriever/overview?hl=ko&quot; data-og-url=&quot;https://developers.google.com/identity/sms-retriever/overview?hl=ko&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cJO2zo/hyVALlrIP8/NVyZukwo1XdVt5Ab6kGkc0/img.png?width=1200&amp;amp;height=675&amp;amp;face=0_0_1200_675,https://scrap.kakaocdn.net/dn/JvCsJ/hyVAHchPuV/Il9aF0lqTi9bdDzcE0n1hK/img.png?width=1380&amp;amp;height=520&amp;amp;face=0_0_1380_520&quot;&gt;&lt;a href=&quot;https://developers.google.com/identity/sms-retriever/overview?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developers.google.com/identity/sms-retriever/overview?hl=ko&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cJO2zo/hyVALlrIP8/NVyZukwo1XdVt5Ab6kGkc0/img.png?width=1200&amp;amp;height=675&amp;amp;face=0_0_1200_675,https://scrap.kakaocdn.net/dn/JvCsJ/hyVAHchPuV/Il9aF0lqTi9bdDzcE0n1hK/img.png?width=1380&amp;amp;height=520&amp;amp;face=0_0_1380_520');&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;SMS Retriever API를 사용한 자동 SMS 인증 &amp;nbsp;|&amp;nbsp; Credential Verification &amp;nbsp;|&amp;nbsp; Google for Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 페이지는 Cloud Translation API를 통해 번역되었습니다. 의견 보내기 SMS Retriever API를 사용한 자동 SMS 인증 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. SMS Re&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developers.google.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;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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;SMS Retriever API 적용 순서&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 우선 기획팀이 SMS Retrierver 기능을 적용할 수 있게 본인확인 기관(KMC, 모빌리언스 등등) 에 문의를 넣어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 안드로이드 개발자는 현 앱이 상용화가 되어있다면, 구글 앱스토어에 올라가 있는 해당 앱에 Hash Key 값이 존재하는데 그 값을 추출해야 한다. 위 Hash Key 값을 추출하여 본인확인 기관 측에 원하는 문구를 정리하여 문의를 하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 그 이후는 클라이언트 개발자와 서버 개발자와 API 관련하여 소통하면 될 것이다.&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 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;SMS Retriever API 에 사용할 Hash 추출하는 방법은?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추출 방법은 &lt;span style=&quot;color: #ee2323;&quot;&gt;2가지 방법&lt;/span&gt;이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단, 첫 번째로는 Terminel 내 명령어를 통해서 추출하는 방법이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째로는 내부 코드를 짜서 Logcat 을 이용하여 Hash 값을 찍어서 확인하는 방법이다.&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;a href=&quot;https://developers.google.com/identity/sms-retriever/verify?hl=ko#computing_your_apps_hash_string&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developers.google.com/identity/sms-retriever/verify?hl=ko#computing_your_apps_hash_string&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1710642169101&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;서버에서 SMS 인증 수행 &amp;nbsp;|&amp;nbsp; Credential Verification &amp;nbsp;|&amp;nbsp; Google for Developers&quot; data-og-description=&quot;이 페이지는 Cloud Translation API를 통해 번역되었습니다. 의견 보내기 서버에서 SMS 인증 수행 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 전화번호를 자동&quot; data-og-host=&quot;developers.google.com&quot; data-og-source-url=&quot;https://developers.google.com/identity/sms-retriever/verify?hl=ko#computing_your_apps_hash_string&quot; data-og-url=&quot;https://developers.google.com/identity/sms-retriever/verify?hl=ko&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/IqtwM/hyVAHwxBmG/10rRLUng9vH8HmYnKkCzFK/img.png?width=1200&amp;amp;height=675&amp;amp;face=0_0_1200_675&quot;&gt;&lt;a href=&quot;https://developers.google.com/identity/sms-retriever/verify?hl=ko#computing_your_apps_hash_string&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developers.google.com/identity/sms-retriever/verify?hl=ko#computing_your_apps_hash_string&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/IqtwM/hyVAHwxBmG/10rRLUng9vH8HmYnKkCzFK/img.png?width=1200&amp;amp;height=675&amp;amp;face=0_0_1200_675');&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;서버에서 SMS 인증 수행 &amp;nbsp;|&amp;nbsp; Credential Verification &amp;nbsp;|&amp;nbsp; Google for Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 페이지는 Cloud Translation API를 통해 번역되었습니다. 의견 보내기 서버에서 SMS 인증 수행 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 전화번호를 자동&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developers.google.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;p data-ke-size=&quot;size16&quot;&gt;MasOS 같은 경우에 명령어가 다르기 때문에 아래 명령어를 하나 더 남기도록 하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1710642619813&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;keytool -exportcert -alias [xxxx] -keystore [xxxx.keystore] | xxd -p | tr -d &quot;[:space:]&quot; | echo -n com.clipandbooks.sample.smsretriever `cat` | shasum -a 256 | tr -d &quot;[:space:]-&quot; | xxd -r -p | base64 | cut -c1-11&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 방법은 아래 링크를 남기겠다. 그것을 토대로 Hash 값을 뽑으면 될 것이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/googlearchive/android-credentials/blob/master/sms-verification/android/app/src/main/java/com/google/samples/smartlock/sms_verify/AppSignatureHelper.java&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/googlearchive/android-credentials/blob/master/sms-verification/android/app/src/main/java/com/google/samples/smartlock/sms_verify/AppSignatureHelper.java&lt;/a&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;Hash 값은 11자리로 되어있을 것이다. 해당 값을 문자 끝에 넣어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 이 외에도  SMS 형식의 규칙이 존재하여, 앱 콜백함수로 인증번호가 넘어갈 것이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Be no longer than 140 bytes&lt;/li&gt;
&lt;li&gt;Begin with the prefix &amp;lt;#&amp;gt;&lt;/li&gt;
&lt;li&gt;Contain a one-time code that the client sends back to your server to complete the verification flow&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 규칙을 따라 아래와 같은 예시로 문구를 정하면 될 것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1710642991568&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;#&amp;gt; [회사명] 본인확인을 위해 인증번호 [xxxxxx] 를 입력해주세요. FLw4Kt/c2eq&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;&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;이 외에, 서버 측과는 SMS 인증번호 발송, 재발송, 확인, 타임아웃 대기 등등 실제 서비스를 위해 맞춰야할 부분을 커뮤니케이션을 하면 될 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Mobile App/Android</category>
      <category>KMC</category>
      <category>SMS</category>
      <category>SMS Retriever</category>
      <category>모발리언스</category>
      <category>본인인증</category>
      <category>본인확인</category>
      <author>후추부</author>
      <guid isPermaLink="true">https://devnuts.tistory.com/253</guid>
      <comments>https://devnuts.tistory.com/253#entry253comment</comments>
      <pubDate>Sun, 17 Mar 2024 11:39:03 +0900</pubDate>
    </item>
    <item>
      <title>[안드로이드] release 해서 앱 실행하면 왜 crash 가 발생할까? (ProGuard leads to NullPointerException)</title>
      <link>https://devnuts.tistory.com/252</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;겪은 이슈&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WebView 를 이용하여 하이브리드 App 을 개발하고, release 로 .apk 를 말아 사업팀에 전달하다 발생한 이슈였다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_2700.jpeg&quot; data-origin-width=&quot;2732&quot; data-origin-height=&quot;734&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDC9hC/btsFfxrksew/IP8uLskWMdUAmW6Zsnlmdk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDC9hC/btsFfxrksew/IP8uLskWMdUAmW6Zsnlmdk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDC9hC/btsFfxrksew/IP8uLskWMdUAmW6Zsnlmdk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDC9hC%2FbtsFfxrksew%2FIP8uLskWMdUAmW6Zsnlmdk%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;2732&quot; height=&quot;734&quot; data-filename=&quot;IMG_2700.jpeg&quot; data-origin-width=&quot;2732&quot; data-origin-height=&quot;734&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;b&gt;WebViewClient&lt;/b&gt; 쪽에서 url 이 Null 이 발생하여 &lt;b&gt;NullPointerException&lt;/b&gt; 이 발생하는 &lt;span style=&quot;color: #ee2323;&quot;&gt;Error&lt;/span&gt; 만 발생했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;WebViewClient.class&lt;/b&gt; 83 줄에는 아래와 같은 코드가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1708826345568&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    return super.shouldOverrideUrlLoading(view, request);
}&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;저 부분에서 왜 Null 이 발생했던 걸까?? Why?&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;이슈 해결&lt;/b&gt;&lt;/span&gt;&lt;/h3&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;pre id=&quot;code_1708826793506&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;android {
    // ...
    buildTypes {
        debug {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                    'proguard-rules.txt',
                    'proguard-rules.debug.txt'
            debuggable true
        }
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                    'proguard-rules.txt'
        }
    }
}&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;build.gradle 파일 내, 소스에서 buildTypes 중에 release minifyEnabled 'false' 를 하게 되면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;release 시에 &lt;span style=&quot;color: #ee2323;&quot;&gt;Crash&lt;/span&gt; 가 발생하지 않았다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어?? 모지? &lt;b&gt;Proguard&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;일단 내 소스는 &lt;b&gt;WebViewClient&lt;/b&gt; 를 커스텀해서 사용하고 있었고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;shouldOverrideUrlLoading&lt;/b&gt; 함수를 오버라이딩 하여, 로그를 찍으면서 해당 웹뷰 화면 전환 간 Url 이 잘 찍히는지 확인하는 소스가 있었다. 해당 소스는 아래 Util 쪽, Logger Class 를 이용하여 Log tracking 을 했다.&lt;/p&gt;
&lt;pre id=&quot;code_1708826479386&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private static void Logger(int priority, String msg) {
    if (GiftshopInfo.LOGGER) {
        StringBuilder msgBuilder = new StringBuilder();
        msgBuilder.append(&quot;[FORSHOP_LOG]&quot;).append(&quot;[&quot;).append(Thread.currentThread().getStackTrace()[4].getMethodName())
                .append(&quot;()&quot;).append(&quot;]&quot;).append(&quot; &quot;).append(msg)
                .append(&quot; (&quot;).append(Thread.currentThread().getStackTrace()[4].getFileName()).append(&quot;:&quot;)
                .append(Thread.currentThread().getStackTrace()[4].getLineNumber()).append(&quot;)&quot;);

        Log.println(priority, Thread.currentThread().getStackTrace()[4].getFileName().replace(&quot;.java&quot;, &quot;&quot;), msgBuilder.toString());
    }
}&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;그러면서 생각했던 건,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어? 난독화를 하게 되면 &lt;b&gt;Null Exception&lt;/b&gt; 이 발생하니깐, 난독화 이후에 Class 를 찾지 못하는 이슈일까?&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;난독화를 하면, 소스 클래스가, a.b.c.d.e.class 이런식으로 소스파일 명들이 바뀌게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러다보니 위 Logger Class 내에서 getFileName() 이런 함수를 사용하게 될 경우, 난독화 이전 원하는 Class 를 찾지 못해서 발생한 &lt;span style=&quot;color: #ee2323;&quot;&gt;Error&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;오버라이딩해서 사용했던, Log 소스 한 줄을 주석하니, release 시에, &lt;span style=&quot;color: #ee2323;&quot;&gt;Crash&lt;/span&gt; 가 발생되지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참.. 난독화 관련하여 공부 안한 티가 났다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;난독화란?&lt;/span&gt;&lt;/b&gt;&lt;/h3&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;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앱 소스 코드를 분석하기 어렵게 만들기 위해 앱 소스 내에서 난독화 기술을 사용하게 된다. 그 중 Proguard 를 난 사용했다.&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;p data-ke-size=&quot;size16&quot;&gt;보안 수준을 높일 수 있기 때문에 난독화한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 Google Play Store 를 통해서 Android 앱을 누구나 안드로이드 폰 기종으로 설치를 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;누구나 자유롭게 해당 앱을 다로드 받아, APK 파일을 추출하는 건 가능하다.&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;이 APK 파일을 디컴파일(Decompile) 을 하여, 소스코드를 보는 것도 가능하다.&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;여기서 사용했던, Proguard 는 식별자 난독화(Renaming) 을 지원하고,&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;ex&lt;/b&gt;. a,b,c, ac, k 등)&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;</description>
      <category>Mobile App/Android</category>
      <category>.apk</category>
      <category>Crash</category>
      <category>proguard</category>
      <category>release</category>
      <category>난독화</category>
      <category>프로가드</category>
      <author>후추부</author>
      <guid isPermaLink="true">https://devnuts.tistory.com/252</guid>
      <comments>https://devnuts.tistory.com/252#entry252comment</comments>
      <pubDate>Sun, 25 Feb 2024 11:25:25 +0900</pubDate>
    </item>
    <item>
      <title>[안드로이드] java. lang. IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time. (Room Update)</title>
      <link>https://devnuts.tistory.com/251</link>
      <description>&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;흔한 이슈&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_0621.jpeg&quot; data-origin-width=&quot;2266&quot; data-origin-height=&quot;1190&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sf08D/btsEQPRX8HB/TVo2TaHUvu8N6XoxSz8Ms0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sf08D/btsEQPRX8HB/TVo2TaHUvu8N6XoxSz8Ms0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sf08D/btsEQPRX8HB/TVo2TaHUvu8N6XoxSz8Ms0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fsf08D%2FbtsEQPRX8HB%2FTVo2TaHUvu8N6XoxSz8Ms0%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;2266&quot; height=&quot;1190&quot; data-filename=&quot;IMG_0621.jpeg&quot; data-origin-width=&quot;2266&quot; data-origin-height=&quot;1190&quot;/&gt;&lt;/span&gt;&lt;/figure&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;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위 Error 를 해석하면 무엇일까?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;UI 가 장시간 Lock 이 될 수 있기 때문에 기본 스레드에서 데이터베이스에 허용시킬 수 없습니다. 라는 뜻.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&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; UI 변경이 이루어지는 작업일 경우, UI(main) 스레드를 사용하지말라는 이야기다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;장시간 UI 가 멈추는 상황일 때, ANR이 발생해 앱이 죽을 수 있다. 따라서 다른 스레드를 이용해야 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;겪은 이슈&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Room 을 이용하여 데이터를 저장했고,&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;저장한 데이터를 Update 하여 사용자 화면(UI)에 보이는 데이터가 바뀌어야 했다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;CRUD 중, Update와 Delete 하는 부분에서 위와 같은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&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;이슈가 발생한 코드는 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1707830890159&quot; class=&quot;kotlin&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;fun updateCoupon(coupon: Coupon) {
    viewModelScope.launch {
        updateCouponUseCase(coupon)
    )
}&lt;/code&gt;&lt;/pre&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;&amp;nbsp;&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;이슈 해결&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Room 라이브러리를 이용하여 데이터베이스를 이용할 땐,&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;백그라운드 스레드에서 DB 작업을 수행해야 했다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Update와 Delete 하는 작업이 Select 와 Insert 보다 더 오래걸려 네트워크 속도가 좀 더 빠른 CoroutineScope 를 사용했다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;다만, memory leak 이 걱정되는 부분이 있어, 이 부분은 훗날 &lt;b&gt;트레이드 오프&lt;/b&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;Dispatchers.IO 를 이용하여 아래와 같이 코드를 작성했다.&lt;/p&gt;
&lt;pre id=&quot;code_1707830890161&quot; class=&quot;kotlin&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;fun updateCoupon(coupon: Coupon) {
    CoroutineScope(Dispatchers.IO).launch {                                                       
        updateCouponUseCase(coupon)                               
    }                                                                                             
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;viewModelScope VS CoroutineScope 차이는?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;viewModelScope 는 안드로이드에서 제공하는 ViewModel 을 사용할 시, 해당 스코프를 사용할 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ViewModel 이 destroy 될 때, 자식 coroutine 들을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;자동으로 취소&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;이는 memory leak, 알지 못하는 백그라운드 작업이 지속적으로 도는 상황에서 리소스 방지를 할 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그 이유는 Fragment 와 ViewModel 이 연결되어 있고, Fragment 와 ViewModel 이 생명주기가 같으니 해당 뷰가 지워질 때,&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ViewModel 이 destroy 이 되면서 모든 job 이 cancel 된다고 생각하면 된다.&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;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;CoroutineScope 를 ViewModel 에서 사용한다면, &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;onCleard 함수에서 scope 의 취소&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;만약 안드로이드 구성요소(Activity, Fragment, ViewModel) 의 Lifecycle 에 따라 올바로 할당 해제되지 않는다면 해제되어야 하는 Job 들이 계속해서 동작해서 메모리 릭으로 이어질 수 있다.&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;고로, 수동으로 onCleard 함수를 이용하여 취소하기보단, viewModelScope 를 사용하여 자동으로 취소하는게 리소스 방지에 도움된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&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;viewModelScope 와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;CoroutineScope(Dispachers.IO) 네트워크 속도 차이&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;ref.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://velog.io/@tjeong/viewModelScope-%EA%B3%84%EC%86%8D-%EC%93%B8%EA%B9%8C&quot;&gt;https://velog.io/@tjeong/viewModelScope-%EA%B3%84%EC%86%8D-%EC%93%B8%EA%B9%8C&lt;/a&gt;&lt;/p&gt;</description>
      <category>Mobile App/Android</category>
      <category>a long period</category>
      <category>coroutinescope</category>
      <category>Room</category>
      <category>viewModelScope</category>
      <category>안드로이드</category>
      <author>후추부</author>
      <guid isPermaLink="true">https://devnuts.tistory.com/251</guid>
      <comments>https://devnuts.tistory.com/251#entry251comment</comments>
      <pubDate>Tue, 13 Feb 2024 22:29:03 +0900</pubDate>
    </item>
  </channel>
</rss>