<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>생각하는 개발자</title>
    <link>https://manorgass.tistory.com/</link>
    <description>죽어서 육신이 썩자마자 사람들에게 잊히고 싶지 않다면, 읽을 만한 가치가 있는 글을 쓰든지, 글로 남길 만한 가치가 있는 일을 하라.</description>
    <language>ko</language>
    <pubDate>Sun, 12 Apr 2026 21:48:34 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>디빌리</managingEditor>
    <image>
      <title>생각하는 개발자</title>
      <url>https://t1.daumcdn.net/cfile/tistory/99E6CA33599342C320</url>
      <link>https://manorgass.tistory.com</link>
    </image>
    <item>
      <title>Android :: Compose 기반의 BottomSheet 구현 방법</title>
      <link>https://manorgass.tistory.com/85</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;# 개요&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;523&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpjKGp/btsHKNkCuk3/NMskuToNKKdy7jjKitucw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpjKGp/btsHKNkCuk3/NMskuToNKKdy7jjKitucw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpjKGp/btsHKNkCuk3/NMskuToNKKdy7jjKitucw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpjKGp%2FbtsHKNkCuk3%2FNMskuToNKKdy7jjKitucw0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;523&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;523&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;바텀시트는 모바일 앱에서는 흔하게 볼 수 있는 컴포넌트 입니다. 당연하게도 Compose는 BottomSheet를 제공하고 있습니다. 구현 시 아래 3가지 컴포저블 중 하나를 사용하면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;ModalBottomSheet&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;ModalBottomSheetLayout&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;BottomSheetScaffold&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Android 개발자 Compose 가이드로 소개되어 있는 &lt;a href=&quot;https://developer.android.com/develop/ui/compose/components/bottom-sheets?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ModalBottomSheet&lt;/a&gt;부터 살펴보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;#1&amp;gt; ModalBottomSheet 를 사용해 바텀시트 노출하기&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;가장 간단한 형태로, 바텀시트가 노출되어야 하는 시점에 이 Composable이 노출되게 하면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1717341167749&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ModalBottomSheetScreen() {
    var isShowBottomSheet by remember { mutableStateOf(false) }

    Box(modifier = Modifier.fillMaxSize()) {
        Button(
            modifier = Modifier.align(Alignment.Center),
            onClick = { isShowBottomSheet = !isShowBottomSheet }
        ) {
            if (isShowBottomSheet) {
                ModalBottomSheet(
                    scrimColor = Color.Cyan.copy(alpha = 0.3f),
                    onDismissRequest = { isShowBottomSheet = !isShowBottomSheet },
                    content = { BottomSheetContent() }
                )
                Text(text = &quot;Hide Bottom Sheet&quot;)
            } else {
                Text(text = &quot;Show Bottom Sheet&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;심플하죠? 간단하지만 쓸 수 없습니다. 왜냐하면 이녀석, 하단 네비게이션 바를 가려버리거든요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1395&quot; data-origin-height=&quot;666&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Gp84W/btsHLVWumQT/0SyyplQSlqsjY8EKyBrjWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Gp84W/btsHLVWumQT/0SyyplQSlqsjY8EKyBrjWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Gp84W/btsHLVWumQT/0SyyplQSlqsjY8EKyBrjWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGp84W%2FbtsHLVWumQT%2F0SyyplQSlqsjY8EKyBrjWk%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;1395&quot; height=&quot;666&quot; data-origin-width=&quot;1395&quot; data-origin-height=&quot;666&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;스크린의 완전 바닥부터 노출이 됩니다. 아래와 같이 인셋을 설정하면 조금 낫습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #ef5369;&quot;&gt;&lt;b&gt; WindowCompat.setDecorFitsSystemWindows(window, false)&lt;/b&gt; &lt;/span&gt;&lt;/i&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-origin-width=&quot;1394&quot; data-origin-height=&quot;674&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oZvr2/btsHMehelnq/TP0PzPVKnS4KtGyE8cKBBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oZvr2/btsHMehelnq/TP0PzPVKnS4KtGyE8cKBBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oZvr2/btsHMehelnq/TP0PzPVKnS4KtGyE8cKBBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoZvr2%2FbtsHMehelnq%2FTP0PzPVKnS4KtGyE8cKBBK%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;1394&quot; height=&quot;674&quot; data-origin-width=&quot;1394&quot; data-origin-height=&quot;674&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;그래도 내려갈 때 하단 네비게이션 바를 가립니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mfoW8/btsHLte5nw3/xbEEJyHo0Wg4iNYB6DCAo0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mfoW8/btsHLte5nw3/xbEEJyHo0Wg4iNYB6DCAo0/img.webp&quot; data-alt=&quot;create by Chat GPT 4o&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mfoW8/btsHLte5nw3/xbEEJyHo0Wg4iNYB6DCAo0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmfoW8%2FbtsHLte5nw3%2FxbEEJyHo0Wg4iNYB6DCAo0%2Fimg.webp&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;1024&quot; height=&quot;1024&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;create by Chat GPT 4o&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;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;아직 포기하긴 이릅니다. 총알이 두발 남았거든요. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;#2&amp;gt; ModalBottomSheetLayout 를 사용해 바텀시트 노출하기&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;화면의 나머지 부분과의 상호작용을 차단하는 바텀시트를 제공한다. &lt;a href=&quot;https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#ModalBottomSheetLayout(kotlin.Function1,androidx.compose.ui.Modifier,androidx.compose.material.ModalBottomSheetState,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.ui.unit.Dp,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,kotlin.Function0)&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[링크]&lt;/a&gt;&lt;/span&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;모달 바텀시트를 제공하는 컨테이너 형태의 Composable 입니다. 바텀시트와 컨텐츠를 분리해서 선언할 수 있습니다. 이녀석, 네비게이션 바를 가리지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1717341699767&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@OptIn(ExperimentalMaterialApi::class)
@Composable
fun ModalBottomSheetLayoutScreen() {
    var skipHalfExpanded by remember { mutableStateOf(false) }
    val state = rememberModalBottomSheetState(
        initialValue = ModalBottomSheetValue.Hidden,
        skipHalfExpanded = skipHalfExpanded
    )
    val scope = rememberCoroutineScope()

    ModalBottomSheetLayout(
        sheetState = state,
        sheetContent = {
            LazyColumn {
                items(50) {
                    ListItem(
                        text = { Text(&quot;Item $it&quot;) },
                        icon = {
                            Icon(
                                Icons.Default.Favorite,
                                contentDescription = &quot;Localized description&quot;
                            )
                        }
                    )
                }
            }
        }
    ) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(16.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Row(
                Modifier.toggleable(
                    value = skipHalfExpanded,
                    role = Role.Checkbox,
                    onValueChange = { checked -&amp;gt; skipHalfExpanded = checked }
                )
            ) {
                Checkbox(checked = skipHalfExpanded, onCheckedChange = null)
                Spacer(Modifier.width(16.dp))
                Text(&quot;Skip Half Expanded State&quot;)
            }
            Spacer(Modifier.height(20.dp))
            Button(
                onClick = {
                    scope.launch {
                        state.show()
                    }
                }
            ) {
                Text(&quot;Click to show sheet&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;위 코드를 실행하시면 샘플 동작을 확인하실 수 있습니다. 주요 특징은 다음과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;반만 열림 상태 허용여부 설정 가능.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;바텀시트 핸들 제스쳐를 허용할 것인지 설정 가능.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p 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 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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;다시말해 [ 바텀시트의 확인 버튼 클릭 시에만 닫힘 ] 과 같은 동작을 구현하기 어렵습니다. 왜인지 모르겠으나 구글에서 관련 프로퍼티를 제공하지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;그렇다고 불가능 하진 않습니다. 시트 상태값 변경 Callback 을 받아 트릭을 사용해 처리가 가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;234&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k7zfd/btsHKmagyEy/3QRuWc2xUfxU2fFPe3ybrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k7zfd/btsHKmagyEy/3QRuWc2xUfxU2fFPe3ybrK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k7zfd/btsHKmagyEy/3QRuWc2xUfxU2fFPe3ybrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk7zfd%2FbtsHKmagyEy%2F3QRuWc2xUfxU2fFPe3ybrK%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;855&quot; height=&quot;234&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;234&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;#3&amp;gt; BottomSheetScaffold &lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;를 사용해 바텀시트 노출하기&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;화면의 메인 UI 영역과 공존하며 두 영역을 동시에 보고 상호작용 할 수 있다. &lt;a href=&quot;https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#BottomSheetScaffold(kotlin.Function1,androidx.compose.ui.Modifier,androidx.compose.material.BottomSheetScaffoldState,kotlin.Function0,kotlin.Function1,kotlin.Function0,androidx.compose.material.FabPosition,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.ui.unit.Dp,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.unit.Dp,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,kotlin.Function1)&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[링크]&lt;/a&gt;&lt;/span&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;모달이 아닌 바텀시트를 제공하는 컨테이너 형태의 Composable 입니다. 네이버 지도와 같은 서비스에서 마커 클릭 시 올라오는 형태의 바텀시트를 생각하시면 좋습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1717342526500&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BottomSheetScaffoldScreen() {
    val state = rememberBottomSheetScaffoldState(
        bottomSheetState = rememberStandardBottomSheetState(
            initialValue = SheetValue.Hidden,
            skipHiddenState = false
        )
    )
    val scope = rememberCoroutineScope()

    BottomSheetScaffold(
        scaffoldState = state,
        sheetContent = { BottomSheetContent() },
        // if set below setting, skip PartialExpand State.
        //sheetPeekHeight = 0.dp
    ) {
        Box {
            Column(
                modifier = Modifier.align(Alignment.Center),
                verticalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                Text(text = &quot;Current State is ${state.bottomSheetState.currentValue}&quot;)
                Button(
                    onClick = {
                        scope.launch {
                            state.bottomSheetState.show()
                        }
                    }
                ) {
                    Text(text = &quot;Show Bottom Sheet&quot;)
                }

                Button(
                    onClick = {
                        scope.launch {
                            state.bottomSheetState.hide()
                        }
                    }
                ) {
                    Text(text = &quot;Hide Bottom Sheet&quot;)
                }

                Button(
                    onClick = {
                        scope.launch {
                            state.bottomSheetState.expand()
                        }
                    }
                ) {
                    Text(text = &quot;Expand Bottom Sheet&quot;)
                }

                Button(
                    onClick = {
                        scope.launch {
                            state.bottomSheetState.partialExpand()
                        }
                    }
                ) {
                    Text(text = &quot;PartialExpand Bottom Sheet&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;바텀시트는 아래 3가지 상태를 가집니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Hidden&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Expanded&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;PariallyExpanded&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;기본적으로 Hidden 상태는 제공되지 않으며, state.hide() 호출시 Exception이 발생합니다. Hidden 상태를 쓰고자 하는 경우, 시트 상태 초기화 시 skipHiddenState를 명시적으로 false 로 초기화 해줘야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;577&quot; data-origin-height=&quot;167&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dxYj3i/btsHLFfiwOa/JEHr6O0SRTnZC0RgoqjiAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dxYj3i/btsHLFfiwOa/JEHr6O0SRTnZC0RgoqjiAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dxYj3i/btsHLFfiwOa/JEHr6O0SRTnZC0RgoqjiAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdxYj3i%2FbtsHLFfiwOa%2FJEHr6O0SRTnZC0RgoqjiAK%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;577&quot; height=&quot;167&quot; data-origin-width=&quot;577&quot; data-origin-height=&quot;167&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;또한, 반만 열림상태를 건너뛰고 싶은 경우 sheetPeekHeight 값을 0.dp 로 설정해주시면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;561&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bInAGy/btsHMvXscEA/JRQRbkfk8YAx7rMmA1Goak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bInAGy/btsHMvXscEA/JRQRbkfk8YAx7rMmA1Goak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bInAGy/btsHMvXscEA/JRQRbkfk8YAx7rMmA1Goak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbInAGy%2FbtsHMvXscEA%2FJRQRbkfk8YAx7rMmA1Goak%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;561&quot; height=&quot;168&quot; data-origin-width=&quot;561&quot; data-origin-height=&quot;168&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이녀석을 사용하면, 물론 몇가지 트릭이 필요하지만, View 기반의 바텀시트와 동일한 기능을 제공할 수 있습니다.&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;[&lt;a href=&quot;https://github.com/manorgass/ComposeBottomSheetSample&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;샘플코드 Github&lt;/a&gt;]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;# 마치며&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Compose 를 사용하면서 자주 하게되는 말이 있습니다.&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;&quot; 어? 이게 안된다고? &quot; 혹은 &quot; 어? 이게 된다고? &quot;&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;이번 BottomSheet 도입 작업은 위 두 감탄의 연속이었습니다. 하지만 이겨 내야합니다. Compose가 주는 생산성이 너무 강력해서 다시 View 기반으로 돌아갈 수 없거든요.&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;이 포스팅이 Compose로 바텀시트를 구현하겠다는 생각을 가진 분들에게 조금이나마 도움이 되길 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내용에 오류가 있거나 궁금한 점은 댓글로 남겨주세요. 감사합니다&lt;/p&gt;</description>
      <category>Programming/Android</category>
      <category>Android</category>
      <category>android compose</category>
      <category>compose bottomsheet</category>
      <category>안드로이드</category>
      <category>안드로이드 바텀시트</category>
      <category>안드로이드 컴포즈</category>
      <category>컴포즈 바텀시트</category>
      <author>디빌리</author>
      <guid isPermaLink="true">https://manorgass.tistory.com/85</guid>
      <comments>https://manorgass.tistory.com/85#entry85comment</comments>
      <pubDate>Mon, 3 Jun 2024 01:13:27 +0900</pubDate>
    </item>
    <item>
      <title>Android :: Android Studio 앱 실행 시 Run 탭 안보이게 하는방법</title>
      <link>https://manorgass.tistory.com/84</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k9mbv/btsjmClZF83/6nNsLb14Y4SLByQ75ecHd1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k9mbv/btsjmClZF83/6nNsLb14Y4SLByQ75ecHd1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k9mbv/btsjmClZF83/6nNsLb14Y4SLByQ75ecHd1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk9mbv%2FbtsjmClZF83%2F6nNsLb14Y4SLByQ75ecHd1%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;640&quot; height=&quot;426&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;426&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;이번 포스팅에서는 앱 실행 시 자동으로 표시되는 Run 탭이 표시되지 않게 설정하는 방법에 대해 설명합니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Run Tab이란?&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;앱 실행 시 자동으로 표시되는 탭으로 Application이 생성하는 output을 표시한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1718&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qCLf9/btsjk6uJtFP/l6TT0icIDep97jKCqB9Pi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qCLf9/btsjk6uJtFP/l6TT0icIDep97jKCqB9Pi1/img.png&quot; data-alt=&quot;앱 실행 시 자동으로 표시되는 Run Tool Window.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qCLf9/btsjk6uJtFP/l6TT0icIDep97jKCqB9Pi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqCLf9%2Fbtsjk6uJtFP%2Fl6TT0icIDep97jKCqB9Pi1%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;2000&quot; height=&quot;1718&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1718&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;앱 실행 시 자동으로 표시되는 Run Tool Window.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;필자의 경우 앱 실행을 통해 결과를 확인하는 경우가 많으며, 해당 탭이 뜰 때마다 수동으로 닫아주는 경우가 잦았다. (Alt + 4 연타..) 필자와 같은 불편함을 겪는 사람을 위해 감사하게도 앱 실행 시 Run 탭 표시 여부를 설정할 수 있다. 본 포스팅은 그 방법에 대한 설명이다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;앱 실행 시 Run 탭 표시가 안되게 하기&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;아래 순서를 따라 설정해보자.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;1. Android Studio 상단의 Run 선택창을 클릭한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l7nVa/btsjki3bJja/vz8QjY12ugMlyMz7N8BvNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l7nVa/btsjki3bJja/vz8QjY12ugMlyMz7N8BvNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l7nVa/btsjki3bJja/vz8QjY12ugMlyMz7N8BvNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl7nVa%2Fbtsjki3bJja%2Fvz8QjY12ugMlyMz7N8BvNK%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;461&quot; height=&quot;1336&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;2. Edit Configurations... 클릭.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;3. 좌측 패널의 `app` 을 선택하고 스크롤을 맨 아래로 내리면 체크 표시가 되어있는 Activate tool window 설정이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRzEUQ/btsjjB9KuKW/3v084PGDj59LDr8XJE9Kp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRzEUQ/btsjjB9KuKW/3v084PGDj59LDr8XJE9Kp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRzEUQ/btsjjB9KuKW/3v084PGDj59LDr8XJE9Kp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRzEUQ%2FbtsjjB9KuKW%2F3v084PGDj59LDr8XJE9Kp1%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;2000&quot; height=&quot;1280&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;4. 해당 체크박스를 해제.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;5. Apply 버튼을 눌러 적용.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&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;font-family: 'Nanum Gothic';&quot;&gt;위 순서대로 적용했다면 이제 앱 실행 시 Run 탭이 표시되지 않는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1716&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cClBKf/btsjlZV8MIU/Ga3PRxyYyKEHoeOQ8LG1XK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cClBKf/btsjlZV8MIU/Ga3PRxyYyKEHoeOQ8LG1XK/img.png&quot; data-alt=&quot;이제 귀찮게 닫을필요가 없어졌다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cClBKf/btsjlZV8MIU/Ga3PRxyYyKEHoeOQ8LG1XK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcClBKf%2FbtsjlZV8MIU%2FGa3PRxyYyKEHoeOQ8LG1XK%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;2000&quot; height=&quot;1716&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1716&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이제 귀찮게 닫을필요가 없어졌다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Programming/Android</category>
      <category>Android</category>
      <category>android studio</category>
      <category>android studio 설정</category>
      <category>런탭</category>
      <category>안드로이드</category>
      <category>안드로이드 스튜디오</category>
      <category>안드로이드 스튜디오 설정</category>
      <author>디빌리</author>
      <guid isPermaLink="true">https://manorgass.tistory.com/84</guid>
      <comments>https://manorgass.tistory.com/84#entry84comment</comments>
      <pubDate>Sat, 10 Jun 2023 16:49:50 +0900</pubDate>
    </item>
    <item>
      <title>Android :: Android Studio Live Template 적용방법</title>
      <link>https://manorgass.tistory.com/83</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sJjGH/btsdZzoTNJ1/QMMR8Z4YQVQ5r0XkCdYAV0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sJjGH/btsdZzoTNJ1/QMMR8Z4YQVQ5r0XkCdYAV0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sJjGH/btsdZzoTNJ1/QMMR8Z4YQVQ5r0XkCdYAV0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsJjGH%2FbtsdZzoTNJ1%2FQMMR8Z4YQVQ5r0XkCdYAV0%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;640&quot; height=&quot;426&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;426&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이번 포스팅에서는 Android Studio의 Live Template 에 대해 살펴보고 사용법에 대해 설명합니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;개요&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;작년 8월에 영상 중계 서비스를 제공하는 조직에서 부동산 플랫폼 서비스를 제공하는 조직으로 이직을 하게되었습니다. 서비스 분야가 다른만큼 주 업무에도 변화가 생겼는데요, 가장 큰 변화는 Core(비지니스로직) 중심의 개발에서 UI 중심의 개발로 주 업무가 변경되었 다는 점입니다.&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이전 조직에서는 빠르고 안전한 알고리즘 연구가 주 업무였다면, 현 조직에서는 크고 작은 기능들을 추가/삭제 하는 것이 주 업무입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동화를 할 순 없을까?&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p 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 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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;비지니스로직 구현과 같은 부분은 자동화 할 순 없지만, 프로퍼티 선언과 같은 간단한 일들은 자동화 할 순 없을까? 하는 생각을 하게되었고 곧 답을 찾게 되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;그 답은 바로 Live Template 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;Live Template이란?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Live Template은 Android Studio에서 제공하는 코드 템플릿 기능입니다. Live Template을 사용하면 개발자가 자주 사용하는 코드 구조를 미리 정의하여, 반복적인 작업에서 시간과 노력을 절약할 수 있습니다.&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;예를 들어, Live Template을 사용하여 레이아웃 XML 파일을 생성하면, 자동으로 데이터 바인딩과 적절한 레이아웃을 생성할 수 있습니다. 또한, Activity나 Fragment와 같은 모듈을 생성할 때도 사용할 수 있습니다.&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Live Template은 매우 유용한 기능이지만, 사용자가 직접 코드를 작성하는 것보다 미리 정의된 코드 구조를 사용하므로 코드의 일관성을 유지하기 위해 중요한 역할을 합니다. 따라서, Live Template을 사용하면 개발팀 전체의 코드 일관성을 유지하면서, 생산성을 높일 수 있습니다.&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;아마, 이미 여러분은 사용중에 있을겁니다. 예를들어 logd라고 치면 안드로이드 스튜디오에서는 아래와 같이 표시가 되며&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UnKIO/btsdZZniEIh/XmmZzH2OiFyGLFXpT67da1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UnKIO/btsdZZniEIh/XmmZzH2OiFyGLFXpT67da1/img.png&quot; data-alt=&quot;logd를 입력하면 해당 이름과 매칭되는 라이브 탬플릿을 사용할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UnKIO/btsdZZniEIh/XmmZzH2OiFyGLFXpT67da1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUnKIO%2FbtsdZZniEIh%2FXmmZzH2OiFyGLFXpT67da1%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;646&quot; height=&quot;196&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;196&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;logd를 입력하면 해당 이름과 매칭되는 라이브 탬플릿을 사용할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p 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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v48QD/btsd0uf3Lfx/sJlkqGq8jaeLwK1xKM4Bwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v48QD/btsd0uf3Lfx/sJlkqGq8jaeLwK1xKM4Bwk/img.png&quot; data-alt=&quot;기본으로 정의되어있는 logd 라이브 템플릿을 적용한 모습.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v48QD/btsd0uf3Lfx/sJlkqGq8jaeLwK1xKM4Bwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv48QD%2Fbtsd0uf3Lfx%2FsJlkqGq8jaeLwK1xKM4Bwk%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;631&quot; height=&quot;162&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;162&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;기본으로 정의되어있는 logd 라이브 템플릿을 적용한 모습.&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;Live Template 설정하기&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;i&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #1b711d;&quot;&gt;자주 사용하는 LiveData, StateFlow, SharedFlow 설정 방법에 대해 설명합니다.&lt;/span&gt;&lt;/i&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;우선, 안드로이드 스튜디오의 Settings &amp;gt; Editor &amp;gt; Live Templates 로 이동해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1325&quot; data-origin-height=&quot;902&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QGPbb/btsdZzvFW3r/srRCI5EfQykj2vRauULy5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QGPbb/btsdZzvFW3r/srRCI5EfQykj2vRauULy5K/img.png&quot; data-alt=&quot;우측 + 버튼 클릭 시 그룹 혹은 라이브 템플릿을 생성 할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QGPbb/btsdZzvFW3r/srRCI5EfQykj2vRauULy5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQGPbb%2FbtsdZzvFW3r%2FsrRCI5EfQykj2vRauULy5K%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;1325&quot; height=&quot;902&quot; data-origin-width=&quot;1325&quot; data-origin-height=&quot;902&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;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;우측 + 버튼을 눌러 적당한 이름의 Template 그룹을 생성해줍니다. 저의 경우는 Custom이라고 이름을 지었습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1126&quot; data-origin-height=&quot;875&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csBfKi/btsd0tuFQXy/aK9gnhakXurcP9xk5WTZaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csBfKi/btsd0tuFQXy/aK9gnhakXurcP9xk5WTZaK/img.png&quot; data-alt=&quot;Custom 이라는 이름의 LiveTemplate 그룹이 생성된 모습.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csBfKi/btsd0tuFQXy/aK9gnhakXurcP9xk5WTZaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsBfKi%2Fbtsd0tuFQXy%2FaK9gnhakXurcP9xk5WTZaK%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;1126&quot; height=&quot;875&quot; data-origin-width=&quot;1126&quot; data-origin-height=&quot;875&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Custom 이라는 이름의 LiveTemplate 그룹이 생성된 모습.&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;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;생성한 그룹을 클릭한 뒤 다시 우측의 + 버튼을 눌러 Live Template을 선택해줍니다. 그럼 빈 LiveTemplate 이 생성이 되는데, Abbreviation 에는 해당 라이브 템플릿을 호출할 때 쓰일 약어를 적어주고, Template text에는 생성할 코드 이름을 적어줍니다. &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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이번 예에서는 liveData를 사용할 것이므로 아래와 같이 입력해줍니다. &lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1683274191998&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private val _$NAME$ = androidx.lifecycle.MutableLiveData&amp;lt;$TYPE$&amp;gt;($VALUE$)
val $NAME$ : androidx.lifecycle.LiveData&amp;lt;$TYPE$&amp;gt; = _$NAME$&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1126&quot; data-origin-height=&quot;875&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dDBHjg/btsdYQEHELs/HubQVQAxYmOXebbipXfl40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dDBHjg/btsdYQEHELs/HubQVQAxYmOXebbipXfl40/img.png&quot; data-alt=&quot;liveData 라는 이름의 LiveData 프로퍼티 선언을 제공하는 LiveTemplate을 생성한 모습.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dDBHjg/btsdYQEHELs/HubQVQAxYmOXebbipXfl40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdDBHjg%2FbtsdYQEHELs%2FHubQVQAxYmOXebbipXfl40%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;1126&quot; height=&quot;875&quot; data-origin-width=&quot;1126&quot; data-origin-height=&quot;875&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;liveData 라는 이름의 LiveData 프로퍼티 선언을 제공하는 LiveTemplate을 생성한 모습.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;그리고 나서는 하단의 Change 버튼을 클릭해 해당 라이브템플릿이 적용될 문법(Context)를 설정해줍니다. 저의 경우에는 Kotlin 파일에서만 사용할 것이므로 아래와 같이 Kotlin 체크박스에 전체 선택을 해줬습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1127&quot; data-origin-height=&quot;883&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d9hAld/btsd0tIdyCP/DdcmqHOh34uLcZIdqEOF11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d9hAld/btsd0tIdyCP/DdcmqHOh34uLcZIdqEOF11/img.png&quot; data-alt=&quot;Kotlin 문법에서만 적용하겠다는 체크박스를 선택.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d9hAld/btsd0tIdyCP/DdcmqHOh34uLcZIdqEOF11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd9hAld%2Fbtsd0tIdyCP%2FDdcmqHOh34uLcZIdqEOF11%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;1127&quot; height=&quot;883&quot; data-origin-width=&quot;1127&quot; data-origin-height=&quot;883&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Kotlin 문법에서만 적용하겠다는 체크박스를 선택.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이렇게 설정을 마치고나면 실제 코드에서 live만 써도 방금 정의한 라이브템플릿이 선택지에 표시가 됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;617&quot; data-origin-height=&quot;96&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csqw6A/btsdY2LRz7c/dJVtFW8wAOk9ak6kW5opq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csqw6A/btsdY2LRz7c/dJVtFW8wAOk9ak6kW5opq1/img.png&quot; data-alt=&quot;짠! 방금 설정한 liveData 라이브 템플릿이 노출됩니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csqw6A/btsdY2LRz7c/dJVtFW8wAOk9ak6kW5opq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcsqw6A%2FbtsdY2LRz7c%2FdJVtFW8wAOk9ak6kW5opq1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;617&quot; height=&quot;96&quot; data-origin-width=&quot;617&quot; data-origin-height=&quot;96&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;짠! 방금 설정한 liveData 라이브 템플릿이 노출됩니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;여기서 Enter 키를 입력하면 Template text 로 정의한 코드가 자동으로 입력되는 것을 확인 하실 수 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;357&quot; data-origin-height=&quot;63&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYbCsC/btsdZIzokhE/MlHe9GF0XoX0Lmscl9If11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYbCsC/btsdZIzokhE/MlHe9GF0XoX0Lmscl9If11/img.png&quot; data-alt=&quot;liveData 라이브 템플릿을 적용한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYbCsC/btsdZIzokhE/MlHe9GF0XoX0Lmscl9If11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYbCsC%2FbtsdZIzokhE%2FMlHe9GF0XoX0Lmscl9If11%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;357&quot; height=&quot;63&quot; data-origin-width=&quot;357&quot; data-origin-height=&quot;63&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;liveData 라이브 템플릿을 적용한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Template text 에서 양쪽에 달러기호($) 로 정의한 내용은 빈 상태로 표시되며, 사용자가 직접 입력하는 부분입니다. 탭을 누르면 다음 달러기호 위치로 이동합니다.&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;제가 제공해드린 Template text 를 사용하시면, Backing Field와 외부에 노출할 immutable filed 의 이름과, 데이터 타입 그리고 초기값을 쉽게 설정 할 수 있습니다.&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;아래는 StateFlow와 SharedFlow 에 사용할 Template text입니다. 참고 부탁드립니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1683274369580&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// State Flow
private val _$NAME$ = kotlinx.coroutines.flow.MutableStateFlow&amp;lt;$TYPE$&amp;gt;($VALUE$)
val $NAME$ : kotlinx.coroutines.flow.StateFlow&amp;lt;$TYPE$&amp;gt; = _$NAME$&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1683274376664&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Shared Flow
private val _$NAME$ = kotlinx.coroutines.flow.MutableSharedFlow&amp;lt;$TYPE$&amp;gt;($VALUE$)
val $NAME$ : kotlinx.coroutines.flow.SharedFlow&amp;lt;$TYPE$&amp;gt; = _$NAME$&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;안드로이드 스튜디오의 라이브 템플릿을 사용하면 사전에 정의된 코드를 자동으로 생성할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;라이브 템플릿을 사용하면 보일러 플레이트 코드를 줄일 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;라이브 템플릿을 사용하면 코딩 컨벤션을 유지하는데 도움이 된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Live Data, State Flow, Shared Flow 와 같이 주로 Backing Field 와 함께 사용하는 프로퍼티 생성 시 사용하면 생산성 향상에 큰 도움이 된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Live Template 생성 시 유효한 문맥(Context) 를 지정할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;LIve Template Text에 달러 기호($) 를 이용해 사용자에게 입력받아야 할 영역을 구분 할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;마치며&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p 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 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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이런 작은 장치들이 별것 아닌 것 같아도, 쌓이고 쌓이다보면 유의미한 차이를 불러옵니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;끝까지 읽어주셔서 감사합니다. 좋은 하루 보내세요!&lt;/span&gt;&lt;/p&gt;</description>
      <category>Programming/Android</category>
      <category>Android</category>
      <category>android studio</category>
      <category>live template</category>
      <category>LiveTemplate</category>
      <category>라이브템플릿</category>
      <category>안드로이드</category>
      <category>안드로이드 스튜디오</category>
      <category>안드로이드 스튜디오 라이브 템플릿</category>
      <category>안스 템플릿</category>
      <author>디빌리</author>
      <guid isPermaLink="true">https://manorgass.tistory.com/83</guid>
      <comments>https://manorgass.tistory.com/83#entry83comment</comments>
      <pubDate>Fri, 5 May 2023 17:28:08 +0900</pubDate>
    </item>
    <item>
      <title>Android :: 위치정보 파헤치기 / FusedLocationProvider 개념과 사용법</title>
      <link>https://manorgass.tistory.com/82</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yLg2A/btq1Eoy9Vok/WGbyLmaeIRUTvMfx5tkLB1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yLg2A/btq1Eoy9Vok/WGbyLmaeIRUTvMfx5tkLB1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yLg2A/btq1Eoy9Vok/WGbyLmaeIRUTvMfx5tkLB1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyLg2A%2Fbtq1Eoy9Vok%2FWGbyLmaeIRUTvMfx5tkLB1%2Fimg.jpg&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이번 포스팅에서는 Android의 위치 산출방법에 대해 살펴보고 매우 정확한 위치정보를 제공해주는 FusedLocationProvider의 개념과 사용법에 대해 이야기합니다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;/span&gt;Android 기기의 위치정보를 획득하기 위해서는 위험 수준(dangerous level)의 권한인 ACCESS_COARSE_LOCATION 혹은 ACCESS_FINE_LOCATION 권한을 획득해야 합니다. 권한 관련 내용은 본 포스팅에서는 다루지 않으니, 관련 정보가 필요하신 분은 아래 포스팅을 참고해주세요.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://manorgass.tistory.com/74?category=471628&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Android 권한 파헤치기 글 보기&lt;/a&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;#1&amp;gt; 개요&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;잠시 제 이번 주 일상에 대해 이야기를 해볼까 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;커피머신이 필요해 당근 마켓을 통해 &lt;b&gt;같은 동네에 살고 있다고 인증된&lt;/b&gt; 어떤분과 중고 거래를 했습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;택시를 탈일이 생겨 카카오 택시를 앱을 통해&amp;nbsp; 통해 택시를 불러 목적지까지 편안하게 이동했습니다. 제 위치를 입력하지 않았는데 &lt;b&gt;기사분이 정확히&lt;/b&gt; 찾아오셨습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;지인들과 맛집으로 알려진 식당에서 맛있는 저녁식사를 했습니다. 골목에 있는 가게인데 네이버 지도 &lt;b&gt;길안내 서비스&lt;/b&gt;를 통해 정확히 찾아갔어요.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size18&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 data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;하지만 개발자 입장에서 이런 위치기반 서비스를 구현하려고 한다면, 정확한 위치를 제공하는 것이 복잡하고 어렵게 느껴지는데, 높은 정확도의 위치정보를 제공하기 위해서는 고려해야 할 것들이 많기 때문입니다. 기본적으로 Android OS에서 제공하는 위치정보 서비스를 사용하는 경우, 위치가 튀는 경우도 발생하고 건물 내부에서의 움직임을 정확히 파악할 수 없습니다. 또한 통신사 기지국 Cell의 가장자리 부분에서 위치가 정확하지 않은 경우도 발생합니다.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bz4p2H/btq1ByJiXxl/mc4qylM1s4vJG8pK3k1fZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bz4p2H/btq1ByJiXxl/mc4qylM1s4vJG8pK3k1fZk/img.png&quot; data-alt=&quot;통신사 Cell 이미지. 출처: 위키피디아&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bz4p2H/btq1ByJiXxl/mc4qylM1s4vJG8pK3k1fZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbz4p2H%2Fbtq1ByJiXxl%2Fmc4qylM1s4vJG8pK3k1fZk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;통신사 Cell 이미지. 출처: 위키피디아&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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 data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이런 개발자들의 고민들을 해결해주려는 걸까요? 구글은 2019 Google I/O 행사에서 FusedLocationProvider에 대한 스피치를 진행하였습니다. 발표 내용을 들어보면 알 수 있듯이 이 통합 위치 제공자를 통해 위에서 언급한 위치기반 서비스 구현 시 고민해야 했던 대부분의 문제들을 해결할 수 있습니다. 뿐만 아니라 이 녀석, 건물 내부에서의 움직임까지 정확히 파악합니다. 그래서 최근 Android 공식 사이트에서는 위치정보 획득 시 FusedLocationProvider를 사용할 것을 권장하고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;새로운 위치 제공자에 대한 설명에 앞서 Android OS에서 제공하는 위치정보 서비스(Location Service)가 위치정보를 제공하는 원리와 한계에 대해 살펴보도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;#2&amp;gt; 안드로이드의 위치 서비스 (Android Location Service)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Android OS 에서 제공하는 Location Service는 2가지의 위치 제공자(Location Provider)에 위치정보를 요청할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;1. GPS_PROVIDER&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;GNSS(Global Navigation Satellite System) 위성을 통해 위치정보를 파악합니다. 때문에 위성신호가 잡히지 않는 건물 내부에서는 위치정보 업데이트가 되지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;2. NETWORK_PROVIDER&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;통신사 기지국의 Cell 타워와 근처 WiFi Access Point 정보를 통해 위치를 파악합니다. 참고로, 셀타워나 WiFi AP의 위치정보는 Google에서 지속적으로 수집 및 업데이트를 하고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;GPS Provider는 GPS 위성 신호를 통해서 위치정보를 파악합니다. 이런 위성을 통한 위치 파악 기술은 잘 알려져 있지만 Network Provider는 어떻게 기지국 Cell이나 와이파이와 같은 네트워크 정보만으로 위치를 알 수 있는 걸까요?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Android 기기는 인터넷에 연결된 경우 Google 서버에 주기적으로 위치정보 및 인터넷 연결 정보를 업로드합니다. 그리고 이렇게 수집된 정보들을 기반으로 구글 서버에서는 나름의 네트워크 별 위치정보 테이블을 만들고 위치정보를 알려줍니다. 그리고 위치정보 수집에 대해서는 우리가 알게 모르게 이미 동의를 한 상태입니다. 세상에 공짜는 없는 법이죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;793&quot; data-origin-height=&quot;801&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kw6DQ/btq1Mp5P0RO/HMFjnz1xtLsXuj7iDhElk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kw6DQ/btq1Mp5P0RO/HMFjnz1xtLsXuj7iDhElk1/img.png&quot; data-alt=&quot;위치정보 수집에 대한 안내문구&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kw6DQ/btq1Mp5P0RO/HMFjnz1xtLsXuj7iDhElk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fkw6DQ%2Fbtq1Mp5P0RO%2FHMFjnz1xtLsXuj7iDhElk1%2Fimg.png&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;793&quot; data-origin-height=&quot;801&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;위치정보 수집에 대한 안내문구&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;예를 들어 Cell A 구역의 WiFi B에 연결한 기기들의 마지막 위치정보가 L1인 경우가 3건, L2인 경우가 2건인 경우, Network Provider는 &quot;이 와이파이에 연결했던 기기의 마지막 위치 정보가 L1인 경우가 제일 많았으니까 L1일 거야!&quot; 라며 위치정보를 L1으로 내려주는 식입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;3.png&quot; data-origin-width=&quot;827&quot; data-origin-height=&quot;879&quot; width=&quot;493&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bW49Cl/btq1ONkP6cv/lFoWHClKzfKQbkdS0fHLnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bW49Cl/btq1ONkP6cv/lFoWHClKzfKQbkdS0fHLnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bW49Cl/btq1ONkP6cv/lFoWHClKzfKQbkdS0fHLnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbW49Cl%2Fbtq1ONkP6cv%2FlFoWHClKzfKQbkdS0fHLnk%2Fimg.png&quot; data-filename=&quot;3.png&quot; data-origin-width=&quot;827&quot; data-origin-height=&quot;879&quot; width=&quot;493&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;따라서 Network Provider의 경우 건물 내부에 있는 경우에도 위치정보를 제공하지만, GPS Provider의 경우 위성신호가 잡히지 않기 때문에 정보를 제공하지 못합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;4.png&quot; data-origin-width=&quot;688&quot; data-origin-height=&quot;869&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bV86kB/btq1MqjmTND/iXFH6PSke1jGlfhFv1D4G1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bV86kB/btq1MqjmTND/iXFH6PSke1jGlfhFv1D4G1/img.png&quot; data-alt=&quot;건물 내부에서 위치정보 요청 시 GPS Provider에서는 위치정보를 획득하지 못한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bV86kB/btq1MqjmTND/iXFH6PSke1jGlfhFv1D4G1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbV86kB%2Fbtq1MqjmTND%2FiXFH6PSke1jGlfhFv1D4G1%2Fimg.png&quot; data-filename=&quot;4.png&quot; data-origin-width=&quot;688&quot; data-origin-height=&quot;869&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;건물 내부에서 위치정보 요청 시 GPS Provider에서는 위치정보를 획득하지 못한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;하지만 밖으로 나가면 얘기가 달라집니다. 외부에서 GPS_PROVIDER는 높은 정확도로 움직임을 업데이트하지만 NETWORK_PROVIDER는 AP에서 AP로 순간이동(?)을 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;#3&amp;gt; FusedLocationProvider(통합 위치 제공자) 란?&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;FusedLocationProvider는 LOCATION_SERVICE에서 해결하지 못한 GPS와 NETWORK 위치 제공자의 간극을 매워주기 위해 출시되었습니다. 뿐만 아니라 빌딩 섬에서의 GPS 외곡과 같은 현상도 보정해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;1.PNG&quot; data-origin-width=&quot;1563&quot; data-origin-height=&quot;616&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wOqGE/btq1KdZkzBi/cqSpfGKKid7Kuk1jCvWjWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wOqGE/btq1KdZkzBi/cqSpfGKKid7Kuk1jCvWjWk/img.png&quot; data-alt=&quot;건물 내/외부에서의 각 위치제공자 별 정확도 그래프&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wOqGE/btq1KdZkzBi/cqSpfGKKid7Kuk1jCvWjWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwOqGE%2Fbtq1KdZkzBi%2FcqSpfGKKid7Kuk1jCvWjWk%2Fimg.png&quot; data-filename=&quot;1.PNG&quot; data-origin-width=&quot;1563&quot; data-origin-height=&quot;616&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;건물 내/외부에서의 각 위치제공자 별 정확도 그래프&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;111111.png&quot; data-origin-width=&quot;1769&quot; data-origin-height=&quot;809&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckdhKZ/btq1KAfITI5/Mc6Es3JQwZ4xqQUEeX91Zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckdhKZ/btq1KAfITI5/Mc6Es3JQwZ4xqQUEeX91Zk/img.png&quot; data-alt=&quot;건물 내/외부에서 모두 좋은 정확도를 보여주는 FusedLocationProvider의 그래프&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckdhKZ/btq1KAfITI5/Mc6Es3JQwZ4xqQUEeX91Zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckdhKZ%2Fbtq1KAfITI5%2FMc6Es3JQwZ4xqQUEeX91Zk%2Fimg.png&quot; data-filename=&quot;111111.png&quot; data-origin-width=&quot;1769&quot; data-origin-height=&quot;809&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;건물 내/외부에서 모두 좋은 정확도를 보여주는 FusedLocationProvider의 그래프&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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 data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;725&quot; data-origin-height=&quot;1015&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dR9Ji6/btq1MqwUsxc/YwOrLw6Dd8rEl3dROV7hEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dR9Ji6/btq1MqwUsxc/YwOrLw6Dd8rEl3dROV7hEk/img.png&quot; data-alt=&quot;건물 내부에서 위치정보를 파악하는 FusedLocation의 알고리즘을 가시화한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dR9Ji6/btq1MqwUsxc/YwOrLw6Dd8rEl3dROV7hEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdR9Ji6%2Fbtq1MqwUsxc%2FYwOrLw6Dd8rEl3dROV7hEk%2Fimg.png&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;725&quot; data-origin-height=&quot;1015&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;건물 내부에서 위치정보를 파악하는 FusedLocation의 알고리즘을 가시화한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;위 사진에서 큰 회색원은 마지막으로 수집된 GPS 정보이고, 파란색 줄은 사용자의 움직임을 추적한 선입니다. 건물 내부에 들어갔다고 판단되면 똑똑한 FusedLocationProvider는 활용할 수 있는 모든 정보(WiFi AP, 기타 센서 등)를 종합해 사용자가 있을 것으로 예상되는 위치를 계산합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이렇게 계산된 위치들이 위 사진에서 작은 점들로 표시되어 있습니다. 점에 꼬리처럼 붙어있는 것은 예측되는 사용자의 방향입니다. 그리고 예측된 위치의 밀도가 가장 높은 좌표를 최종 사용자 위치로 판단합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;어떤가요? 정말 똑똑하죠? FusedLocationProvider에 대한 더 자세한 내용이 궁금하시면 아래 영상을 참고하세요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=MEjFW_tLrFQ&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/NSVFn/hyJK8GZghS/0vGnzcAZdYVk6VQqq9fAH0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=904_98_1024_230&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/MEjFW_tLrFQ&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption&gt;Google I/O 19 에서 발표한 FusedLocationProvider에 대한 스피치 영상&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;#4&amp;gt; FusedLocationProvider 를 사용한 위치정보 획득 방법&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;위에서 살펴본 것처럼 FusedLocationProvider가 위치를 계산하는 알고리즘이 매우 정밀한데 반해, 개발자가 위치를 획득하는 방법은 아주 간단합니다.&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfpMnf/btq1R8Xv5Md/B4AtSPc3tburdDt9Ymj2sK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfpMnf/btq1R8Xv5Md/B4AtSPc3tburdDt9Ymj2sK/img.png&quot; data-alt=&quot;그저.. 빛...&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfpMnf/btq1R8Xv5Md/B4AtSPc3tburdDt9Ymj2sK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfpMnf%2Fbtq1R8Xv5Md%2FB4AtSPc3tburdDt9Ymj2sK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;그저.. 빛...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이번 챕터에서는 FusedLocationProvider를 통해 마지막으로 알려진 위치를 얻는 방법과, 원하는 interval 주기로 위치 업데이트 정보를 요청하는 방법을 살펴보도록 하겠습니다. 코드만 봐도 이해가 될 것 같은 부분에는 딱히 설명을 하지 않았습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;프로젝트 종속성 설정&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;통합 위치 제공자(Fused Location Provider)는 Google Play Service의 Location API에서 제공합니다. 따라서 아래와 같이 프로젝트에 Google Play Service 종속성을 추가해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;프로젝트 수준의 Gradle 파일의 repositories 속성에 아래 저장소 추가&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;maven { url &quot;[&amp;lt;&lt;a href=&quot;https://maven.google.com&quot;&gt;https://maven.google.com&lt;/a&gt;&amp;gt;](&amp;lt;&lt;a href=&quot;https://maven.google.com/&quot;&gt;https://maven.google.com/&lt;/a&gt;&amp;gt;)&quot;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;모듈 (Application) 수준의 Gradle 파일에 아래 종속성 추가&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;implementation 'com.google.android.gms:play-services-location:17.1.0'&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;통합 위치 제공자 초기화&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1617529516839&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private lateinit var fusedLocationProviderClient: FusedLocationProviderClient

private fun initLocationClient() {
    fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context)

    val locationRequest = LocationRequest.create()?.apply {
        interval = 1000
        priority = LocationRequest.PRIORITY_HIGH_ACCURACY
    }

    val builder = LocationSettingsRequest.Builder()
        .addLocationRequest(locationRequest!!)
    val client = LocationServices.getSettingsClient(context)
    val task = client.checkLocationSettings(builder.build())
    task.addOnSuccessListener {
        Log.d(TAG, &quot;location client setting success&quot;)
    }

    task.addOnFailureListener {
        Log.d(TAG, &quot;location client setting failure&quot;)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;우선 원하는 형태의 Location Request를 생성하고, 해당 설정으로 위치 요청이 가능한지 확인해야 합니다. 위 코드에서 Location Request에 사용된 옵션에 대한 설명은 다음과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;interval: 업데이트 간격을 ms 단위로 설정합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;priority: 필요한 정확도를 설정하는 값으로 아래 4가지로 분류됩니다.&lt;/span&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;BALANCED_POWER_ACCURACY&lt;br /&gt;&lt;/b&gt;도시 블록 내의 위치 정밀도 요청. 정확도는 대략 100미터. Wi-Fi 정보와 휴대폰 기지국 위치를 사용할 수 있음. 대략적인 수준의 정확성으로 전력을 비교적 적게 사용함.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;HIGH_ACCURACY&lt;/b&gt; &lt;br /&gt;가장 정확한 위치를 요청. 이 설정을 사용하면 위치 서비스가 GPS를 사용하여 위치를 확인할 가능성이 높음.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;LOW_POWER&lt;/b&gt; &lt;br /&gt;도시 수준의 정밀도 요청. 대략 10킬로미터의 정확성. 아주 대략적인 수준의 정확성으로 전력을 더 적게 소비함.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;NO_POWER&lt;/b&gt; &lt;br /&gt;전력 소비에 별다른 영향을 미치지 않으면서 사용 가능한 경우 위치 업데이트를 수신하려면 이 설정을 사용. 해당 설정을 사용할 경우 앱에서 위치를 트리거하지 않고 다른 앱에서 트리거한 위치 정보를 가져다 씀.&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;위 코드에서는 priority를 HIGH_ACCURACY로 설정했습니다. 따라서 높은 품질의 위치정보는 기대할 수 있지만, 배터리 효율은 기대하기 어렵습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;마지막으로 알려진 위치 요청&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;아래 코드 스니펫은 마지막으로 알려진 위치 정보를 요청하는 코드입니다. 권한체크는 필수입니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1617529570868&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;fun requestLastLocation() {
  if (ActivityCompat.checkSelfPermission(
          context,
          Manifest.permission.ACCESS_FINE_LOCATION
      ) != PackageManager.PERMISSION_GRANTED &amp;amp;&amp;amp; ActivityCompat.checkSelfPermission(
          context,
          Manifest.permission.ACCESS_COARSE_LOCATION
      ) != PackageManager.PERMISSION_GRANTED
  ) {
      return
  }
  fusedLocationProviderClient.lastLocation
      .addOnSuccessListener { location -&amp;gt;
          listener.onLocationUpdated(location)
      }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;위치 업데이트 요청&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;아래 코드 스니팻은 interval(ms) 간격으로 주기적인 위치정보 업데이트를 요청하는 코드입니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1617529588567&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private lateinit var locationCallback: LocationCallback

private fun initLocationCallback() {
    locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult?) {
            locationResult ?: return
            for (location in locationResult.locations) {
                listener.onLocationUpdated(location)
                break
            }
        }
    }
}

fun startLocationUpdates() {
    if (ActivityCompat.checkSelfPermission(
            context,
            Manifest.permission.ACCESS_FINE_LOCATION
        ) != PackageManager.PERMISSION_GRANTED &amp;amp;&amp;amp; ActivityCompat.checkSelfPermission(
            context,
            Manifest.permission.ACCESS_COARSE_LOCATION
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        return
    }
    val locationRequest = LocationRequest.create()?.apply {
        interval = 1000
        priority = LocationRequest.PRIORITY_HIGH_ACCURACY
    }
    fusedLocationProviderClient.requestLocationUpdates(
        locationRequest,
        locationCallback,
        Looper.getMainLooper()
    )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;마치며&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;오늘은 통합 위치 제공자(Fused Location Provider)를 통한 위치정보 획득 방식에 대해 알아보았습니다. 구글이 Android OS의 Location Service를 업데이트하는 방식이 아닌 Google Player Service 중 하나인 FusedLocationProvider 사용을 권고하는 이유는 OS 버전에 종속되지 않고, 지속적으로 업데이트되는 위치 계산 알고리즘이 적용된, 최상의 품질의 위치정보를 제공하겠다는 의지로 보여집니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;끝까지 읽어주셔서 감사합니다. 좋은 하루 보내세요!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: right;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;본 포스팅에 사용된 코드 스니팻의 전체 코드는 아래 스니팻을 통해 확인 가능합니다.&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1617598930219&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;article&quot; data-og-title=&quot;FusedLocationProvider.kt&quot; data-og-description=&quot;GitHub Gist: instantly share code, notes, and snippets.&quot; data-og-host=&quot;gist.github.com&quot; data-og-source-url=&quot;https://gist.github.com/manorgass/9fcae660c973c7cd260fbc5e35386849&quot; data-og-url=&quot;https://gist.github.com/manorgass/9fcae660c973c7cd260fbc5e35386849&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fSYDP/hyJMjARF4e/yc8aVJUMCkVJk3RLoKQXQk/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640&quot;&gt;&lt;a href=&quot;https://gist.github.com/manorgass/9fcae660c973c7cd260fbc5e35386849&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://gist.github.com/manorgass/9fcae660c973c7cd260fbc5e35386849&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fSYDP/hyJMjARF4e/yc8aVJUMCkVJk3RLoKQXQk/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;FusedLocationProvider.kt&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;GitHub Gist: instantly share code, notes, and snippets.&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;gist.github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1617598950566&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;article&quot; data-og-title=&quot;LegacyLocationProvider.kt&quot; data-og-description=&quot;GitHub Gist: instantly share code, notes, and snippets.&quot; data-og-host=&quot;gist.github.com&quot; data-og-source-url=&quot;https://gist.github.com/manorgass/2356a44dacd3cec63d481c124da6ad72&quot; data-og-url=&quot;https://gist.github.com/manorgass/2356a44dacd3cec63d481c124da6ad72&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/toIBd/hyJMmqOKjz/10UZDdM0tfrofCFZltKaj1/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640&quot;&gt;&lt;a href=&quot;https://gist.github.com/manorgass/2356a44dacd3cec63d481c124da6ad72&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://gist.github.com/manorgass/2356a44dacd3cec63d481c124da6ad72&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/toIBd/hyJMmqOKjz/10UZDdM0tfrofCFZltKaj1/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;LegacyLocationProvider.kt&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;GitHub Gist: instantly share code, notes, and snippets.&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;gist.github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%; text-align: center;&quot;&gt;하트와 댓글작성은 필자에게 큰 힘이 됩니다!&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
      <category>Programming/Android</category>
      <category>Android</category>
      <category>Android FusedLocation</category>
      <category>android location service</category>
      <category>FusedLocationProvider</category>
      <category>Location</category>
      <category>안드로이드</category>
      <category>안드로이드 Location</category>
      <category>안드로이드 위치</category>
      <category>안드로이드 위치정보 획득</category>
      <category>통합위치제공자</category>
      <author>디빌리</author>
      <guid isPermaLink="true">https://manorgass.tistory.com/82</guid>
      <comments>https://manorgass.tistory.com/82#entry82comment</comments>
      <pubDate>Mon, 5 Apr 2021 14:11:30 +0900</pubDate>
    </item>
    <item>
      <title>Kotlin 기초강의#6 :: 분기처리와 열거형 / when, if, enum 살펴보기</title>
      <link>https://manorgass.tistory.com/81</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;kotlin.png&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;1200&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nIDwR/btqVIbyM797/cT5kdDwYqi8WFY4Lc2GOI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nIDwR/btqVIbyM797/cT5kdDwYqi8WFY4Lc2GOI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nIDwR/btqVIbyM797/cT5kdDwYqi8WFY4Lc2GOI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnIDwR%2FbtqVIbyM797%2FcT5kdDwYqi8WFY4Lc2GOI0%2Fimg.png&quot; data-filename=&quot;kotlin.png&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;1200&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt; &amp;nbsp; Java의 enum과 Kotlin의 enum은 비슷하지만 반드시 알아야 하는 차이점이 있습니다. 이와 더불어 코틀린에서 변화가 생긴 if와 새롭게 추가된 분기 처리를 위한 강력한 식(Expression)인 when에 대해 살펴보겠습니다.&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#1_ 들어가며&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;Programming을 하다보면 반드시 필요한 게 분기 처리입니다. 조건에 따른 처리를 명시함으로써 여러 예측 가능한 상황들에 유연하게 대처할 수 있기 때문입니다. 전통적인 프로그래밍 언어에서는 if문(statement)이나 switch문(statement)을 사용해서 이를 처리합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1612349611477&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if(input == 1) {
  // 구구단 1단 출력
} else if(input ==2) {
  // 구구단 2단 출력
} else {
  // 에러 메시지 출력
}

switch(input) {
  case 1: // 구구단 1단 출력
    break;
  case 2: // 구구단 2단 출력
    break;
  default: // 에러 메세지 출력
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kotlin에서는 if식(expression)과 when식(expression)을 통해 분기 처리가 가능합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1612349707762&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if(input == 1) {
  // 구구단 1단 출력
} else if(input == 2) {
  // 구구단 2단 출력
} else {
  // 에러 메세지 출력
}

when(input) {
  1 -&amp;gt; // 구구단 1단 출력
  2 -&amp;gt; // 구구단 2단 출력
  eles -&amp;gt; // 에러 메세지 출력
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;여기서 재미있는 점은 if가 자바에서는 문(statement) 이었지만 코틀린에서는 식(expression)이 되었다는 것인데요, 문과 식의 차이는 아래와 같으며 &lt;a href=&quot;https://manorgass.tistory.com/68&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;지난 포스팅&lt;/a&gt;에서도 설명한 바 있습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  문(statement)과 식(expression)의 구분&lt;br /&gt;...&amp;nbsp;&lt;br /&gt;식은 값을 만들어 내며 다른 식의 하위 요소로 계산에 참여할 수 있는 반면 문은 자신을 둘러싸고 있는 가장 안쪽 블록의 최상위 요소로 존재하며 아무런 값을 만들어내지 않는다는 차이가 있다.&amp;nbsp;&lt;br /&gt;...&lt;br /&gt;출처 : Kotlin in Action / page. 62&lt;/blockquote&gt;
&lt;p&gt;왜 Kotlin은 if에 대해 이런 변화를 주었을까요? 그리고 switch를 대신해 when을 제공하는 이유는 무엇일까요? 먼저 코틀린의 if와 when에 대해서 살펴보겠습니다. 그리고 분기 처리와 짝꿍처럼 붙어 다니는 Kotlin의 enum에 대해 이야기합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#2_ Kotlin의 if, 작지만 큰 변화&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;Kotlin의 if는 Java의 if와 사용 방법이 동일하지만 작은 차이가 있습니다. 그 차이는 바로 Java에서는 상태만 가지는 문(statement)인 반면, Kotlin의 if는 값을 반환하는 식(expression)이라는 것입니다. 때문에 Java에서 불가능했던 분기 처리를 통한 초기화가 Kotlin에서는 가능합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1612349998913&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// java
String userLevel;
if(id == 0) {
  userLevel = &quot;Administrator&quot;
} else if(id in 1 .. 10) {
  userLevel = &quot;Normal&quot;
} else {
  userLevel = &quot;Hacker&quot;
}

// kotlin
val userLevel = if(id == 0) {
  &quot;Administrator&quot;
} else if(id in 1 .. 10) {
  &quot;Normal&quot;
} else {
  &quot;Hacker&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Java에서라면 String 변수를 먼저 선언하고, if문 안에 3개의 대입문이 들어가야 했지만 Kotlin에서는 if를 통한 초기화가 가능합니다. userLevel이라는 변수가 Java에서는 4번, Kotlin에서는 1번 타이핑 되었습니다. 이 차이가 별것 아닌 것처럼 보이지만 중복을 제거한다는 것은 클린 코드 관점에서 엄청나게 큰 메리트입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;if식이 반환하는 값은 Block 안의 마지막 줄에 해당하는 값입니다. 따라서 아래와 같은 표현도 틀린 식이 아닙니다.&lt;/p&gt;
&lt;pre id=&quot;code_1612350234468&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val userLevel: String = if(id == 0) {
  println(&quot;user level is Admin&quot;)
  &quot;Administrator&quot; // 최종 리턴값은 블럭의 맨 마지막 줄이다
} else {
  println(&quot;Senpai Notice Me!&quot;)
  &quot;Unknown&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;또한 Kotlin에서는 if가 식이 됨에 따라 삼항연산자를 지원하지 않습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;420&quot; data-origin-height=&quot;315&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beStWR/btqVzRH8PA0/zCkUuOPHs96KDDUDSU4ZlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beStWR/btqVzRH8PA0/zCkUuOPHs96KDDUDSU4ZlK/img.png&quot; data-alt=&quot;삼항연산자가 사라져서 속상한 개발자.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beStWR/btqVzRH8PA0/zCkUuOPHs96KDDUDSU4ZlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeStWR%2FbtqVzRH8PA0%2FzCkUuOPHs96KDDUDSU4ZlK%2Fimg.png&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;420&quot; data-origin-height=&quot;315&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;삼항연산자가 사라져서 속상한 개발자.jpg&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;대신 if와 else를 통해 동일한 표현이 가능합니다. 개인적으로 삼항연산자의 표현이 귀여워서 즐겨 썼는데 아쉽네요.&lt;/p&gt;
&lt;pre id=&quot;code_1612350549396&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Java
int bigger = (a &amp;gt; b) ? a : b

// kotlin
val bigger = if(a &amp;gt; b) a else b&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;하지만 Kotlin의 if/else 식의 표현이 삼항연산자보다 더 직관적입니다. Java의 삼항 연산자는 &quot;A가 B보다 크냐? 그럼 A를 대입하고, 아니냐? 그럼 B를 넣어라.&quot;처럼 해석되는 반면 Kotlin의 if/else 식은 &quot;더 큰 수의 값은 만약 A가 B보다 크면 A고 아니면 B다.&quot;라는 영어문장처럼 해석되기 때문이죠.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;Untitled11.png&quot; data-origin-width=&quot;347&quot; data-origin-height=&quot;552&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blGnSd/btqVJRme2kp/0EQaginf65bdbvMVNe39h0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blGnSd/btqVJRme2kp/0EQaginf65bdbvMVNe39h0/img.png&quot; data-alt=&quot;if/else 식을 보고 납득한 개발자.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blGnSd/btqVJRme2kp/0EQaginf65bdbvMVNe39h0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblGnSd%2FbtqVJRme2kp%2F0EQaginf65bdbvMVNe39h0%2Fimg.png&quot; data-filename=&quot;Untitled11.png&quot; data-origin-width=&quot;347&quot; data-origin-height=&quot;552&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;if/else 식을 보고 납득한 개발자.jpg&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;프로그래밍을 하다보면 새로운 코드를 짜는 시간보다 기존 코드를 읽는 시간이 더 많습니다. 이럴 때 영어문장을 읽는 것처럼 코드가 읽힌다면 가독성이 올라가고 이는 결국 코드 생산성에 영향을 미치게 됩니다. Kotlin 개발자들은 이런 점을 염두에 두고 if에 변화를 준 것이 아닐까 생각됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#3_ Kotlin의 when, switch보다 더 똑똑한&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;Java와 완벽한 호환을 보장한다더니 switch는 어디갔냐구요? 걱정하지 마세요 더 좋은 친구가 생겼습니다. Kotlin에서는 switch 대신 when을 지원하는데요, 이 녀석도 if처럼 식(expression)으로서 값을 반환합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1612353119248&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// java의 switch
String userLevel;
switch(id){
  case 0:
    userLevel = &quot;administrator&quot;;
    break;
  case 1:
  case 2:
  ...
  case 10:
    userLevel = &quot;Normal&quot;; 	
    break;
  default:
    userLevel = &quot;Hacker&quot;;
}

// Kotlin의 when
val userLevel = when(id) {
  0 -&amp;gt; &quot;administrator&quot;
  in 1..20 -&amp;gt; &quot;Normal&quot;
  else -&amp;gt; &quot;Hacker&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;사용법은 switch와 비슷하지만 매번 case/break를 입력해야 했던 switch에 비해 간결합니다. 위에서 보여진 when의 형태는 아래와 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1612353185527&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;when(param) {
  [condition] -&amp;gt; [expression]
  [condition] -&amp;gt; [expression]
  [condition] -&amp;gt; [expression]
  else -&amp;gt; [expression]
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;[param] 이 있는 경우 아래 [condition]은 [param]에 대한 조건식이어야 합니다.&lt;/li&gt;
&lt;li&gt;when 내부 블럭 안에서 [condition] -&amp;gt; [expression] 형태로 분기 처리를 합니다.&lt;/li&gt;
&lt;li&gt;[expression] 이 1줄인 경우 Block을 생략할 수 있으며, 2줄 이상인 경우 반드시 Block을 사용해야 합니다.&lt;/li&gt;
&lt;li&gt;when 앞에 대입 연산자 (=)가 있는 경우 반드시 대입되는 데이터 타입에 맞는 값을 [expression]의 마지막 줄에 명시해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;따라서 아래 코드는 위에서 작성한 when의 코드와 동일한 동작을 수행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1612353336295&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val userLevel = when {
  id == 0 -&amp;gt; { &quot;administrator&quot; }
  id in 1..10 -&amp;gt; {
    println(&quot;user level is Normal!&quot;)
    &quot;Normal&quot;
  }
  else -&amp;gt; &quot;Hacker&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;뿐만아니라 아래와 같은 특징들도 가지고 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;[condition]이 여러 개인 경우 콤마로 구분해 다수의 [condition]에 하나의 [expression]을 적용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;분기 조건에 상수만 사용할 수 있는 switch와 달리 객체를 허용합니다.&lt;/li&gt;
&lt;li&gt;스마트 캐스팅(Smart Casting)을 지원합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;아래 코드와 함께 위 특성에 대해 살펴보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1612353437432&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// [condition]이 여러개인 경우 콤마로 구분해 다수의 [condition]에 하나의 [expression]을 매칭 할 수 있다.
val userLevel = when (id) {
  0 -&amp;gt; &quot;administrator&quot;
  1,2,3,4,5,6..10 -&amp;gt; &quot;Normal&quot;
  else -&amp;gt; &quot;Hacker&quot;
}

// 분기 조건에 상수만 사용 할 수 있는 switch와 달리 객체를 허용한다. (1)
val adminSet = setOf(0)
val normalSet = setOf(1,2,3,4,5,6,7,8,9,10)
val userLevel = when {
  adminSet.contains(id) -&amp;gt; &quot;administrator&quot;
  normalSet.contains(id) -&amp;gt; &quot;Normal&quot;
  else -&amp;gt; &quot;Hacker&quot;
}

// 분기 조건에 상수만 사용 할 수 있는 switch와 달리 객체를 허용한다. (2)
val setA = setOf(0,1)
val setB = setOf(1,0)
when(setA) {
  setB -&amp;gt; println(&quot;setA와 setB는 구성이 같다.&quot;)
  else -&amp;gt; println(&quot;setA와 setB는 구성이 다르다.&quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;분기 조건에 객체를 사용한 2번째 예제의 경우 어떤 텍스트가 출력될까요? 정답은 바로 &lt;b&gt;&quot;setA와 setB의 구성이 같다.&quot;&lt;/b&gt; 입니다. 순서가 다른데 어째서 setA == setB가 true냐구요? 그 이유는 바로 &lt;b&gt;&quot;같냐&quot;&lt;/b&gt;가 아닌 &lt;b&gt;&quot;동등하냐&quot;&lt;/b&gt;를 비교하기 때문입니다. set의 경우 내부 element들의 순서가 달라도 데이터만 같다면 동등하다고 판단합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;스마트 캐스팅은 이해가 어려우실 수도 있을 것 같아 동일한 역할을 하는 Java 코드와 함께 설명드리겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1612353583579&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 스마트 캐스팅을 지원한다
fun smartCasting(n: Any) {
  when (n) {
    is Int -&amp;gt; println(&quot;${n + 1}&quot;)
    is String -&amp;gt; println(n.split(&quot;\n&quot;))
    is Main -&amp;gt; n.finish()
  }
}

// java 
if(n instanceof Integer) {
  System.out.println(&quot;&quot; + (((int)n) + 1));
} else if(n instanceof String) {
  System.out.println(((String)n).split(&quot;\n&quot;));
} else if(n instanceof Main) {
  ((Main)n).finish()
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kotlin의 is는 Java의 instanceof와 동일한 역할을 합니다. 단, is를 통해 Object의 타입이 파악된 경우 그 뒤에 실행되는 코드에서 타입이 파악된 Object에 대해 자동으로 캐스팅을 해줍니다. 이렇게 영리하게 자동으로 캐스팅을 해주는 기능을 스마트 캐스팅(Smart Casting)이라고 부릅니다. 때문에 같은 역할을 하는 Kotlin 코드에서는 ((String) n)과 같은 형태의 기계적으로 달아야 하는 상용구가 사라졌습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;1111.jfif&quot; data-origin-width=&quot;493&quot; data-origin-height=&quot;493&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Xk4Zp/btqVvOrDU65/B7ztKgsyAfFILAkaSrffu0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Xk4Zp/btqVvOrDU65/B7ztKgsyAfFILAkaSrffu0/img.jpg&quot; data-alt=&quot;대충 when이 강력해서 좋다는 짤.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Xk4Zp/btqVvOrDU65/B7ztKgsyAfFILAkaSrffu0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXk4Zp%2FbtqVvOrDU65%2FB7ztKgsyAfFILAkaSrffu0%2Fimg.jpg&quot; data-filename=&quot;1111.jfif&quot; data-origin-width=&quot;493&quot; data-origin-height=&quot;493&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;대충 when이 강력해서 좋다는 짤.jpg&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;지금까지 Kotlin의 if와 when에 대해 간략하게 알아봤습니다. if는 문에서 식으로 변화했고, switch는 사라지고 강력한 when이 등장했습니다. 제가 중간중간 이런 변화로 인해 발생하는 이점에 대해 말씀드렸지만 직접 사용해보시면 생각보다 훨씬 편리하다는 것을 느끼실 수 있을 겁니다. 이런 작지만 큰 변화들로 인해 개발자는 보다 더 &quot;기능&quot; 개발에만 집중 할 수 있게 되었습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;마지막으로 분기처리와의 환상의 호흡을 자랑하는 enum에 대해 살펴보겠습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#4_ Kotlin의 enum, Java의 유산(;)을 간직한&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;코틀린의 enum(열거형)은 Java의 enum과 비교했을 때 언어의 문법을 제외하고는 완전히 동일합니다. 때문에 깊게 다루지는 않을 예정이니 더 많은 내용이 궁금하신 분들은 &lt;a href=&quot;https://manorgass.tistory.com/69&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이전에 포스팅&lt;/a&gt;한 내용을 참고해주세요.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;근데 이녀석 조금 특이합니다. 코틀린에서 유일하게 세미콜론(;)이 필요한 녀석이기 때문이죠. 간단한 예제와 함께 사용법을 살펴보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1612354121548&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;enum class WEEK {
  SUN, MON, TUE, WED, THU, FRI, SAT
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;세미콜론이 보이지 않습니다. 이렇게 enum class의 element만 선언한 경우에는 말이죠. 하지만 아래 추가적인 코드가 들어가는 경우 &quot;여기까지가 element 선언 끝이야! 이제부터 로직을 짤 거야!!&quot;라고 세미콜론을 통해 알려줘야 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1612354268117&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;enum class WEEK(val korWord: String) {
  SUN(&quot;일&quot;), 
  MON(&quot;월&quot;),
  TUE(&quot;화&quot;),
  WED(&quot;수&quot;),
  THU(&quot;목&quot;),
  FRI(&quot;금&quot;),
  SAT(&quot;토&quot;); // 세미콜론을 통해 element선언의 끝을 알림
  
  companion object {
    fun parseTo(korWord: String) : WEEK {
      return values().find{it.korWord == korWord} ?: SUN
    }
  }
}

// 실제 사용코드
fun main() {
  val mon = WEEK.parseTo(&quot;월&quot;) // mon == WEEK.MON
  val tue = WEEK.parseTo(&quot;화&quot;) // mon == WEEK.TUE
  val unknown = WEEK.parseTo(&quot;??&quot;) // mon == WEEK.SUN
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;WEEK enum class의 파싱 메서드에 사용된 &lt;span style=&quot;color: #ef5369;&quot;&gt;find&lt;/span&gt;는 correction 내에서 람다의 조건과 일치하는 첫번째 element를 리턴하는 메서드이며, 엘비스 연산자라는 이름을 가진 &lt;span style=&quot;color: #ef5369;&quot;&gt;?:&lt;/span&gt; 로 표현된 연산자는 좌측 식의 리턴 값이 null인 경우 우측식의 값을 리턴하라는 명령을 내리는 연산자입니다. 즉, find의 람다식과 일치하는 element가 없는 경우 default로 WEEK.SUN을 리턴하라는 의미입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  ?: 연산자에 엘비스라는 이름이 붙은 이유는 우측으로 90도 회전시켜보면 미국 로큰롤의 제왕으로 알려진 엘비스 프레슬리의 머리를 한 이모티콘 같다고 해서 그렇게 이름 지었다고 합니다. 코와 입까지 표현하면 아래와 같은 모습일 것 같네요.&lt;br /&gt;&lt;br /&gt;?:^)&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;delitled.png&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;375&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UqkW4/btqVIJWmMpP/1kqKGffTIprwFiLs2juaB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UqkW4/btqVIJWmMpP/1kqKGffTIprwFiLs2juaB1/img.png&quot; data-alt=&quot;엘비스 프레슬리.jpg / 출처 : https://img1.daumcdn.net/thumb/R800x0/?scode=mtistory2&amp;amp;amp;amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99D9A54A5BD77D181C&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UqkW4/btqVIJWmMpP/1kqKGffTIprwFiLs2juaB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUqkW4%2FbtqVIJWmMpP%2F1kqKGffTIprwFiLs2juaB1%2Fimg.png&quot; data-filename=&quot;delitled.png&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;375&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;엘비스 프레슬리.jpg / 출처 : https://img1.daumcdn.net/thumb/R800x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99D9A54A5BD77D181C&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#5_ 마치며&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;오늘 살펴본 코틀린의 분기 식이 가진 장점들이 증명하듯, 코틀린은 개발자가 &quot;기능&quot; 개발에만 집중할 수 있도록 여러 장치들을 마련해 놓았습니다. 단순히 Java코드를 Kotlin문법으로만 바꿔서 사용하기보다는 코틀린스러운 코딩 방식을 접하게 된다면 생산성이 놀랍도록 향상되는 경험을 하실 수 있을 겁니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;가장 빠른 길은 제대로 가는 것뿐이다.&lt;br /&gt;- 로버트 C. 마틴&lt;/blockquote&gt;
&lt;p&gt;클린 코드, 클린 아키텍처의 저자 엉클 밥이 이야기한 것처럼 사소한 문법들도 제대로 이해해서 독자분들이 코틀린스러운 코틀린 코드를 작성하는 개발자가 되었으면 좋겠습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;끝까지 읽어주셔서 감사합니다. 좋은 하루 보내세요.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%; text-align: center;&quot;&gt;&lt;b&gt;광고 클릭, 하트, 댓글은 필자에게 큰 힘이 됩니다!&lt;br /&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
      <category>Programming/Kotlin</category>
      <category>Kotlin</category>
      <category>kotlin enum</category>
      <category>kotlin if</category>
      <category>kotlin when</category>
      <category>kotlin 기초</category>
      <category>코틀린</category>
      <category>코틀린 enum</category>
      <category>코틀린 if</category>
      <category>코틀린 when</category>
      <category>코틀린 기초</category>
      <author>디빌리</author>
      <guid isPermaLink="true">https://manorgass.tistory.com/81</guid>
      <comments>https://manorgass.tistory.com/81#entry81comment</comments>
      <pubDate>Wed, 3 Feb 2021 21:28:53 +0900</pubDate>
    </item>
    <item>
      <title>Kotlin 기초강의#5 :: 프로퍼티(Property)와 뒷받침하는 필드(Backing Field)</title>
      <link>https://manorgass.tistory.com/80</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;kotlin_logo.png&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;1200&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ChMRf/btqID656dwT/eBCSmIv75anpTIaubVSNak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ChMRf/btqID656dwT/eBCSmIv75anpTIaubVSNak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ChMRf/btqID656dwT/eBCSmIv75anpTIaubVSNak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FChMRf%2FbtqID656dwT%2FeBCSmIv75anpTIaubVSNak%2Fimg.png&quot; data-filename=&quot;kotlin_logo.png&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;1200&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  본 포스팅에서는 코틀린의 프로퍼티의 개념과 원리 그리고 활용 방법에 대해 설명합니다.&lt;/blockquote&gt;
&lt;p&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;기초강의 시리즈 전편 바로가기 : &lt;a style=&quot;color: #9d9d9d;&quot; href=&quot;https://manorgass.tistory.com/79&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Kotlin 기초강의#4 :: 코틀린 클래스의 선언과 생성자&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#1&amp;gt; 개요&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;이전 포스팅에서 사람의 이름과 나이를 저장하는 자바빈즈 JavaBeans 클래스인 Person을 만들었습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1600171669783&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person(val name: String, val age: Int)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;자바빈즈 클래스란 규약에 따르는 게터와 세터를 구현하는 프로퍼티를 가져야 합니다. 하지만 Person 클래스에는 게터와 세터가 보이지 않습니다. 그런데 어떻게 자바빈즈라고 할 수 있을까요?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;코틀린의 프로퍼티는 자동으로 게터와 세터를 구현합니다. 더 정확히 말하면 val 의 경우 게터만, var의 경우 게터와 세터 모두를 제공합니다. 그렇기 때문에 Person Class의 name과 age 프로퍼티는 보이지는 않지만 자동으로 구현된 getter가 있으므로 자바빈즈라고 할 수 있겠습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;자동으로 구현된다는 말이 이해가 안되시죠? 아래 내용들을 읽어보시면 이해가 되실 겁니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;우선 자바에서 말하는 프로퍼티의 개념에 대해 알아보고 코틀린의 프로퍼티에 대해 이야기하도록 하겠습니다. 같이 살펴보시죠.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;게터와 세터에 대해서는 이전에 다룬 적이 있으니 궁금하신 분은 아래 링크를 참고하세요.&lt;/p&gt;
&lt;p&gt;(&lt;span style=&quot;color: #9d9d9d;&quot;&gt;게터와 세터 포스팅 바로가기 :&amp;nbsp;&lt;a style=&quot;color: #9d9d9d;&quot; href=&quot;https://manorgass.tistory.com/56&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Java :: 게터와 세터 :: getter 와 setter&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color: #666666;&quot;&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#2&amp;gt; 자바의 프로퍼티&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;&lt;span style=&quot;color: #666666;&quot;&gt;자바에서는 클래스의 필드와 &lt;b&gt;접근자 메서드&lt;/b&gt;(accessor method / getter, setter)를 한데 묶어 프로퍼티라 칭합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #666666;&quot;&gt;프로퍼티(property)라는 개념이 생겨나게 된 이유는 자바 클래스의 목적과 깊은 연관이 있습니다. 왜냐하면 클래스의 목적이 데이터를 캡슐화 하는데 있기 때문입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #666666;&quot;&gt;자바 클래스는 기본적으로 필드(field)를 private으로 설정하고 외부에서 값을 확인할 필요가 있는 경우 getter를, 값을 변경할 필요가 있는 경우 setter를 제공합니다. 그리고 이를 통해 &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;u&gt;캡슐화된 클래스의 고유한 기능은 유지하면서 클라이언트의 요구에 따라 속성 값을 변경(set) 혹은 확인(get) 할 수 있도록 합니다.&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;프로퍼티(property)&lt;/b&gt;&lt;/span&gt;는 직역하면 속성입니다. 왜 이런 이름이 붙었는지 아시겠죠?&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1600171756315&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class AudioPlayer {
	private MediaCodec audioDecoder; // 외부에서 접근하지 못하도록 게터와 세터를 제공하지 않음
  private String vesion = &quot;1.3.2&quot;; // 외부에서 확인만 가능하도록 게터만 제공
  private int volume = 5; // 해당 필드는 외부에서 변경 가능하도록 게터와 세터를 제공

  public String getVersion() {
    return version;
  }

  public int getVolume() {
    return volume;
  }

	public void setVolume(int volume) {
    this.volume = volume;
    changeVolume();
  }
  ... 
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;일반적으로 위와 같이 음악을 재생하는 클래스에서 우리는 내부적으로 어떻게 미디어 파일을 재생하는지는 관심이 없습니다. 단지 볼륨, 재생속도와 같은 속성값을 변경하길 원합니다. 음악을 재생한다 라는 고유의 기능은 유지하면서 필요에 따라 볼륨, 재생속도와 같은 속성을 변경할 수 있도록 해주는 게 캡슐화의 핵심입니다. 그리고 이런 캡슐화를 일관성 있게 제공하기 위해 프로퍼티라는 개념이 사용됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;  용어정리&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;- 필드(field) : 클래스 내의 맴버변수&lt;br /&gt;- 프로퍼티(property) : 필드와 게터 세터를 한데 묶어서 부르는 단어&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#3&amp;gt; 코틀린의 프로퍼티&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;코틀린은 맴버변수라는 말 대신 프로퍼티라는 말을 사용합니다. 코틀린은 맴버변수에 대한 기본 접근자 메서드(default accessor method)를 자동으로 구현해주기 때문입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;아래와 같이 코틀린 프로퍼티의 선언 키워드에 따라 자동으로 생성되는 접근자 메서드가 다릅니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;val 인 경우 - 불변 값이므로 getter가 자동으로 구현됩니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;var 인 경우 - 가변 값이므로 getter와 setter가 자동으로 구현됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;여기서 기본 접근자 메서드란, 단순히 프로퍼티의 값을 변경하고 리턴하는 형태의 기본적인 getter와 setter를 의미합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;실제로 자바에서는 아래와 같이 코틀린 언어로 작성된 Person 클래스 프로퍼티 값을 자동으로 생성된 게터를 활용해 확인합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1600171828581&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person(val name: String, val age: Int)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1600171841283&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Person p0 = new Person(&quot;Bob&quot;, 23);
System.out.println(p0.getName()); 
// Bob
System.out.println(p0.getAge()); 
// 23&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;단, 코틀린에서는 getter와 setter를 통하지 않고 직접 프로퍼티에 접근하는 것만을 허용합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfXVfp/btqIJbsc357/7xwQyAWMFHMzBGPZcBLj10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfXVfp/btqIJbsc357/7xwQyAWMFHMzBGPZcBLj10/img.png&quot; data-alt=&quot;Java에서 Person 클래스의 프로퍼티에 접근하는 경우&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfXVfp/btqIJbsc357/7xwQyAWMFHMzBGPZcBLj10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfXVfp%2FbtqIJbsc357%2F7xwQyAWMFHMzBGPZcBLj10%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;Java에서 Person 클래스의 프로퍼티에 접근하는 경우&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTW0WW/btqIMVCLVPK/bbR43mdqr8WtKWpyt2I3fK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTW0WW/btqIMVCLVPK/bbR43mdqr8WtKWpyt2I3fK/img.png&quot; data-alt=&quot;Kotlin에서 Person 클래스의 프로퍼티에 접근하는 경우&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTW0WW/btqIMVCLVPK/bbR43mdqr8WtKWpyt2I3fK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTW0WW%2FbtqIMVCLVPK%2FbbR43mdqr8WtKWpyt2I3fK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;Kotlin에서 Person 클래스의 프로퍼티에 접근하는 경우&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;코틀린에서 프로퍼티에 직접 접근하도록 강제한 정확한 이유는 모르겠지만, 아마 가독성을 위한 것이라 생각됩니다. 몇 년 전부터 구글에서는 java클래스 작성 시 게터와 세터가 아닌 필드를 public으로 만들어 직접 접근하도록 구현하는 것을 권장해왔거든요. 이런 개발 트렌드가 반영된 것이 아닐까 예상해봅니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;그런데 왜 setter는 보이지 않을까요? 그 이유는 위 예제에서 Person 프로퍼티를 모두 val로 선언했기 때문입니다. 아래와 같이 age를 var로 선언한 경우 자바에서 setter에 접근할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1600171924084&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person(val name: String, var age: Int)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDLJ9A/btqIJa7Xpan/lbSHYYtEeN9e8droZsQu2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDLJ9A/btqIJa7Xpan/lbSHYYtEeN9e8droZsQu2K/img.png&quot; data-alt=&quot;프로퍼티를 var로 선언 시 Java에서 setter가 노출됨을 확인 할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDLJ9A/btqIJa7Xpan/lbSHYYtEeN9e8droZsQu2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDLJ9A%2FbtqIJa7Xpan%2FlbSHYYtEeN9e8droZsQu2K%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로퍼티를 var로 선언 시 Java에서 setter가 노출됨을 확인 할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;접근자 메서드 네이밍 규칙&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;코틀린 프로퍼티의 접근자 메서드(default accessor method)는 아래와 같은 규칙에 따라 이름이 결정됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;getter의 경우 프로퍼티 이름 앞에 get을 붙이고 카멜 표기법에 따라 생성됩니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;setter의 경우 프로퍼티 이름 앞에 set을 붙이고 카멜 표기법에 따라 생성됩니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;프로퍼티 이름이 is로 시작하는 경우 getter는 프로퍼티 이름 그대로 생성되고, setter는 is가 set으로 변경되며 카멜 표기법을 따릅니다. (e.g. isResume &amp;rarr; getter: isResume, setter: setResume)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;코틀린에서 게터와 세터를 자동으로 생성해주니 아주 편리합니다. 하지만 값이 변경되거나 조회될 때 이에 따른 부수적인 로직을 추가하고 싶다면 어떻게 해야 할까요? 걱정하지 마세요 접근자 메서드는 필요에 따라 명시적으로 선언이 가능합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;  카멜 표기법&lt;/b&gt;&lt;/span&gt;이란 두 단어 이상의 문장을 표기할 때 공백 대신에 단어의 첫 글자를 대문자로 사용해 읽기 쉽게 표기하는 방식을 말합니다. 그 모양이 마치 낙타의 등과 비슷하다고 하여 카멜 표기법이라는 이름이 붙었다고 하네요! e.g) showAllTextView, kotlinIsPowerfulThanJava .....&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;1200px-CamelCase_new.svg.png&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;883&quot; width=&quot;272&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c6Uo86/btqISvithC2/z3OQS1JQElKHuuWGAKVfT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c6Uo86/btqISvithC2/z3OQS1JQElKHuuWGAKVfT1/img.png&quot; data-alt=&quot;camelCase.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c6Uo86/btqISvithC2/z3OQS1JQElKHuuWGAKVfT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc6Uo86%2FbtqISvithC2%2Fz3OQS1JQElKHuuWGAKVfT1%2Fimg.png&quot; data-filename=&quot;1200px-CamelCase_new.svg.png&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;883&quot; width=&quot;272&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;camelCase.png&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#4&amp;gt; 프로퍼티의 접근자 메서드&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;코틀린은 친절하게 게터와 세터를 자동으로 구현해주지만, 원한다면 명시적으로 선언할 수 있습니다. 그 방법에 대해 살펴보시죠.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;게터(getter)와 세터(setter)의 명시적 선언&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;프로퍼티의 접근자 메서드를 명시적으로 선언하는 규칙은 다음과 같습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;프로퍼티는 클래스 내에 선언되어야 한다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;게터의 경우 프로퍼티 아래 get() 메서드를 선언한다. 리턴값은 프로퍼티의 데이터 타입과 동일해야 한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이런 규칙으로 인해 default constructor에 지정된 프로퍼티에는 접근자 메서드를 명시적으로 선언할 수 없습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;명시적으로 선언한 기본 접근자 메서드&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;Person Class에서 자동으로 생성되는 기본 접근자 메서드를 명시적으로 선언하면 아래와 같은 형태가 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1600172012612&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person(name: String, age: Int) {
  val name = name
    get() {
      return field
    }

  var age = age
    get() {
      return field
    }
    set(value) {
      field = value
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;명시적인 접근자 메서드 정의를 위해 아래와 같은 변경사항이 생겼습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;프로퍼티의 접근자 메서드(accessor method)를 선언하는 경우 프로퍼티를 클래스 내부에 선언해야 합니다. 따라서 default constructor에 선언했던 val와 var를 제거했습니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;그리고 클래스 내부에 동일한 이름의 프로퍼티를 선언 후 매개변수 값으로 초기화하도록 변경했습니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;명시적으로 게터(getter)와 세터(setter)를 선언했습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;접근자 메서드의 선언 규칙&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;프로퍼티의 접근자 메서드는 아래와 같은 규칙에 따라 선언되어야 합니다. 공통 규칙은 반드시 프로퍼티 아래에 선언이 되어야 한다는 것입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;b&gt;게터(getter)&lt;/b&gt;는 get이라는 이름의 파라미터를 포함하지 않은 메서드 형태로 선언한다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;게터(getter)&lt;/b&gt;는 반드시 프로퍼티와 동일한 타입의 데이터를 리턴해야 한다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;세터(setter)&lt;/b&gt;는 var로 선언된 프로퍼티에만 선언이 가능하다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;세터(setter)&lt;/b&gt;는 set이라는 이름의 파라미터 1개를 포함하는 메서드 형태로 구현한다. 파라미터의 데이터 타입은 프로퍼티와 동일하며 명시적으로 선언하지 않는다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;위 4가지 규칙에 따라 접근자 메서드를 명시적으로 선언할 수 있습니다. 그런데 위 예제에서 보이는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;field&lt;/b&gt;&lt;/span&gt;는 무엇일까요?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;뒷받침하는 필드(Backing Fields)&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;앞서 코틀린에서는 필드라는 말 대신에 프로퍼티라는 용어를 사용한다고 말씀드렸습니다. 그리고 프로퍼티는 필드와 접근자 메서드를 통틀어 칭하는 단어라고 말씀드렸고요. 위 예제에서 보이는 field는 프로퍼티의 실제 값을 저장하는 변수를 칭하는 키워드입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;아래 코드는 field를 통해 프로퍼티의 값을 리턴하는 게터를 보여줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1600172112633&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val name = &quot;Kim&quot;
  get() {
    return field
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 프로퍼티의 값을 저장하는 field를 코틀린에서는 뒷받침하는 필드, Backing Fields라고 합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;접근자 메서드(accessor method) 커스터마이징&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;접근자 메서드를 명시적으로 선언하는 방법을 알게 되었으니 이제 게터와 세터에 원하는 로직을 추가할 수 있습니다. 아래 코드는 name 프로퍼티의 getter가 호출되는 횟수를 저장해 출력하는 예제를 보여줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1600172137745&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private var getNameCount = 0
val name = &quot;Kim&quot;
  get() {
    println(&quot;name getter call count : ${++getNameCount}&quot;)
    return field
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위 예제와 같이 field를 반드시 리턴해야 하는 것은 아닙니다. 아래와 같이 사각형의 넓이와 높이를 입력받는 경우 게터를 통해 정사각형인지 여부를 리턴할 수도 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1600174263324&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Rectangle(val width: Int, val height) {
  val isSquare : Boolean
    get() {
      return width == height
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;물론 동일한 역할을 하는 메서드를 구현해서 정사각형인지 여부를 판단할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1600174715192&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;fun isSquare(w: Int, h: Int) = (w == h)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;상황에 따라 읽기 쉽고 쓰기 편한 방식으로 구현하시면 됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#5&amp;gt; 마치며&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;이번 포스팅을 통해 코틀린의 프로퍼티의 개념과 활용 방법에 대해 알아봤습니다. 프로퍼티의 접근자 메서드의 명시적 선언을 통해 단순히 프로퍼티의 값을 변경하는 것만으로도 다양한 로직을 실행시킬 수 있다는 점에서 매력적입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;하지만 프로퍼티라는 단어가 의미하는 바와 같이 &lt;u&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가능하면 프로퍼티는 해당 클래스의 상태 혹은 속성을 나타내는 목적으로만 사용하는 것을 권고드립니다.&lt;/span&gt;&lt;/u&gt; 프로퍼티의 접근자 메서드에 너무 많은 책임을 할당하면 가독성이 떨어질뿐더러 불필요한 종속성들이 발생하기 때문입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;8b82f928f64b5999ee22e696a6a209df.jpeg&quot; data-origin-width=&quot;495&quot; data-origin-height=&quot;796&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bi5yW1/btqIRNRcVlx/6N7eSxCu5TgwIroEhs4o1K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bi5yW1/btqIRNRcVlx/6N7eSxCu5TgwIroEhs4o1K/img.jpg&quot; data-alt=&quot;프로퍼티에 많은 책임과 종속성이 생기면 일어나는 일.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bi5yW1/btqIRNRcVlx/6N7eSxCu5TgwIroEhs4o1K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbi5yW1%2FbtqIRNRcVlx%2F6N7eSxCu5TgwIroEhs4o1K%2Fimg.jpg&quot; data-filename=&quot;8b82f928f64b5999ee22e696a6a209df.jpeg&quot; data-origin-width=&quot;495&quot; data-origin-height=&quot;796&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로퍼티에 많은 책임과 종속성이 생기면 일어나는 일.jpg&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;코틀린 프로퍼티 필드에 적용된 Backing 기법은 프로퍼티뿐만 아니라 프로퍼티(Backing Properties)라는 기법을 통해 프로퍼티의 활용을 극대화하는 방법도 있습니다. 이러한 패턴에 대해서는 추후 다뤄보도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;긴 글 읽어주셔서 감사합니다. 좋은 하루 되세요.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%; text-align: center;&quot;&gt;&lt;b&gt;하트와 구독, 그리고 광고 클릭은 포스팅 제작에 큰 도움이 됩니다.&lt;br /&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
      <category>Programming/Kotlin</category>
      <category>backing field</category>
      <category>Kotlin</category>
      <category>kotlin property</category>
      <category>Kotlin 강의</category>
      <category>게터 세터</category>
      <category>접근자 메서드</category>
      <category>코틀린</category>
      <category>코틀린 기초강의</category>
      <category>코틀린 접근자 메서드</category>
      <category>코틀린 프로퍼티</category>
      <author>디빌리</author>
      <guid isPermaLink="true">https://manorgass.tistory.com/80</guid>
      <comments>https://manorgass.tistory.com/80#entry80comment</comments>
      <pubDate>Tue, 15 Sep 2020 22:00:41 +0900</pubDate>
    </item>
    <item>
      <title>Kotlin 기초강의#4 :: 코틀린 클래스의 선언과 생성자</title>
      <link>https://manorgass.tistory.com/79</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;kotlin.png&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;1200&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZdUAv/btqH4jJ8kYJ/J5kitMJZsmWnqJrukKYQ9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZdUAv/btqH4jJ8kYJ/J5kitMJZsmWnqJrukKYQ9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZdUAv/btqH4jJ8kYJ/J5kitMJZsmWnqJrukKYQ9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZdUAv%2FbtqH4jJ8kYJ%2FJ5kitMJZsmWnqJrukKYQ9K%2Fimg.png&quot; data-filename=&quot;kotlin.png&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;1200&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  이번 포스팅에서는 객체지향 프로그래밍의 가장 기본이 되는 클래스의 선언 방법과 생성자에 대해 알아봅니다.&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#1&amp;gt; OOP(Obejct-Oriented Programming)의 시발점: 클래스&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;객체지향 프로그래밍 언어인 자바를 통해 프로그램을 만들기 위해 가장먼저 무엇을 하나요? 바로 적당한 이름의 클래스를 생성하는 것 부터 시작합니다. 자바 프로그래밍을 해보셨다면 아래와 같은 코드를 수도없이 많이 작성해보셨을 겁니다.&lt;/p&gt;
&lt;pre id=&quot;code_1599288205095&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class MainClass {
  public static void main(String[] args) {
    // TODO: Programming
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위 클래스 선언을 코틀린 언어로 작성하면 바로 아래와 같이 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1599288248069&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class MainClass {
  companion object {
    fun main(args: Array&amp;lt;String&amp;gt;) {
      // TODO: Programming
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  코틀린 언어는 자바의 static 키워드를 지원하지 않습니다. 그 대신 패키지 수준의 최상위 함수와 객체 선언을 통해 static 메서드 역할을 대신합니다. 위 예제에서 companion object(동반객체)를 통해 클래스 안의 private맴버에 접근 할 수 있는 static 메서드를 선언합니다. 최상위니 동반이니 무슨말인지 잘 이해가 안되시면 일단은 이런게 있구나 하고 넘어가도 좋습니다. 추후 심화 포스팅에서 모두 다룰 예정입니다.&lt;/blockquote&gt;
&lt;p&gt;자바와 큰 차이가 없다고 생각하실 지 모르겠습니다. 하지만 코틀린과 자바의 클래스 선언 방식에 위 예제에서는 보이지 않는 작지만 큰 차이들이 있습니다. 그리고 그 차이들이 엄청난 편리성을 가져다줍니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;본 포스팅에서는 그 차이와 그로 인해 발생하는 커다란 이점에 대해 이야기 합니다. 같이 살펴보시죠!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#2&amp;gt; 코틀린의 클래스&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;코틀린 예제에 단골로 등장하는 사람 이름과 나이를 저장하는 Person이라는 이름의 자바빈(JavaBean) 클래스를 만들어 보면서 코틀린 클래스에 대해 알아보겠습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  자바빈(JavaBean)이란 자바빈 규격서에 따라 작성된 자바 클래스를 칭합니다. 기본 생성자를 가져야하고, 클래스의 프로퍼티는 게터와 세터를 구현해야 합니다.&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;클래스의 선언&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;우선 Person이라는 클래스를 정의해봅시다. 위 섹션에서 살펴본 것 처럼 클래스 선언을 할 때는 class 라는 키워드 뒤에 원하는 클래스 이름을 적어주면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1599288586002&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person {}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;참고로 코틀린의 클래스는 자바와 마찬가지로 기본 가시성이 public 입니다. 따라서 아래와 같이 선언해도 컴파일러는 위와 동일한 클래스 선언이라고 판단합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1599288597829&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Person {}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;클래스 선언을 하긴 했지만 우리가 원하는 것은 이름과 나이 데이터를 담을 수 있는 프로퍼티(클래스 맴버 변수)를 가진 Person 클래스입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;클래스의 프로퍼티 선언&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;아래와 같이 이름과 나이를 담을 프로퍼티를 선언 할 수 있습니다. 코틀린의 프로퍼티는 기본적으로 선언과 동시에 초기화를 해줘야 합니다. 그렇지 않은 경우 컴파일 시 애러가 발생합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1599288659223&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person {
  var name: String = &quot;&quot;
  var age: Int = 0
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;보통 이런 model 역할을 하는 클래스는 프로퍼티를 초기화 하는 생성자가 필요합니다. 코틀린 클래스의 생성자는 java와는 조금 다른 문법을 가지고 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#3&amp;gt; 코틀린의 클래스 생성자 (Kotlin Class Constructor)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;클래스의 생성자&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;생성자는 constructor 라는 키워드를 통해 선언할 수 있습니다. 이 키워드를 사용해 name과 age 프로퍼티를 초기화 하는 생성자를 구현할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1599288764702&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person {
  constructor (name: String, age: Int) {
    this.name = name
    this.age = age
  }
  var name: String = &quot;&quot;
  var age: Int = 0
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;뭔가 지저분해보이죠? 기본 생성자는 클래스 이름 옆에 선언할 수 있으며 constructor 키워드를 생략해도 됩니다. 따라서 위 클래스 선언과 아래 두가지 타입의 클래스 선언은 완전히 동일합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1599288793235&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 클래스 이름 옆에 선언된 기본 생성자
class Person constructor (name: String, age: Int) {
  var name: String = name
  var age: Int = age
}

// 생성자 키워드를 생략한 형태
class Person (name: String, age: Int) {
  var name: String = name
  var age: Int = age
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;클래스 생성자 오버로드(overload)&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;기본 생성자는 유지하되, 클래스 생성 시 name 프로퍼티만 초기화하고 age는 기본 값인 0으로 설정하는 생성자를 선언하고 싶다면 어떻게 해야할까요? 바로 아래와 같이 constructor 키워드를 통해 생성자를 오버로드 해주면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1599291516525&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person (name: String, age: Int) {
	constructor(name: String) {
		this.name = name
		this.age = 0
	}
  var name: String = name
  var age: Int = age
}

val p1 = Person(&quot;생각하는&quot;, 20) // name=&quot;생각하는&quot;, age=20
val p2 = Person(&quot;개발자&quot;)       // name=&quot;개발자&quot;, age=0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;자바 스타일의 개발에 익숙하신 분들이라면 이런 오버로드를 많게는 5개 이상까지도 작성해본 경험이 있으실 겁니다. 하지만 코틀린은 기본값이라는 개념을 통해 파라미터 갯수에 따라 생성자를 반복적으로 선언하는 일이 없도록 해줍니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;파라미터의 기본값(default value) 설정&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;우선 아래 코드를 살펴보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1599291593074&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person (var name:String = &quot;개발자&quot;, var age:Int = &quot;20&quot;)

val p0 = Person() // name=&quot;개발자&quot;, age=20
val p1 = Person(&quot;김철수&quot;) // name=&quot;김철수&quot;, age=20
val p2 = Person(&quot;김영희&quot;, 25) // name=&quot;김영희&quot;, age=25
val p3 = Person(age=30, name=&quot;도라에몽&quot;) // name=&quot;도라에몽&quot;, age=30&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;어떤가요? 아래 p0~4 의 사용 방법과 주석만 봐도 어떤 의미인지 아시겠죠? 그래도 친절히 설명해보도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;우선 class 선언이 간결하게 바뀌었습니다. 변경 사항과 그 이유는 아래와 같습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;클래스 맴버 프로퍼티 선언이 생성자 파라미터로 이동했습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;생성자 파라미터 앞에 var/val 를 선언하면 해당 파라미터가 클래스의 맴버 프로퍼티로 선언되며, 파라미터에 전달된 값으로 초기화 됩니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;생성자(constructor) 오버로드 코드가 사라졌습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;기본 값(default value)를 설정함으로써, 생성자의 파라미터로 값을 전달하지 않는 경우 기본 값으로 초기화 되므로 기존 생성자 오버로드가 필요 없습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;여기서 p3에 대해 추가적으로 설명을 드리자면, 함수 호출 시 해당 함수의 파라미터 이름을 명시하고 값을 선언하면 파라미터 순서와 관계없이 해당 파라미터에 값이 설정됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;파라미터 기본 값 이라는 기능 하나로 정말 많은 양의 상용구 코드(Boilerplate Code)가 사라졌습니다. 놀랍지 않나요?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#4&amp;gt; 자바 스타일과의 비교&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;지금까지 만든 Person Class 선언을 자바 스타일과 비교해보겠습니다. 얼마나 많은 코드가 사라졌는지 눈으로 확인해보시죠.&lt;/p&gt;
&lt;pre id=&quot;code_1599291738552&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Java Style
public class Person {
  private String name = &quot;개발자&quot;;
  private int age = 20;

  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

  public Person(int age, String name) {
    this.name = name;
    this.age = age;
  }

  public Person(String name) {
    this.name = name;
  }

  public Person(int age) {
    this.age;
  }
}

// Kotiln Style
class Person(var name:String = &quot;개발자&quot;, var age:Int = 20)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;어떤가요? 정말 편리하죠? 하지만 벌써 놀라기는 이릅니다. 코틀린은 &lt;span style=&quot;color: #333333;&quot;&gt;상용구 코드를 줄여주는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;다양한 문법들을 지원합니다. 이 내용들은 앞으로의 포스팅에서 하나씩 풀어가도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#5&amp;gt; 마치며&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;이번 포스팅에서는 Person이라는 이름을 가진 자바빈즈 클래스를 만들어봤습니다.&amp;nbsp;하지만 자바빈즈 규약에서는 클래스의 프로퍼티가 관례(convertion)를 따르는 getter와 setter를 구현해야 한다고 명시하고 있습니다. 위에서 작성한 클래스에는 개터와 세터가 없는데 자바빈즈라니 어떻게 된 일일까요?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;결론부터 말씀드리면 지금까지 작성한 Person 클래스는 자바빈즈 규약을 정확히 따르고 있습니다. 그 이유에 대해서는 다음 포스팅 주제인 코틀린의 프로퍼티 편에서 이야기합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%; text-align: center;&quot;&gt;하트와 구독, 그리고 광고 클릭은 포스팅 제작에 큰 도움이 됩니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
      <category>Programming/Kotlin</category>
      <category>class constructor</category>
      <category>Kotlin</category>
      <category>kotlin class</category>
      <category>Kotlin Parameter</category>
      <category>Kotlin 기초강의</category>
      <category>코틀린 기초강의</category>
      <category>코틀린 생성자</category>
      <category>코틀린 클래스</category>
      <category>코틀린 파라미터</category>
      <category>코틀린 파라미터 기본값</category>
      <author>디빌리</author>
      <guid isPermaLink="true">https://manorgass.tistory.com/79</guid>
      <comments>https://manorgass.tistory.com/79#entry79comment</comments>
      <pubDate>Sat, 5 Sep 2020 16:58:51 +0900</pubDate>
    </item>
    <item>
      <title>Solution :: 부팅 USB 용량 복구 방법 / Windows 10 기반</title>
      <link>https://manorgass.tistory.com/78</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;FH63XNDI504TRGD.png&quot; data-origin-width=&quot;320&quot; data-origin-height=&quot;223&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdi56g/btqHZkpB3ue/a7UPOe6BoMv2ld3OFiafH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdi56g/btqHZkpB3ue/a7UPOe6BoMv2ld3OFiafH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdi56g/btqHZkpB3ue/a7UPOe6BoMv2ld3OFiafH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcdi56g%2FbtqHZkpB3ue%2Fa7UPOe6BoMv2ld3OFiafH0%2Fimg.png&quot; data-filename=&quot;FH63XNDI504TRGD.png&quot; data-origin-width=&quot;320&quot; data-origin-height=&quot;223&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size18&quot; data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;  OS 설치를 위해 부팅 USB를 만든 뒤 USB용량이 작게 인식되어 당황하신 경험들이 있으실 겁니다. 이럴 때 USB의 용량을 복구하는 방법에 대해 설명합니다. 본 포스팅의 내용은 Windows10 기반으로 작성되었습니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;#&amp;gt; 개요&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;PC에 OS를 설치할 때 보통 Windows에서 제공하는 MediaCreationTool 과 같은 프로그램을 통해 부팅 USB를 만들어 OS 설치를 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;1051&quot; data-origin-height=&quot;245&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwGcIm/btqH2eoPLAu/CfciwwFZ55K1ZmoBK1QqVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwGcIm/btqH2eoPLAu/CfciwwFZ55K1ZmoBK1QqVk/img.png&quot; data-alt=&quot;MediaCreationTool 다운로드 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwGcIm/btqH2eoPLAu/CfciwwFZ55K1ZmoBK1QqVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwGcIm%2FbtqH2eoPLAu%2FCfciwwFZ55K1ZmoBK1QqVk%2Fimg.png&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;1051&quot; data-origin-height=&quot;245&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;MediaCreationTool 다운로드 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이런 유틸 프로그램을 통해 몇번의 클릭으로 부팅 USB를 만들 수 있지만 부팅 USB로 설정되면 100Mbyte도 안되는 저장 공간만 잡혀서 당황하는 경우가 발생하곤 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이 글을 보고계신 분들이라면 아마 동일한 현상을 겪고 계실 텐데요, 아주 잘 오셨습니다. 제가 설명하는 순서대로 따라 하시면 USB용량을 원상태로 복구시킬 수 있습니다. 그럼 시작합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;#&amp;gt; USB 용량 복구방법&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Step 1&amp;gt; 커멘드창 열기&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;우리의 USB를 살리려면 우선 까만색 바탕을 가진 콘솔창을 띄워서 컴퓨터에게 명령을 내려야 합니다. 아래 두 가지 중 하나의 방법으로 커맨드 창을 열어주세요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Win+R 키를 누른 뒤 cmd 라고 입력한 후 앤터를 친다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Win 키 혹은 시작버튼을 클릭한 뒤 명령 프롬포트라고 검색해 실행한다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size18&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 data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKne9s/btqHTZGsAuG/veqFPUKkJGk39HsjelqgG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKne9s/btqHTZGsAuG/veqFPUKkJGk39HsjelqgG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKne9s/btqHTZGsAuG/veqFPUKkJGk39HsjelqgG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKne9s%2FbtqHTZGsAuG%2FveqFPUKkJGk39HsjelqgG0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Step 2&amp;gt; Disk Part 프로그램 실행&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이제 디스크를 관리해주는 프로그램을 실행시켜야 합니다. 명령어 창에 &lt;span style=&quot;color: #ee2323;&quot;&gt;disk part &lt;/span&gt;라고 입력 후 앤터키를 눌러주세요. 그럼 권한 허용과 관련된 창이 뜨는데 허용을 눌러주시면 Disk Part 프로그램이 실행됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1luxX/btqHTZNeF35/cbdPY9ESsBjb37p5BhXyB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1luxX/btqHTZNeF35/cbdPY9ESsBjb37p5BhXyB0/img.png&quot; data-alt=&quot;명령어 기반의 Disk Part 프로그램&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1luxX/btqHTZNeF35/cbdPY9ESsBjb37p5BhXyB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1luxX%2FbtqHTZNeF35%2FcbdPY9ESsBjb37p5BhXyB0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;명령어 기반의 Disk Part 프로그램&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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 data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size18&quot; data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;  &lt;span style=&quot;color: #006dd7; font-family: 'Nanum Gothic';&quot;&gt;Note. 혹시 다른 명령어가 궁금하시면 help 라고 입력 후 엔터를 쳐보세요. 사용 가능항 명령어 목록과 설명이 나타납니다.&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Step 3&amp;gt; USB 디스크 번호 확인&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;아래 명령어를 입력해 현재 인식된 디스크 목록을 확인합니다. &lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1599279515987&quot; class=&quot;scala&quot; data-ke-language=&quot;scala&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;list disk&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;디스크는 0, 1 과 같이 숫자로만 구분되어 있으므로 크기를 통해 USB에 할당된 디스크 번호를 확인해주세요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;list disk.png&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;189&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KqziI/btqHYIK9lsU/ghzvSvycYQQgyokhJKBHr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KqziI/btqHYIK9lsU/ghzvSvycYQQgyokhJKBHr1/img.png&quot; data-alt=&quot;list disk 명령어를 입력한 결과. 디스크 뒤에 매겨진 번호를 확인해야 한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KqziI/btqHYIK9lsU/ghzvSvycYQQgyokhJKBHr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKqziI%2FbtqHYIK9lsU%2FghzvSvycYQQgyokhJKBHr1%2Fimg.png&quot; data-filename=&quot;list disk.png&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;189&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;list disk 명령어를 입력한 결과. 디스크 뒤에 매겨진 번호를 확인해야 한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;제 경우에는 크기를 보았을 때 &lt;span style=&quot;color: #333333;&quot;&gt;USB가 &lt;/span&gt;디스크 2로 할당되어 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Step 4&amp;gt; 파티션 삭제 후 생성, 그리고 포맷&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;디스크 번호까지 확인하셨으면 해당 디스크를 선택해 파티션을 삭제하고 다시 만들어주면 됩니다. 이를 위해 아래 순서대로 명령어를 입력하면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1599279765560&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1. sel disk [USB Disk 할당 번호] // 디스크 선택
2. clean // 파티션 제거
3. create partition primary // 파티션 생성
4. format quick fs=ntfs // NTFS 파일 시스템으로 빠른 포맷
5. exit // 종료&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;우선 USB 디스크를 선택해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;sel disk.png&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;189&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byZeOO/btqHVolMAhS/NsJdCTfdq8lT38GOPanDaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byZeOO/btqHVolMAhS/NsJdCTfdq8lT38GOPanDaK/img.png&quot; data-alt=&quot;2번 디스크를 선택한 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byZeOO/btqHVolMAhS/NsJdCTfdq8lT38GOPanDaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyZeOO%2FbtqHVolMAhS%2FNsJdCTfdq8lT38GOPanDaK%2Fimg.png&quot; data-filename=&quot;sel disk.png&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;189&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;2번 디스크를 선택한 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이렇게 디스크를 선택한 뒤에는 디스크 관련 명령어는 선택한 디스크에 적용됩니다. &lt;span style=&quot;color: #ee2323;&quot;&gt;clean &lt;/span&gt;명령어를 통해 USB의 디스크 파티션을 삭제해주겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;clean.png&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;189&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dt0QaX/btqH0pD7mec/k8Hka6WLYvCQP6rpdEFm7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dt0QaX/btqH0pD7mec/k8Hka6WLYvCQP6rpdEFm7K/img.png&quot; data-alt=&quot;파티션 삭제 명령어 실행 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dt0QaX/btqH0pD7mec/k8Hka6WLYvCQP6rpdEFm7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdt0QaX%2FbtqH0pD7mec%2Fk8Hka6WLYvCQP6rpdEFm7K%2Fimg.png&quot; data-filename=&quot;clean.png&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;189&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;파티션 삭제 명령어 실행 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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 data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;sand.png&quot; data-origin-width=&quot;259&quot; data-origin-height=&quot;64&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vUzkU/btqH4sNFOJh/Hv0g3aKaUSsxWNZdIknB3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vUzkU/btqH4sNFOJh/Hv0g3aKaUSsxWNZdIknB3K/img.png&quot; data-alt=&quot;파티션이 사라진 USB의 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vUzkU/btqH4sNFOJh/Hv0g3aKaUSsxWNZdIknB3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvUzkU%2FbtqH4sNFOJh%2FHv0g3aKaUSsxWNZdIknB3K%2Fimg.png&quot; data-filename=&quot;sand.png&quot; data-origin-width=&quot;259&quot; data-origin-height=&quot;64&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;파티션이 사라진 USB의 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;파티션을 제거가 성공했다면&amp;nbsp; &lt;span style=&quot;color: #ee2323;&quot;&gt;create partition primary &lt;/span&gt;명령어를 통해 다시 파티션을 생성해줍니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;partition.png&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;189&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3A6fx/btqH2ebfpLR/Lag3Cb4iu4sWK7dol1H1y1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3A6fx/btqH2ebfpLR/Lag3Cb4iu4sWK7dol1H1y1/img.png&quot; data-alt=&quot;파티션 생성 명령어 실행 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3A6fx/btqH2ebfpLR/Lag3Cb4iu4sWK7dol1H1y1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3A6fx%2FbtqH2ebfpLR%2FLag3Cb4iu4sWK7dol1H1y1%2Fimg.png&quot; data-filename=&quot;partition.png&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;189&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;파티션 생성 명령어 실행 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;그리고 &lt;span style=&quot;color: #ee2323;&quot;&gt;format quick fs=ntfs&lt;/span&gt; 명령어를 통해 USB를 ntfs 방식으로 포맷해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;cp.png&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;189&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blPcMN/btqHZHFag35/5Q0KG2YHz7N5VULTkkIVZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blPcMN/btqHZHFag35/5Q0KG2YHz7N5VULTkkIVZK/img.png&quot; data-alt=&quot;NTFS 파일 시스템으로 포맷 명령어 실행 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blPcMN/btqHZHFag35/5Q0KG2YHz7N5VULTkkIVZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblPcMN%2FbtqHZHFag35%2F5Q0KG2YHz7N5VULTkkIVZK%2Fimg.png&quot; data-filename=&quot;cp.png&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;189&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;NTFS 파일 시스템으로 포맷 명령어 실행 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;짜잔! 여기까지 따라오셨다면 아래와 같이 USB 용량이 복구되었음을 확인할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;nice.png&quot; data-origin-width=&quot;263&quot; data-origin-height=&quot;79&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biRq6f/btqH0qC0A29/dK5wccB3BnczkzMhxTmga1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biRq6f/btqH0qC0A29/dK5wccB3BnczkzMhxTmga1/img.png&quot; data-alt=&quot;용량 복구가 완료된 USB&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biRq6f/btqH0qC0A29/dK5wccB3BnczkzMhxTmga1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiRq6f%2FbtqH0qC0A29%2FdK5wccB3BnczkzMhxTmga1%2Fimg.png&quot; data-filename=&quot;nice.png&quot; data-origin-width=&quot;263&quot; data-origin-height=&quot;79&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;용량 복구가 완료된 USB&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;마지막으로 exit 명령어를 통해 diskpart 프로그램을 종료합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;#&amp;gt; 정리&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;아래와 같은 순서대로 진행하면 부팅 USB 용량을 복구 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;명령 프롬프트 창 열기&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;diskpart&lt;/span&gt; 입력 후 엔터 (disk part 프로그램 실행)&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;diskpart 프로그램에서 &lt;span style=&quot;color: #ee2323;&quot;&gt;list disk&lt;/span&gt; 입력 후 엔터&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;USB가 할당된 디스크 번호 확인&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;sel disk [USB 디스크 번호]&lt;/span&gt; 입력 후 엔터&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;clean&lt;/span&gt; 입력 후 엔터&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;create partition primary&lt;/span&gt; 입력 후 엔터&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;format quick fs=ntfs&lt;/span&gt; 입력 후 엔터&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;exit&lt;/span&gt; 입력 후 엔터 (disk part 프로그램 종료)&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 60px;&quot; border=&quot;1&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 60px;&quot;&gt;
&lt;td style=&quot;width: 100%; text-align: center; height: 60px;&quot;&gt;&lt;br /&gt;하트와 구독 그리고 광고 클릭은 포스팅 작성에 큰 도움이 됩니다.&lt;br /&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
      <category>Information/Solution</category>
      <category>booting usb</category>
      <category>disk part</category>
      <category>USB</category>
      <category>usb clear</category>
      <category>USB 용량</category>
      <category>usb 용량 복구</category>
      <category>usb 인식 불가</category>
      <category>usb 파티션</category>
      <category>부팅 USB</category>
      <author>디빌리</author>
      <guid isPermaLink="true">https://manorgass.tistory.com/78</guid>
      <comments>https://manorgass.tistory.com/78#entry78comment</comments>
      <pubDate>Sat, 5 Sep 2020 13:45:08 +0900</pubDate>
    </item>
    <item>
      <title>Android :: 안드로이드 TextView 자동 글자크기 변경 / ... 표시 / 흐르는 효과</title>
      <link>https://manorgass.tistory.com/77</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;TextView는 안드로이드 앱 개발 시 가장 많이 쓰이는 View입니다. 텍스트 뷰 크기가 제한적인 경우 경우에 따라 텍스트 크기를 자동으로 조절하거나, ... 같은 문구를 통해 뒤에 더 표시할 내용이 있다는 것을 사용자에게 알려줘야 할 필요가 있습니다. 이럴 때 유용하게 사용할 수 있는 ellipsize와 autoText 속성에 대해 알아봅니다.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;droid.jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mAZV5/btqDQ9S7kHM/IRSFODM6nTvK1LkaTwz3yk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mAZV5/btqDQ9S7kHM/IRSFODM6nTvK1LkaTwz3yk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mAZV5/btqDQ9S7kHM/IRSFODM6nTvK1LkaTwz3yk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmAZV5%2FbtqDQ9S7kHM%2FIRSFODM6nTvK1LkaTwz3yk%2Fimg.jpg&quot; data-filename=&quot;droid.jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;426&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;#1&amp;gt; 개요&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;text1.gif&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;744&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CEZ2U/btqDQt5APT8/ugKGUNmirFCuaoz7JSNlAK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CEZ2U/btqDQt5APT8/ugKGUNmirFCuaoz7JSNlAK/img.gif&quot; data-alt=&quot;포스팅_내용_미리보기.gif // 코드는 맨 아래 링크에 있습니다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CEZ2U/btqDQt5APT8/ugKGUNmirFCuaoz7JSNlAK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/CEZ2U/btqDQt5APT8/ugKGUNmirFCuaoz7JSNlAK/img.gif&quot; data-filename=&quot;text1.gif&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;744&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;포스팅_내용_미리보기.gif // 코드는 맨 아래 링크에 있습니다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;안드로이드 앱을 개발하다보면 텍스트뷰(TextView)에 문자열을 표시하는 경우가 많습니다. 표시할 문자열의 길이가 일정하면 좋겠지만 그렇지 않은 경우가 많은데요, 텍스트뷰의 크기를 가변적으로 변경해도 되는 경우라면 문제가 없겠지만 디자인 상 텍스트뷰의 크기가 제한적인 경우가 많습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이런 경우를 대비해 Android TextView에는 여러 속성을 지원합니다. 그중 유용하게 쓰일 수 있는 &lt;b&gt;autoSizeText&lt;/b&gt; 속성과 &lt;b&gt;ellipsize&lt;/b&gt; 속성에 대해 알아보고 활용 방법에 대해 설명합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;#2&amp;gt; 문자열 길이에 따른 가변 텍스트 사이즈 속성 &lt;span style=&quot;color: #ee2323;&quot;&gt;autoSizeText&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;text_autosize_with_log.gif&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;744&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kYwrb/btqDQtxKlGZ/6boEZHmHXK0HGZ9NNrsSd0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kYwrb/btqDQtxKlGZ/6boEZHmHXK0HGZ9NNrsSd0/img.gif&quot; data-alt=&quot;autoSizeText 속성이 적용된 TextView&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kYwrb/btqDQtxKlGZ/6boEZHmHXK0HGZ9NNrsSd0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/kYwrb/btqDQtxKlGZ/6boEZHmHXK0HGZ9NNrsSd0/img.gif&quot; data-filename=&quot;text_autosize_with_log.gif&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;744&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;autoSizeText 속성이 적용된 TextView&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;TextView의 auto size 속성은 텍스트뷰의 공간이 제한적이고, singleLine 속성이 true가 아닌 경우 즉, 한 줄이 아닌 경우 쓰일 수 있는 좋은 옵션입니다. 아래 코드는 위 gif에서 보여지는 TextView의 xml 코드입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1588481828948&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;TextView
  android:id=&quot;@+id/textView&quot;
  android:layout_width=&quot;match_parent&quot;
  android:layout_height=&quot;100dp&quot;
  android:autoSizeTextType=&quot;uniform&quot;
  android:background=&quot;@android:color/black&quot;
  android:padding=&quot;8dp&quot;
  android:textColor=&quot;@android:color/white&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;가변 텍스트 사이즈는 android:autoSizeTextType&lt;/span&gt; 속성이 &lt;span&gt;uniform&lt;/span&gt; 인 경우에만 활성화 됩니다. 이때, 아래와 같은 추가 속성들을 통해 사이즈 변경 step과 최대/최소 사이즈를 직접 설정할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;android:autoSizeMinTextSize - 최소 사이즈를 설정&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;android:autoSizeMaxTextSize - 최대 사이즈를 설정&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;android:autoSizeStepGranularity - 텍스트 크기 조절 step을 설정&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위 값을 따로 설정하지 않는 경우 max값은 TextView의 높이에서 표시할 수 있는 최댓값이며, 최솟값은 31px(pixel)이고, size step은 1입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;## 정리&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TextView의 글자 크기를 자동으로 설정하도록 하려면, autoSizeTextType 속성을 uniform으로 설정하고, singleLine이 false로 설정되어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;autoSizeMaxTextSize 속성을 통해 최대 크기를 지정할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;autoSizeMinTextSize 속성을 통해 최소 크기를 지정할 수 있다. 기본값은 31px이다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;autoSizeStepGranularity 속성을 통해 size 변경 폭을 지정할 수 있다. 기본값은 1px이다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;#3&amp;gt; TextView 보다 긴 문자열을 표시하는 속성 &lt;span style=&quot;color: #ee2323;&quot;&gt;ellipsize&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;text_ellipsize.gif&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;744&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zrDPo/btqDRwmZxkW/MnmK3V4rEHPseOqgoBUNX0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zrDPo/btqDRwmZxkW/MnmK3V4rEHPseOqgoBUNX0/img.gif&quot; data-alt=&quot;ellipsize 속성이 적용된 텍스트뷰&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zrDPo/btqDRwmZxkW/MnmK3V4rEHPseOqgoBUNX0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/zrDPo/btqDRwmZxkW/MnmK3V4rEHPseOqgoBUNX0/img.gif&quot; data-filename=&quot;text_ellipsize.gif&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;744&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;ellipsize 속성이 적용된 텍스트뷰&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;auto size가 multiline을 위한 속성이었다면, ellipsize는 single line을 위한 속성입니다. 해당 속성을 이용하면 흐르는 효과를 이용해 모든 텍스트를 보여주거나, &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;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;예를 들어 리스트 뷰에 사용자 정보를 표시한다고 생각해봅시다. 아래와 같이 리스트 아이템은 동일한 높이를 가지는 것이 디자인적으로 좋은 형태입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;SmartSelect_20200502-151854_Samsung Notes.jpg&quot; data-origin-width=&quot;1083&quot; data-origin-height=&quot;346&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HXEwi/btqDQbc4cDV/ULFFoNYZKNNxvfHedDcKz1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HXEwi/btqDQbc4cDV/ULFFoNYZKNNxvfHedDcKz1/img.jpg&quot; data-alt=&quot;리스트 아이템의 디자인(안)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HXEwi/btqDQbc4cDV/ULFFoNYZKNNxvfHedDcKz1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHXEwi%2FbtqDQbc4cDV%2FULFFoNYZKNNxvfHedDcKz1%2Fimg.jpg&quot; data-filename=&quot;SmartSelect_20200502-151854_Samsung Notes.jpg&quot; data-origin-width=&quot;1083&quot; data-origin-height=&quot;346&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;리스트 아이템의 디자인(안)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이름은 보통 5글자를 넘지 않습니다. 하지만 주소는 다르죠. 길이를 가늠하기가 어렵습니다. 이럴 때 사용할 수 있는 옵션이 바로 ellipsize라는 속성입니다. 해당 속성을 사용해 표시할 내용이 TextView 길이를 넘어가는 경우 ... 과 같은 형태로 표시하거나 &lt;span&gt;maruqee&lt;/span&gt; 속성을 통해 모든 내용을 표시해줄 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;ellipsize 속성은 아래와 같이 4가지 값을 가질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;android:ellipsize=&quot;marquee&quot; : 흐르는 효과를 적용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;android:ellipsize=&quot;start&quot; : 시작 부분에 ... 표시를 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;android:ellipsize=&quot;middle&quot; : 중간 부분에 ... 표시를 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;android:ellipsize=&quot;end&quot; : 끝 부분에 ... 표시를 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;text_hga.gif&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;744&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sNfdG/btqDQUBQ5GC/hrZzX8iair3HOuk30l5xO1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sNfdG/btqDQUBQ5GC/hrZzX8iair3HOuk30l5xO1/img.gif&quot; data-alt=&quot;415 총선에서 대패하신 교안님..&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sNfdG/btqDQUBQ5GC/hrZzX8iair3HOuk30l5xO1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/sNfdG/btqDQUBQ5GC/hrZzX8iair3HOuk30l5xO1/img.gif&quot; data-filename=&quot;text_hga.gif&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;744&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;415 총선에서 대패하신 교안님..&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위 샘플 데이터는 위키백과에서 황교안 씨를 검색해서 작성했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이름 : 황교안&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주소: 대한민국 서울특별시 종로구 명륜동 어딘가&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;어떤가요? ellipsize 옵션을 사용하면 표출하려는 데이터의 중요한 부분만 대략적으로 노출시킬 수 있습니다. 전체 정보를 원한다면 클릭 시 detail 다이어로그를 띄워주는 형태로 UI 구현이 가능하겠지요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위 예제의 리스트 아이템 주소 TextView에 순서대로 아래와 같은 속성이 적용되었습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1588482164221&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;when (position) {
        0 -&amp;gt; {
            tvAddress.ellipsize = TextUtils.TruncateAt.MARQUEE
            tvAddress.marqueeRepeatLimit = -1 // marquee_forever
            tvAddress.isSelected = true
        }
        1 -&amp;gt; tvAddress.ellipsize = TextUtils.TruncateAt.START
        2 -&amp;gt; tvAddress.ellipsize = TextUtils.TruncateAt.MIDDLE
        3 -&amp;gt; tvAddress.ellipsize = TextUtils.TruncateAt.END
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;예제에서는 리스트 item position에 따른 각각의 속성을 부여하기 위해 when 문을 사용했지만, 아래와 같이 레이아웃 선언 시에 원하는 속성을 정의할 수도 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1588482179985&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;TextView
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:layout_marginTop=&quot;8dp&quot;
    android:text=&quot;ellipsize -&amp;gt; Marquee&quot;
    android:visibility=&quot;visible&quot; /&amp;gt;

&amp;lt;TextView
    android:id=&quot;@+id/textView1&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:background=&quot;@android:color/black&quot;
    android:ellipsize=&quot;marquee&quot;
    android:marqueeRepeatLimit=&quot;marquee_forever&quot;
    android:padding=&quot;8dp&quot;
    android:singleLine=&quot;true&quot;
    android:textColor=&quot;@android:color/white&quot;
    android:visibility=&quot;visible&quot; /&amp;gt;

&amp;lt;TextView
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:layout_marginTop=&quot;8dp&quot;
    android:text=&quot;ellipsize -&amp;gt; end&quot;
    android:visibility=&quot;visible&quot; /&amp;gt;

&amp;lt;TextView
    android:id=&quot;@+id/textView2&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:background=&quot;@android:color/black&quot;
    android:ellipsize=&quot;end&quot;
    android:padding=&quot;8dp&quot;
    android:singleLine=&quot;true&quot;
    android:textColor=&quot;@android:color/white&quot;
    android:visibility=&quot;visible&quot; /&amp;gt;

&amp;lt;TextView
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:layout_marginTop=&quot;8dp&quot;
    android:text=&quot;ellipsize -&amp;gt; middle&quot;
    android:visibility=&quot;visible&quot; /&amp;gt;

&amp;lt;TextView
    android:id=&quot;@+id/textView3&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:background=&quot;@android:color/black&quot;
    android:ellipsize=&quot;middle&quot;
    android:padding=&quot;8dp&quot;
    android:singleLine=&quot;true&quot;
    android:textColor=&quot;@android:color/white&quot;
    android:visibility=&quot;visible&quot; /&amp;gt;

&amp;lt;TextView
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:layout_marginTop=&quot;8dp&quot;
    android:text=&quot;ellipsize -&amp;gt; start&quot;
    android:visibility=&quot;visible&quot; /&amp;gt;

&amp;lt;TextView
    android:id=&quot;@+id/textView4&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:background=&quot;@android:color/black&quot;
    android:ellipsize=&quot;start&quot;
    android:padding=&quot;8dp&quot;
    android:singleLine=&quot;true&quot;
    android:textColor=&quot;@android:color/white&quot;
    android:visibility=&quot;visible&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;여기서 중요한 점은,&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;u&gt; 텍스트뷰가 흐르는 효과를 주는 marquee 속성을 사용하는 경우에는 반드시 해당 textView가 selected 되어야 한다는 것입니다.&lt;/u&gt; &lt;/b&gt;&lt;/span&gt;그래서 positoin이 0인 경우 해당 textView의 isSelected 프로퍼티를 true로 설정해준 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;또한, 흐르는 효과를 계속해서 반복하려는 경우 xml 속성에 android:marqueeRepeatLimit=&quot;marquee_forever&quot; 을 선언하거나, 코드 상에서 tvAddress.marqueeRepeatLimit = -1 과 같이 설정해 줘야 합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;##&amp;gt; 정리&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ellipsize 속성을 사용하기 위해서는 singleLine 이 ture 이어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ellipsize 속성 값은 marquee, start, middle, end 가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;marquee 속성 값을 사용하는 경우 textView가 selected 되어야 흐르는 효과가 시작된다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;marquee를 반복하려면 marqueeRepeatLimit 속성의 값을 marquee_forever 로 설정해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;start 속성 값은 앞부분은 ... 으로 표시하고 뒷부분 스트링만 보여준다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;middle 속성값은 중간 부분은 ... 으로 표시하고 앞, 뒷부분 스트링만 보여준다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;end 속성값은 뒷부분을 ... 으로 표시하고 앞부분 스트링만 보여준다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;#4&amp;gt; 마치며&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;오늘은 TextView의 속성을 통해 한정된 크기 안에서 많은 텍스트를 표시할 때 사용할 수 있는 두 가지 옵션에 대해 정리를 해봤습니다. 간단하지만 꽤 유용한 속성들이니 독자 분들에게 작게나마 도움이 되었으면 좋겠네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;글 끝까지 읽어주셔서 감사합니다. 좋은 하루 되십시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: right;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;샘플 코드 링크 -&amp;gt; &lt;a style=&quot;color: #9d9d9d;&quot; href=&quot;https://github.com/manorgass/AndroidTextView&quot;&gt;https://github.com/manorgass/AndroidTextView&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;하트와 구독 그리고 광고 클릭은 필자에게 큰 힘이 됩니다&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming/Android</category>
      <category>Android</category>
      <category>auto text size</category>
      <category>ellipsize</category>
      <category>marquee</category>
      <category>TextView</category>
      <category>안드로이드</category>
      <category>자동 글자 크기</category>
      <category>텍스트뷰</category>
      <category>텍스트뷰 속성</category>
      <category>흐르는효과</category>
      <author>디빌리</author>
      <guid isPermaLink="true">https://manorgass.tistory.com/77</guid>
      <comments>https://manorgass.tistory.com/77#entry77comment</comments>
      <pubDate>Sun, 3 May 2020 14:23:32 +0900</pubDate>
    </item>
    <item>
      <title>Android :: 해시키, 키해시(Key Hash)의 개념과 활용 / 생성방법</title>
      <link>https://manorgass.tistory.com/76</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;외부 API를 사용하는 경우 일반적으로 Key Hash 값을 통해 사용자를 인증합니다. 여기서 해시란 무엇이고, 안드로이드 개발 시 키 해시를 얻는 방법과 그 활용법에 대해 설명합니다.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;다운로드 (1).jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bm1JDK/btqDhvpD6Ro/eKZPdWpd86mfAFPkl34DwK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bm1JDK/btqDhvpD6Ro/eKZPdWpd86mfAFPkl34DwK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bm1JDK/btqDhvpD6Ro/eKZPdWpd86mfAFPkl34DwK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbm1JDK%2FbtqDhvpD6Ro%2FeKZPdWpd86mfAFPkl34DwK%2Fimg.jpg&quot; data-filename=&quot;다운로드 (1).jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;426&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#1&amp;gt; Hash Key란?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;오픈 API (카카오맵, FCM, Facebook 로그인 등) 를 사용하려면 해시키를 등록해야 하고, Key Hash가 등록된 앱만 SDK를 이용해 API를 호출할 수 있다고 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;2.jpg&quot; data-origin-width=&quot;593&quot; data-origin-height=&quot;265&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0waar/btqDhuK80mH/UtK3MgcCfnDPi6ujSTmni0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0waar/btqDhuK80mH/UtK3MgcCfnDPi6ujSTmni0/img.png&quot; data-alt=&quot;카카오 API의 안드로이드 플랫폼 키 해시 입력란 캡쳐.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0waar/btqDhuK80mH/UtK3MgcCfnDPi6ujSTmni0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0waar%2FbtqDhuK80mH%2FUtK3MgcCfnDPi6ujSTmni0%2Fimg.png&quot; data-filename=&quot;2.jpg&quot; data-origin-width=&quot;593&quot; data-origin-height=&quot;265&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;카카오 API의 안드로이드 플랫폼 키 해시 입력란 캡쳐.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;이 키 해시(Key Hash)가 무엇이길래 등록을 반드시 해야만 사용할 수 있다고 하는걸까요?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;키 해시는 특정 데이터(data)를 해시 함수(hash function)에 입력한 결과로 받은 리턴값을 말합니다. key hash를 이해하기 위해서는 이를 생성하는 해시 함수에 대해 이해해야 합니다. 같이 살펴볼까요?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;# 해시 함수의 정의&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;위키백과에서는 해시함수에 대해 아래와 같이 정의하고 있습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;해시 함수(hash function)는 임의의 길이의 데이터를 고정된 길이의 데이터로 매핑하는 함수이다. 해시 함수에 의해 얻어지는 값은 해시 값, 해시 코드, 해시 체크섬 또는 간단하게 해시라고 한다.&lt;/blockquote&gt;
&lt;p&gt;해시 함수의 특징은 크게 2가지로 정리할 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터의 길이가 랜덤해도 리턴값의 길이는 일정하다.&lt;/li&gt;
&lt;li&gt;입력값이 같으면 리턴값도 언제나 동일하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;뿐만 아니라 함수의 출력 값만 가지고는 입력값을 추론하는 것이 상당히 어렵습니다. 이런 특징으로 인해 암호화된 key 값이라는 개념으로 보안인증에 사용되곤 합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;해시함수.jpg&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;312&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYMyKd/btqDliJHgsb/9Evru1kFVXsIb5F50tsK00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYMyKd/btqDliJHgsb/9Evru1kFVXsIb5F50tsK00/img.png&quot; data-alt=&quot;해시 알고리즘의 예 / 출처 : 위키백과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYMyKd/btqDliJHgsb/9Evru1kFVXsIb5F50tsK00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYMyKd%2FbtqDliJHgsb%2F9Evru1kFVXsIb5F50tsK00%2Fimg.png&quot; data-filename=&quot;해시함수.jpg&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;312&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;해시 알고리즘의 예 / 출처 : 위키백과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;# Key Hash의 활용&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;API Provider(카카오, 구글 등)는 민감한 정보일 수도 있는 앱의 사이닝 키(signing key)값이 아닌 그 값을 해시한(특히 SHA-1 함수를 통해) hash key를 통해 인증된 사용자인지 여부를 판단합니다. 해시를 통한 사용자 인증의 장점은 해시값이 노출되어도 피해가 전혀 없다는 것입니다. 해시값만 가지고는 원본 데이터를 추론할 수 없기 때문입니다. 따라서 hash key가 노출되어도 입력값인 signing key는 안전합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;그럼 API Provider는 왜 해시가 등록된 앱에 대해서만 API 요청을 허용하는 것일까요? 그 이유는 바로 무분별한 트래픽을 방지하기 위해서입니다. 일반적으로 무료로 공개되어있는 API는 하루 1천 건, 2천 건 등의 요청수 제한을 두고 있습니다. 또한 제한이 있는 무료 사용자와 요청 제한이 없는 유료 사용자를 구분하는 용도로도 쓰일 수 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;# 정리&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;키 해시는 해시함수의 출력값을 말한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해시함수(e.g. SHA1) 는 입력 데이터의 길이와 관계없이 동일한 길이의 출력값을 만든다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해시함수는 입력값이 같으면 출력값이 늘 동일하다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;API 공급업체에서는 사용자 구분을 위해 이 해시함수의 출력값인 Key Hash를 사용한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;참고로 해시함수는 MD5계열, SHA 계열, CRC32등이 있습니다. 이 쓸모 있어 보이는 키 해시, 어떻게 얻을 수 있을까요?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#2&amp;gt; Key Hash 획득하기&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;키 해시를 획득하는 방법에 대해 설명하기에 앞서 원론적인 개념부터 짚고 넘어가겠습니다. Android Application은 Java 기반으로 구현합니다. 이 말인 즉, Android 개발자의 개발 머신에는 JDK가 설치되어 있다는 뜻입니다. 또한, jdk\bin 폴더에는 다양한 어플리케이션이 존재하는데, 이 중 해시키를 생성할 수 있는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;keytool이라는&lt;/b&gt;&lt;/span&gt; 프로그램이 들어있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;jdk.png&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;508&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5az7t/btqDmVUuUH1/1XvyDDMxMml213D42rH1PK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5az7t/btqDmVUuUH1/1XvyDDMxMml213D42rH1PK/img.png&quot; data-alt=&quot;jdk/bin 폴더에 있는 다양한 프로그램들&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5az7t/btqDmVUuUH1/1XvyDDMxMml213D42rH1PK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5az7t%2FbtqDmVUuUH1%2F1XvyDDMxMml213D42rH1PK%2Fimg.png&quot; data-filename=&quot;jdk.png&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;508&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;jdk/bin 폴더에 있는 다양한 프로그램들&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;그래서 Firebase나 카카오 api 등에서 제공하는 Android 플랫폼의 키 해시 획득 가이드 문서에 이 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;keytool&lt;/b&gt;&lt;/span&gt;이라는 프로그램을 활용한 설명이 있는 것이죠. 어떤가요? 이제 퍼즐이 딱딱 들어맞는 느낌이 오시나요?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;미미.png&quot; data-origin-width=&quot;632&quot; data-origin-height=&quot;459&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csvvl8/btqDnxeMxKY/BWb6Ppge0z8z9ku0wBw7K0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csvvl8/btqDnxeMxKY/BWb6Ppge0z8z9ku0wBw7K0/img.png&quot; data-alt=&quot;미... 미미!!.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csvvl8/btqDnxeMxKY/BWb6Ppge0z8z9ku0wBw7K0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcsvvl8%2FbtqDnxeMxKY%2FBWb6Ppge0z8z9ku0wBw7K0%2Fimg.png&quot; data-filename=&quot;미미.png&quot; data-origin-width=&quot;632&quot; data-origin-height=&quot;459&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;미... 미미!!.jpg&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;본 포스팅에서는 터미널에서 keytool을 이용해 획득하는 방법과 코드상에서 획득하는 방법에 대해 알려드리겠습니다. 두 방식 모두 동일한 결과값을 리턴하므로 편한 방식으로 사용하시면 되겠습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;# 코드 상에서 key hash 획득하기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;해시 키 획득 방법에 대해 구글링을 해보셨다면 아래와 같은 코드를 많이 보셨을 겁니다.&lt;/p&gt;
&lt;pre id=&quot;code_1586525943923&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;main() {
	Log.i(TAG, &quot;Key Hash Value :&quot; + getHashKey(this as Activity);
}

public String getKeyHashBase64(Context context) {
      PackageInfo packageInfo = Utility.getPackageInfo(context, PackageManager.GET_SIGNATURES);
      if (packageInfo == null)
          return null;

      for (Signature signature : packageInfo.signatures) {
          try {
              MessageDigest md = MessageDigest.getInstance(&quot;SHA&quot;);
              md.update(signature.toByteArray());
              return Base64.encodeToString(md.digest(), Base64.DEFAULT);
          } catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException e) {
            e.printStackTrace();
          }
      }
      return null;
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위 메서드를 통해 획득한 String 값을 로그에 찍으면 아래와 비슷한 형태의 값을 확인하실 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;133.png&quot; data-origin-width=&quot;272&quot; data-origin-height=&quot;37&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dwnHmV/btqDljBNmcN/bOtvVnPkXOcn6jEdYF2bHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dwnHmV/btqDljBNmcN/bOtvVnPkXOcn6jEdYF2bHk/img.png&quot; data-alt=&quot;getKeyHashBase64 함수의 리턴값을 로그켓으로 확인한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dwnHmV/btqDljBNmcN/bOtvVnPkXOcn6jEdYF2bHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdwnHmV%2FbtqDljBNmcN%2FbOtvVnPkXOcn6jEdYF2bHk%2Fimg.png&quot; data-filename=&quot;133.png&quot; data-origin-width=&quot;272&quot; data-origin-height=&quot;37&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;getKeyHashBase64 함수의 리턴값을 로그켓으로 확인한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;저 해시값은 무슨 키를 해시한 결과일까요? 바로 프로젝트에 설정된 signing key 입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;12344.png&quot; data-origin-width=&quot;952&quot; data-origin-height=&quot;530&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cXU0sr/btqDk5KwCC9/VFDcTinYpc8KxLqKyQOykK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cXU0sr/btqDk5KwCC9/VFDcTinYpc8KxLqKyQOykK/img.png&quot; data-alt=&quot;프로젝트 설정 창에서 확인한 signing 설정상태&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cXU0sr/btqDk5KwCC9/VFDcTinYpc8KxLqKyQOykK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcXU0sr%2FbtqDk5KwCC9%2FVFDcTinYpc8KxLqKyQOykK%2Fimg.png&quot; data-filename=&quot;12344.png&quot; data-origin-width=&quot;952&quot; data-origin-height=&quot;530&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로젝트 설정 창에서 확인한 signing 설정상태&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;위 사진은 프로젝트 생성 후 key관련 설정을 하지 않았을 때의 모습입니다. 보시는 것처럼 signing 키가 비어있습니다. 이 경우에 debug.keystore 키를 해시한 값이 리턴됩니다. 이 키는 안드로이드 스튜디오 설치 후 한 번이라도 빌드를 한 경우 자동으로 생성되는 key로서, 모든 PC마다 고유합니다. &lt;span style=&quot;color: #333333;&quot;&gt;Path는 리눅스의 경우 &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;~/.android/debug.keystore&lt;/b&gt;, 윈도우즈의 경우 &lt;b&gt;%HOMEPATH%/&lt;span style=&quot;color: #333333;&quot;&gt;.android/debug.keystore&lt;/span&gt;&lt;/b&gt; 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lb1FK/btqDlNWYb7s/Zsn9pNHUWeaColRzGQ9sC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lb1FK/btqDlNWYb7s/Zsn9pNHUWeaColRzGQ9sC1/img.png&quot; data-alt=&quot;windows 탐색기에 %HOMEPATH%/.android 를 입력한 결과. debug.keystore 파일을 확인할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lb1FK/btqDlNWYb7s/Zsn9pNHUWeaColRzGQ9sC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Flb1FK%2FbtqDlNWYb7s%2FZsn9pNHUWeaColRzGQ9sC1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;windows 탐색기에 %HOMEPATH%/.android 를 입력한 결과. debug.keystore 파일을 확인할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;# 터미널에서 키 해시 획득 &amp;gt; 리눅스 기반 터미널&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;터미널을 실행한 뒤 아래와 같은 명령어를 입력해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1586526749327&quot; class=&quot;java&quot; style=&quot;display: block; overflow: auto; padding: 15px; color: #383a42; background: #f6f7f8; font-size: 14px; border-radius: 3px; font-family: Menlo, Consolas, Monaco, monospace; border: 1px solid #dddddd; margin: 20px auto 0px; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 명령어 입력형태
keytool -exportcert -alias [key별칭] -keystore [key경로] | openssl sha1 -binary | openssl base64

// 디버깅 키를 해시하는 경우
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;&lt;span&gt;[key경로]&lt;/span&gt;&lt;/b&gt; 부분에 해시할 키 path를, &lt;b&gt;[&lt;span&gt;key별칭]&lt;/span&gt;&lt;/b&gt; 부분에 해당 키의 별칭이 있다면 입력해줍니다. 테스트용으로 debug 키를 해시하는 경우에는 별칭에 &lt;b&gt;androiddebugkey를,&lt;/b&gt; 경로에는 &lt;b&gt;~/. android/debug.keystore를&lt;/b&gt; 입력해줍니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;14124123123.png&quot; data-origin-width=&quot;581&quot; data-origin-height=&quot;370&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SZhsd/btqDk6o85a9/uOP7ZO63s2ceqc7BwcMUq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SZhsd/btqDk6o85a9/uOP7ZO63s2ceqc7BwcMUq0/img.png&quot; data-alt=&quot;리눅스 기반 터미널에서 디버깅 키를 해시한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SZhsd/btqDk6o85a9/uOP7ZO63s2ceqc7BwcMUq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSZhsd%2FbtqDk6o85a9%2FuOP7ZO63s2ceqc7BwcMUq0%2Fimg.png&quot; data-filename=&quot;14124123123.png&quot; data-origin-width=&quot;581&quot; data-origin-height=&quot;370&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;리눅스 기반 터미널에서 디버깅 키를 해시한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;디버그 키를 해시하는 경우에는 비밀번호에 그냥 엔터를 입력해주시면 됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;# 터미널에서 키 해시 획득 &amp;gt; Windows 기반 터미널&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;u&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;keytool을 사용할 수 있는 상태로 만들어주기&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;윈도우의 경우에는 jdk/bin 디렉터리를 환경변수 PATH에 설정해주지 않았다면 그냥 터미널에 keytool을 사용하면 알 수 없는 명령어라는 메시지가 나타납니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;1141241251.png&quot; data-origin-width=&quot;756&quot; data-origin-height=&quot;431&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IXAnQ/btqDkzSFNcq/hrNhv1TyZgR2bkOCxqMPI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IXAnQ/btqDkzSFNcq/hrNhv1TyZgR2bkOCxqMPI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IXAnQ/btqDkzSFNcq/hrNhv1TyZgR2bkOCxqMPI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIXAnQ%2FbtqDkzSFNcq%2FhrNhv1TyZgR2bkOCxqMPI1%2Fimg.png&quot; data-filename=&quot;1141241251.png&quot; data-origin-width=&quot;756&quot; data-origin-height=&quot;431&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;이런 경우에는 아래 두 가지 방법 중 하나로 keytool을 사용할 수 있게 해줍니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;시스템 &amp;gt; 고급 시스템 설정 &amp;gt; 환경변수 &amp;gt; 시스템 변수의 Path 편집 &amp;gt; jdk/bin 경로 추가&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;cd&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt; 명령어를 통해 jdk/bin 경로로 이동&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;1123.png&quot; data-origin-width=&quot;859&quot; data-origin-height=&quot;452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biPngZ/btqDkzZp5kt/5GtPIsKWVSiWQ4e4tOGc3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biPngZ/btqDkzZp5kt/5GtPIsKWVSiWQ4e4tOGc3K/img.png&quot; data-alt=&quot;환경변수 설정 뒤 터미널에서 keytool 명령어를 입력한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biPngZ/btqDkzZp5kt/5GtPIsKWVSiWQ4e4tOGc3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiPngZ%2FbtqDkzZp5kt%2F5GtPIsKWVSiWQ4e4tOGc3K%2Fimg.png&quot; data-filename=&quot;1123.png&quot; data-origin-width=&quot;859&quot; data-origin-height=&quot;452&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;환경변수 설정 뒤 터미널에서 keytool 명령어를 입력한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;u&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;OpenSSL for Windows Library 설치&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;여기서 끝이 아닙니다. 저희는 해시된 키의 binary값을 Base64 인코딩으로 표현한 값이 필요하기 때문이죠.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;sjdjsms.png&quot; data-origin-width=&quot;859&quot; data-origin-height=&quot;452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMoNcr/btqDky0xZzn/0CxrPIbcw7YRiMgH8KJDw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMoNcr/btqDky0xZzn/0CxrPIbcw7YRiMgH8KJDw0/img.png&quot; data-alt=&quot;너...어는 진짜....&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMoNcr/btqDky0xZzn/0CxrPIbcw7YRiMgH8KJDw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMoNcr%2FbtqDky0xZzn%2F0CxrPIbcw7YRiMgH8KJDw0%2Fimg.png&quot; data-filename=&quot;sjdjsms.png&quot; data-origin-width=&quot;859&quot; data-origin-height=&quot;452&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;너...어는 진짜....&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;아주 친절한 Windows는 사용자가 손수 설치해주길 원하므로 아래 경로에서 OpenSSL 라이브러리를 설치해줍니다.&lt;/p&gt;
&lt;p&gt;(설치 url : &lt;a href=&quot;https://code.google.com/archive/p/openssl-for-windows/downloads&quot;&gt;https://code.google.com/archive/p/openssl-for-windows/downloads&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;open.png&quot; data-origin-width=&quot;809&quot; data-origin-height=&quot;379&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/diuLQu/btqDj1PpjbT/IE1z1zFkq3lzcKEMTGbiQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/diuLQu/btqDj1PpjbT/IE1z1zFkq3lzcKEMTGbiQ1/img.png&quot; data-alt=&quot;버전 코드 뒤에 e가 붙은 파일로 다운받아줍시다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/diuLQu/btqDj1PpjbT/IE1z1zFkq3lzcKEMTGbiQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdiuLQu%2FbtqDj1PpjbT%2FIE1z1zFkq3lzcKEMTGbiQ1%2Fimg.png&quot; data-filename=&quot;open.png&quot; data-origin-width=&quot;809&quot; data-origin-height=&quot;379&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;버전 코드 뒤에 e가 붙은 파일로 다운받아줍시다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;여기서 끝이 아니죠. 압축을 풀어보면 openssl 프로그램은 ./bin 디렉토리에 있습니다. 압축을 푼 폴더 전체를 적당한 경로로 옮겨놓고 &lt;span&gt;openssl-0.9.8e_X64\bin&lt;/span&gt; 디렉토리 경로를 시스템 환경변수 Path로 잡아줍니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;dhdh.png&quot; data-origin-width=&quot;527&quot; data-origin-height=&quot;501&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9o0Gh/btqDnxTqhcV/tU4zbl8qe5vIKqHRwQnm60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9o0Gh/btqDnxTqhcV/tU4zbl8qe5vIKqHRwQnm60/img.png&quot; data-alt=&quot;마지막 2줄을 보면 시스템 환경변수 Path에 jdk/bin 경로와 openssl 경로가 등록된 것을 확인 할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9o0Gh/btqDnxTqhcV/tU4zbl8qe5vIKqHRwQnm60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9o0Gh%2FbtqDnxTqhcV%2FtU4zbl8qe5vIKqHRwQnm60%2Fimg.png&quot; data-filename=&quot;dhdh.png&quot; data-origin-width=&quot;527&quot; data-origin-height=&quot;501&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;마지막 2줄을 보면 시스템 환경변수 Path에 jdk/bin 경로와 openssl 경로가 등록된 것을 확인 할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;어후 힘들어, 이제 다 됐습니다. 여기까지 잘 따라오셨다면 아래 명령어를 입력해봅시다.&lt;/p&gt;
&lt;pre id=&quot;code_1586527647572&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 디버깅 키를 해시하는 명령어
keytool -exportcert -alias androiddebugkey -keystore %HOMEPATH%/.android/debug.keystore | openssl sha1 -binary | openssl base64&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;final.png&quot; data-origin-width=&quot;859&quot; data-origin-height=&quot;452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zeeGg/btqDjHwStx8/1lM6QiyQ2Fbk6k6ilDAXOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zeeGg/btqDjHwStx8/1lM6QiyQ2Fbk6k6ilDAXOK/img.png&quot; data-alt=&quot;윈도우즈.. 너어는... 진짜아... 손이 많이가는 아이구나!?&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zeeGg/btqDjHwStx8/1lM6QiyQ2Fbk6k6ilDAXOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzeeGg%2FbtqDjHwStx8%2F1lM6QiyQ2Fbk6k6ilDAXOK%2Fimg.png&quot; data-filename=&quot;final.png&quot; data-origin-width=&quot;859&quot; data-origin-height=&quot;452&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;윈도우즈.. 너어는... 진짜아... 손이 많이가는 아이구나!?&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;# 정리&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px; color: #000000;&quot;&gt;&lt;b&gt;키 해시(Key Hash)&lt;/b&gt;는 코드 상의 로그 혹은 터미널을 통해 획득이 가능하다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;터미널에서 획득하는 경우 &lt;b&gt;keytool&lt;/b&gt;이라는 jdk/bin 에 포함되어 있는 프로그램과 &lt;b&gt;openssl&lt;/b&gt;이라는 프로그램을 사용한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;keytool을 통해 해시값을 바이너리 형태로 구하고 &lt;b&gt;openssl&lt;/b&gt;을 통해 &lt;b&gt;sha1/base64&lt;/b&gt;로 인코딩한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리눅스 기반 터미널에서는 jdk가 설치되어 있으면 명령어만 입력해주면 된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;윈도우 기반 터미널에서는 keytool과 openssl 경로를 System Path에 추가해준 뒤 명령어를 입력해줘야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;google openssl 은 k, e, d 버전이 있는데 &lt;u&gt;&lt;b&gt;e 버전&lt;/b&gt;&lt;/u&gt;을 사용해야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드, 리눅스 기반 터미널, 윈도우 기반 터미널 모두 같은 값을 리턴한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1586527836251&quot; class=&quot;java&quot; style=&quot;display: block; overflow: auto; padding: 15px; color: #383a42; background: #f6f7f8; font-size: 14px; border-radius: 3px; font-family: Menlo, Consolas, Monaco, monospace; border: 1px solid #dddddd; margin: 20px auto 0px; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 명령어 입력형태
keytool -exportcert -alias [key별칭] -keystore [key경로] | openssl sha1 -binary | openssl base64

// 디버깅 키를 해시하는 경우 (리눅스 기반)
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64

// 디버깅 키를 해시하는 경우 (윈도우 기반)
keytool -exportcert -alias androiddebugkey -keystore %HOMEPATH%/.android/debug.keystore | openssl sha1 -binary | openssl base64
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;#3&amp;gt; 마치며&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;원리는 몰라도 구글링을 통해 원하는 값을 획득하고 개발을 진행할 수 있습니다. 하지만 이런 디테일한 정보까지 알기 원하시는 분들이 계실 것 같아 정리를 해봤습니다. 이 글을 읽는 분들에게 많은 도움이 되었으면 좋겠네요.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;긴 글 읽어주셔서 감사합니다. 좋은 하루 되십시오.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%; text-align: center;&quot;&gt;
&lt;p&gt;하트와 구독 그리고 광고 클릭은 필자에게 큰 힘이 됩니다!&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming/Android</category>
      <category>Android</category>
      <category>android key hash</category>
      <category>Java</category>
      <category>key hash</category>
      <category>keytool</category>
      <category>안드로이드 키 해시</category>
      <category>안드로이드 키해시</category>
      <category>안드로이드 해시키</category>
      <category>자바 해시키</category>
      <category>키해시</category>
      <author>디빌리</author>
      <guid isPermaLink="true">https://manorgass.tistory.com/76</guid>
      <comments>https://manorgass.tistory.com/76#entry76comment</comments>
      <pubDate>Fri, 10 Apr 2020 23:20:32 +0900</pubDate>
    </item>
  </channel>
</rss>