<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>wrapping_not.log</title>
        <link>https://velog.io/</link>
        <description>안드로이드, 파이썬 개발자</description>
        <lastBuildDate>Tue, 04 Apr 2023 10:53:47 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>wrapping_not.log</title>
            <url>https://velog.velcdn.com/images/wrapping_not/profile/d21b0d91-8314-4fb4-827d-38a693f0c5e0/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. wrapping_not.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/wrapping_not" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Kotlin 예외처리]]></title>
            <link>https://velog.io/@wrapping_not/Kotlin-%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@wrapping_not/Kotlin-%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Tue, 04 Apr 2023 10:53:47 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/wrapping_not/post/e5dbb5fe-5026-4cc3-b76a-2acb6d7f7b36/image.jpg" alt=""></p>
<p>코틀린의 예외 처리는 자바와 접근방법이 아주 비슷하다. 함수는 정상 종료, 즉 어떤 값을 반환하거나 비정상적으로 오류가 발생한 경우 예외를 던질 수 있다. 예외가 발생한 경우에는 함수를 호출한 쪽에서 예외를 잡아내거나 (catch) 잡아내지 않는 경우 함수 호출 스택의 위로 예외가 전달 될 수 있다. </p>
<h2 id="예외-던지기">예외 던지기</h2>
<p>오류 조건을 신호로 보내려면 자바와 마찬가지로 throw 식에 예외 객체를 사용해야 한다. 문자열이 잘못된 경우 어떤 폴백(fallback) 값을 돌려주는 대신 오류를 발생시키도록 바꿔야한다. </p>
<pre><code class="language-kotlin">fun parseIntNumber(s: String): Int{
    var num = 0

    if(s.length !in 1..31) throw NumberFormatException(&quot;Not a number: $s&quot;)

    for(c in s) {
        if(c !in &#39;0&#39;..&#39;1&#39;) throw NumberFormatException(&quot;Not a number: $s&quot;)
        num = num*2 + (c - &#39;0&#39;)
    }
    return num
}</code></pre>
<ul>
<li>자바와 달리 코틀린은 클래스 인스턴스를 생성(위는 예외) 할 때 new 같은 구문을 사용하지 않는다. 
NumberFormatException처럼 생성자 호출도 일반 함수 호출과 똑같이 생겼다.</li>
</ul>
<h3 id="예외를-던지면-생기는-일">예외를 던지면 생기는 일</h3>
<ul>
<li>프로그램은 예외를 잡아내는 핸들러를 찾는다. 예외와 일치하는 예외 핸들러가 있다면, 예외 핸들러가 예외를 처리한다.</li>
<li>현재 함수 내부에서 핸들러를 찾을 수 없으면 함수 실행이 종료되고 함수가 스택에서 제거(pop)된다. 
그리고 호출한 쪽의 문맥 안에서 예외 핸들러 검색을 수행한다. 이런경우 예외 호출자에게 전파 했다고 한다.</li>
<li>프로그램 진입점에 이를 때까지 예외를 잡아내지 못하면 현재 스레드가 종료된다.</li>
</ul>
<p>→ 코틀린의 예외 처리 단계는 기본적으로 자바와 같다.</p>
<ul>
<li>코틀린에서 break나 continue와 같이 throws 식에도 Nothing 타입식이다.</li>
</ul>
<pre><code class="language-kotlin">fun sayHello(name: String){
    val message = 
        if(name.isNotEmpty()) &quot;Hello $name&quot;
        else throw IllegalArgumentException(&quot;Empty name&quot;)

    println(message)
}</code></pre>
<h2 id="try-문으로-예외-처리">try 문으로 예외 처리</h2>
<ul>
<li>코트린에서도 예외를 처리 할 때는 기본적으로 자바와 똑같은 문법인 try문을 사용한다.</li>
</ul>
<pre><code class="language-kotlin">import java.lang.NumberFormatException

fun readInt(default: Int): Int {
    try{
        return redLine()!!.toInt()
    } catch (e: NumberFormatException){
        return defualt
    }
}</code></pre>
<ul>
<li>예외가 발생 할 수 있는 코드를 try문으로 감싼다. try문에는 최소한 하나 이상 적절한 탑입의 예외를 잡아내는 catch블록이 있어야 한다.</li>
<li>처리할 예외는 파라미터로 표현된다. catch 블록의 내부에서는 이 파라미터를 마음대로 쓸수 있다.</li>
<li>catch 블록은 선언된 순서대로 예외타입을 검사하기 때문에 어떤 타입을 처리할 수 있는 catch 블록을 그 타입 상위 타입을 처리할 수 있는 catch블록 보다 앞에 작성해야 한다. 그렇지 않으면 상위 타입을 잡아내는 핸들러가 하위 타입인 예외도 모두 잡아내버린다.</li>
<li>코틀린에는 검사 예외와 비검사 예외를 구분하지 않는다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[사이드프로젝트 6일차]]></title>
            <link>https://velog.io/@wrapping_not/%EC%82%AC%EC%9D%B4%EB%93%9C%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-6%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@wrapping_not/%EC%82%AC%EC%9D%B4%EB%93%9C%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-6%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Sat, 01 Apr 2023 01:30:31 GMT</pubDate>
            <description><![CDATA[<h2 id="네비게이션-드로어-이어주기">네비게이션 드로어 이어주기</h2>
<pre><code class="language-jsx">override fun onOptionsItemSelected(item: MenuItem): Boolean {
        isclick = false
        val id = item.itemId
        if (id == R.id.menu_item1) {
        } else if (id == R.id.menu_item2) {
            Log.d(&quot;실행&quot;, &quot;ㅇㅇ&quot;)
            if (Build.VERSION.SDK_INT &gt;= 28) {
                startForegroundService(intent)
                Log.v(&quot;asdf&quot;, &quot;startService!&quot;)
            }
        }
        when (item.itemId) {
            android.R.id.home -&gt; {
                if (classes == &quot;8&quot;) {
                    navi_icon!!.setImageResource(R.drawable.uni_1color)
                } else if (classes == &quot;7&quot;) {
                    navi_icon!!.setImageResource(R.drawable.uni_2color)
                } else if (classes == &quot;6&quot;) {
                    navi_icon!!.setImageResource(R.drawable.uni_3color)
                } else if (classes == &quot;5&quot;) {
                    navi_icon!!.setImageResource(R.drawable.uni_4color)
                } else if (classes == &quot;4&quot;) {
                    navi_icon!!.setImageResource(R.drawable.uni_5color)
                } else if (classes == &quot;3&quot;) {
                    navi_icon!!.setImageResource(R.drawable.uni_6color)
                } else if (classes == &quot;2&quot;) {
                    navi_icon!!.setImageResource(R.drawable.uni_7color)
                } else if (classes == &quot;1&quot;) {
                    navi_icon!!.setImageResource(R.drawable.uni_8color)
                }
                drawerLayout.openDrawer(GravityCompat.START)
                return true
            }
        }
        return super.onOptionsItemSelected(item)
    }</code></pre>
<h2 id="리소스-코드">리소스 코드</h2>
<pre><code class="language-jsx">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;

&lt;androidx.drawerlayout.widget.DrawerLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
    xmlns:tools=&quot;http://schemas.android.com/tools&quot;
    android:id=&quot;@+id/drawer_layout&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    android:fitsSystemWindows=&quot;true&quot;
    tools:context=&quot;.MainActivity&quot;&gt;

    &lt;RelativeLayout
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;match_parent&quot;&gt;

        &lt;FrameLayout
            android:layout_width=&quot;match_parent&quot;
            android:layout_height=&quot;match_parent&quot;&gt;

            &lt;ImageView
                android:id=&quot;@+id/img_top&quot;
                android:layout_width=&quot;547dp&quot;
                android:layout_height=&quot;370dp&quot;
                android:layout_marginStart=&quot;0dp&quot;
                android:layout_marginTop=&quot;-89dp&quot;
                android:layout_marginEnd=&quot;0dp&quot;
                app:srcCompat=&quot;@drawable/top_background&quot; /&gt;

            &lt;TextView
                android:id=&quot;@+id/userinfo&quot;
                android:layout_width=&quot;3000dp&quot;
                android:layout_height=&quot;80dp&quot;
                android:layout_gravity=&quot;center_horizontal&quot;
                android:layout_marginTop=&quot;45dp&quot;
                android:fontFamily=&quot;@font/applesdh&quot;
                android:gravity=&quot;center&quot;
                android:text=&quot;SEENABLOW&quot;
                android:textColor=&quot;#FFFFFF&quot;
                android:textSize=&quot;45sp&quot; /&gt;
        &lt;/FrameLayout&gt;

        &lt;GridLayout
            android:layout_width=&quot;370dp&quot;
            android:layout_height=&quot;407dp&quot;
            android:layout_alignParentTop=&quot;true&quot;
            android:layout_marginStart=&quot;20dp&quot;
            android:layout_marginTop=&quot;231dp&quot;
            android:layout_marginEnd=&quot;20dp&quot;
            android:layout_marginBottom=&quot;20dp&quot;
            android:clickable=&quot;true&quot;
            android:columnCount=&quot;2&quot;
            android:focusable=&quot;true&quot;
            android:rowCount=&quot;2&quot;&gt;

            &lt;androidx.cardview.widget.CardView
                android:layout_width=&quot;wrap_content&quot;
                android:layout_height=&quot;wrap_content&quot;
                android:layout_row=&quot;0&quot;
                android:layout_rowWeight=&quot;1&quot;
                android:layout_column=&quot;0&quot;
                android:layout_columnWeight=&quot;1&quot;
                android:layout_gravity=&quot;fill&quot;
                android:layout_margin=&quot;8dp&quot;
                android:clickable=&quot;true&quot;
                android:focusable=&quot;true&quot;
                android:foreground=&quot;?android:attr/selectableItemBackground&quot;
                app:cardCornerRadius=&quot;8dp&quot;
                app:cardElevation=&quot;8dp&quot;
                tools:ignore=&quot;DuplicateClickableBoundsCheck&quot;&gt;

                &lt;LinearLayout
                    android:layout_width=&quot;wrap_content&quot;
                    android:layout_height=&quot;wrap_content&quot;
                    android:layout_gravity=&quot;center_vertical|center_horizontal&quot;
                    android:gravity=&quot;center&quot;
                    android:orientation=&quot;vertical&quot;&gt;

                    &lt;ImageView
                        android:layout_width=&quot;wrap_content&quot;
                        android:layout_height=&quot;wrap_content&quot;
                        android:src=&quot;@drawable/ic_baseline_create_24&quot; /&gt;

                    &lt;TextView
                        android:layout_width=&quot;wrap_content&quot;
                        android:layout_height=&quot;wrap_content&quot;
                        android:text=&quot;시&quot;
                        android:textAlignment=&quot;center&quot;
                        android:textSize=&quot;20sp&quot;
                        android:textStyle=&quot;bold&quot; /&gt;

                &lt;/LinearLayout&gt;
            &lt;/androidx.cardview.widget.CardView&gt;

            &lt;androidx.cardview.widget.CardView
                android:layout_width=&quot;wrap_content&quot;
                android:layout_height=&quot;wrap_content&quot;
                android:layout_row=&quot;0&quot;
                android:layout_rowWeight=&quot;1&quot;
                android:layout_column=&quot;1&quot;
                android:layout_columnWeight=&quot;1&quot;
                android:layout_gravity=&quot;fill&quot;
                android:layout_margin=&quot;8dp&quot;
                android:clickable=&quot;true&quot;
                android:focusable=&quot;true&quot;
                app:cardCornerRadius=&quot;8dp&quot;
                app:cardElevation=&quot;8dp&quot;
                tools:ignore=&quot;DuplicateClickableBoundsCheck&quot;&gt;

                &lt;LinearLayout
                    android:layout_width=&quot;wrap_content&quot;
                    android:layout_height=&quot;wrap_content&quot;
                    android:layout_gravity=&quot;center_vertical|center_horizontal&quot;
                    android:gravity=&quot;center&quot;
                    android:orientation=&quot;vertical&quot;&gt;

                    &lt;ImageView
                        android:layout_width=&quot;48dp&quot;
                        android:layout_height=&quot;48dp&quot;
                        android:src=&quot;@drawable/ic_baseline_description_24&quot; /&gt;

                    &lt;TextView
                        android:layout_width=&quot;wrap_content&quot;
                        android:layout_height=&quot;wrap_content&quot;
                        android:text=&quot;칼럼&quot;
                        android:textAlignment=&quot;center&quot;
                        android:textSize=&quot;20sp&quot;
                        android:textStyle=&quot;bold&quot; /&gt;

                &lt;/LinearLayout&gt;
            &lt;/androidx.cardview.widget.CardView&gt;

            &lt;androidx.cardview.widget.CardView
                android:id=&quot;@+id/card_nov&quot;
                android:layout_width=&quot;wrap_content&quot;
                android:layout_height=&quot;wrap_content&quot;
                android:layout_row=&quot;1&quot;
                android:layout_rowWeight=&quot;1&quot;
                android:layout_column=&quot;0&quot;
                android:layout_columnWeight=&quot;1&quot;
                android:layout_gravity=&quot;fill&quot;
                android:layout_margin=&quot;8dp&quot;
                android:clickable=&quot;true&quot;
                android:focusable=&quot;true&quot;
                android:foreground=&quot;?android:attr/selectableItemBackground&quot;
                app:cardCornerRadius=&quot;8dp&quot;
                app:cardElevation=&quot;8dp&quot;&gt;

                &lt;LinearLayout
                    android:layout_width=&quot;wrap_content&quot;
                    android:layout_height=&quot;wrap_content&quot;
                    android:layout_gravity=&quot;center_vertical|center_horizontal&quot;
                    android:gravity=&quot;center&quot;
                    android:orientation=&quot;vertical&quot;&gt;

                    &lt;ImageView
                        android:layout_width=&quot;69dp&quot;
                        android:layout_height=&quot;52dp&quot;
                        android:src=&quot;@drawable/ic_baseline_menu_book_24&quot; /&gt;

                    &lt;TextView
                        android:layout_width=&quot;wrap_content&quot;
                        android:layout_height=&quot;wrap_content&quot;
                        android:text=&quot;소설&quot;
                        android:textAlignment=&quot;center&quot;
                        android:textSize=&quot;20sp&quot;
                        android:textStyle=&quot;bold&quot; /&gt;

                &lt;/LinearLayout&gt;
            &lt;/androidx.cardview.widget.CardView&gt;

            &lt;androidx.cardview.widget.CardView
                android:id=&quot;@+id/card_poem&quot;
                android:layout_width=&quot;wrap_content&quot;
                android:layout_height=&quot;wrap_content&quot;
                android:layout_row=&quot;0&quot;
                android:layout_rowWeight=&quot;1&quot;
                android:layout_column=&quot;0&quot;
                android:layout_columnWeight=&quot;1&quot;
                android:layout_gravity=&quot;fill&quot;
                android:layout_margin=&quot;8dp&quot;
                android:clickable=&quot;true&quot;
                android:focusable=&quot;true&quot;
                android:foreground=&quot;?android:attr/selectableItemBackground&quot;
                app:cardCornerRadius=&quot;8dp&quot;
                app:cardElevation=&quot;8dp&quot;&gt;

                &lt;LinearLayout
                    android:layout_width=&quot;wrap_content&quot;
                    android:layout_height=&quot;wrap_content&quot;
                    android:layout_gravity=&quot;center_vertical|center_horizontal&quot;
                    android:gravity=&quot;center&quot;
                    android:orientation=&quot;vertical&quot;&gt;

                    &lt;ImageView
                        android:layout_width=&quot;wrap_content&quot;
                        android:layout_height=&quot;wrap_content&quot;
                        android:src=&quot;@drawable/ic_baseline_create_24&quot; /&gt;

                    &lt;TextView
                        android:layout_width=&quot;wrap_content&quot;
                        android:layout_height=&quot;wrap_content&quot;
                        android:text=&quot;시&quot;
                        android:textAlignment=&quot;center&quot;
                        android:textSize=&quot;20sp&quot;
                        android:textStyle=&quot;bold&quot; /&gt;

                &lt;/LinearLayout&gt;
            &lt;/androidx.cardview.widget.CardView&gt;

            &lt;androidx.cardview.widget.CardView
                android:id=&quot;@+id/card_column&quot;
                android:layout_width=&quot;wrap_content&quot;
                android:layout_height=&quot;wrap_content&quot;
                android:layout_row=&quot;0&quot;
                android:layout_rowWeight=&quot;1&quot;
                android:layout_column=&quot;1&quot;
                android:layout_columnWeight=&quot;1&quot;
                android:layout_gravity=&quot;fill&quot;
                android:layout_margin=&quot;8dp&quot;
                android:clickable=&quot;true&quot;
                android:focusable=&quot;true&quot;
                android:foreground=&quot;?android:attr/selectableItemBackground&quot;
                app:cardCornerRadius=&quot;8dp&quot;
                app:cardElevation=&quot;8dp&quot;&gt;

                &lt;LinearLayout
                    android:layout_width=&quot;wrap_content&quot;
                    android:layout_height=&quot;wrap_content&quot;
                    android:layout_gravity=&quot;center_vertical|center_horizontal&quot;
                    android:gravity=&quot;center&quot;
                    android:orientation=&quot;vertical&quot;&gt;

                    &lt;ImageView
                        android:layout_width=&quot;48dp&quot;
                        android:layout_height=&quot;48dp&quot;
                        android:src=&quot;@drawable/ic_baseline_description_24&quot; /&gt;

                    &lt;TextView
                        android:layout_width=&quot;wrap_content&quot;
                        android:layout_height=&quot;wrap_content&quot;
                        android:text=&quot;칼럼&quot;
                        android:textAlignment=&quot;center&quot;
                        android:textSize=&quot;20sp&quot;
                        android:textStyle=&quot;bold&quot; /&gt;

                &lt;/LinearLayout&gt;
            &lt;/androidx.cardview.widget.CardView&gt;

            &lt;androidx.cardview.widget.CardView
                android:id=&quot;@+id/card_news&quot;
                android:layout_width=&quot;wrap_content&quot;
                android:layout_height=&quot;wrap_content&quot;
                android:layout_row=&quot;1&quot;
                android:layout_rowWeight=&quot;1&quot;
                android:layout_column=&quot;1&quot;
                android:layout_columnWeight=&quot;1&quot;
                android:layout_gravity=&quot;fill&quot;
                android:layout_margin=&quot;8dp&quot;
                android:clickable=&quot;true&quot;
                android:focusable=&quot;true&quot;
                android:foreground=&quot;?android:attr/selectableItemBackground&quot;
                app:cardCornerRadius=&quot;8dp&quot;
                app:cardElevation=&quot;8dp&quot;&gt;

                &lt;LinearLayout
                    android:layout_width=&quot;wrap_content&quot;
                    android:layout_height=&quot;wrap_content&quot;
                    android:layout_gravity=&quot;center_vertical|center_horizontal&quot;
                    android:gravity=&quot;center&quot;
                    android:orientation=&quot;vertical&quot;&gt;

                    &lt;ImageView
                        android:layout_width=&quot;69dp&quot;
                        android:layout_height=&quot;52dp&quot;
                        android:src=&quot;@drawable/ic_baseline_tv_24&quot; /&gt;

                    &lt;TextView
                        android:layout_width=&quot;wrap_content&quot;
                        android:layout_height=&quot;wrap_content&quot;
                        android:text=&quot;뉴스&quot;
                        android:textAlignment=&quot;center&quot;
                        android:textSize=&quot;20sp&quot;
                        android:textStyle=&quot;bold&quot; /&gt;

                &lt;/LinearLayout&gt;
            &lt;/androidx.cardview.widget.CardView&gt;

        &lt;/GridLayout&gt;

    &lt;/RelativeLayout&gt;

    &lt;LinearLayout
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;match_parent&quot;
        android:orientation=&quot;vertical&quot;&gt;

        &lt;include layout=&quot;@layout/toolbar_layout&quot; /&gt;
    &lt;/LinearLayout&gt;
›

    &lt;com.google.android.material.navigation.NavigationView
        android:id=&quot;@+id/naviView&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;match_parent&quot;
        android:layout_gravity=&quot;left&quot;
        android:fitsSystemWindows=&quot;true&quot;
        app:headerLayout=&quot;@layout/navi_header&quot;
        app:menu=&quot;@menu/navi_menu&quot;/&gt;

&lt;/androidx.drawerlayout.widget.DrawerLayout&gt;</code></pre>
<h2 id="결과물">결과물</h2>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/6e652d68-7614-4927-a793-9577d44bc95a/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[액티비티_1]]></title>
            <link>https://velog.io/@wrapping_not/%EC%95%A1%ED%8B%B0%EB%B9%84%ED%8B%B01</link>
            <guid>https://velog.io/@wrapping_not/%EC%95%A1%ED%8B%B0%EB%B9%84%ED%8B%B01</guid>
            <pubDate>Fri, 31 Mar 2023 08:51:43 GMT</pubDate>
            <description><![CDATA[<h1 id="안드로이드-액티비티">안드로이드 액티비티</h1>
<p>안드로이드 액티비티는 사용자 인터페이스 화면을 나타내는 하나의 창입니다. 즉, 사용자가 앱에서 보는 화면이 바로 액티비티입니다.</p>
<p>안드로이드에서 다수의 액티비티를 갖는 앱을 만들 수 있습니다. 이 때 각각의 액티비티는 서로 독립적이며, 하나의 앱 내에서도 서로 다른 동작을 수행할 수 있습니다.</p>
<h2 id="컨텍스트">컨텍스트</h2>
<p>컨텍스트는 액티비티, 서비스등의 컴포넌트와 스피너, 리사이클러뷰와 같은 화면 요소를 사용하기 위해서 필요합니다. </p>
<p>컨텍스트는 시스템을 사용하기 위한 정보(프로퍼티)와 도구(메서드)가 담겨있는 클래스 입니다. </p>
<p>대부분의 컨텍스트는 컴포넌트 실행시 함께 생성되고, 그다음에 메서드를 호출 해서 각각의 도구를 사용할 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/6e623915-ef42-4cc0-9a41-d2ed89d0307d/image.png" alt=""></p>
<p>액티비티는 컨텍스트를 상속받아 구현됩니다. </p>
<p>컨텍스트를 상속받은 컴포넌트들은 코드상에서 baseContext를 호출하는 것만드로 안드로이드의 기본 기능을 사용할 수 있습니다.</p>
<h2 id="컨텍스트의-종류">컨텍스트의 종류</h2>
<ol>
<li>애플리케이션 컨텍스트<ul>
<li>어플리케이션과 곤련된 핵심 기능을담고 있는 클래스 입니다. 앱을 통틀어서 하나의 인스턴스만 생성됩니다. 액티비티나 서비스 같은 컴포넌트에서  applicationContext를 직접 호출해서 사용할 수 있는데 호출 하는 지점과 관계없이 모두 동일한 컨텍스트가 호출됩니다.</li>
</ul>
</li>
<li>베이스 컨텍스트<ul>
<li>안드로이드 4대 메이저 컴포넌트인 액티비티, 서비스, 컨텐트 프로바이더, 브로드캐스트리시버의 기반 클래스 입니다. 각각의 컴포넌트에서 baseContext 또는 this로 컨텍스트를 사용할 수 있고 컴포넌트 개수 만큼 컨텍스트도 함께 생성되기 때문에 호출되는 지점에 따라 서로 다른 컨텍스트가 호출 됩니다.</li>
</ul>
</li>
</ol>
<table>
<thead>
<tr>
<th>컴포넌트</th>
<th>컨텍스트 기능</th>
</tr>
</thead>
<tbody><tr>
<td>애플리케이션</td>
<td>애플리케이션과 관련된 핵심 기능을 담고 있는 클래스로, 앱 전체에서 하나의 인스턴스만 생성됩니다.</td>
</tr>
<tr>
<td>액티비티</td>
<td>UI를 관리하는 클래스로, 앱에서 사용자가 볼 수 있는 화면을 담당합니다. 사용자 인터페이스를 구성하고, 사용자 입력에 응답하며, 여러 개의 액티비티를 조합하여 앱의 전체적인 UI를 구성합니다.</td>
</tr>
<tr>
<td>서비스</td>
<td>백그라운드에서 실행되는 컴포넌트로, 앱이 화면에서 나가도 계속 실행할 수 있습니다. 다른 컴포넌트와 연결하여 백그라운드 작업을 수행하거나, 원격 프로세스와 통신하기 위한 수단으로 사용됩니다.</td>
</tr>
<tr>
<td>컨텐트 프로바이더</td>
<td>앱 데이터를 관리하고 다른 앱에 데이터를 제공하는 인터페이스를 제공하는 컴포넌트입니다. 앱의 데이터베이스나 파일 시스템의 내용을 다른 앱에 제공할 수 있습니다.</td>
</tr>
<tr>
<td>브로드캐스트 리시버</td>
<td>시스템이나 다른 앱에서 발생한 이벤트를 수신하는 컴포넌트입니다. 예를 들어, 전화가 왔을 때 브로드캐스트 리시버를 등록하여 이벤트를 처리할 수 있습니다.</td>
</tr>
</tbody></table>
<h2 id="인텐트">인텐트</h2>
<p>안드로이드에서 인텐트(Intent)는 컴포넌트간의 통신을 위한 메시지 객체입니다. 인텐트를 사용하면 다른 앱의 컴포넌트를 실행하거나, 자신의 컴포넌트를 실행할 때 추가적인 정보를 전달할 수 있습니다. 인텐트는 명시적 인텐트와 암시적 인텐트로 나눌 수 있습니다. 명시적 인텐트는 실행할 컴포넌트를 직접 지정하는 방식이며, 암시적 인텐트는 실행할 컴포넌트를 액션(action)과 데이터(data)를 이용하여 시스템에 요청하는 방식입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조와 알고리즘 복잡도 분석]]></title>
            <link>https://velog.io/@wrapping_not/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EC%99%80-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%B3%B5%EC%9E%A1%EB%8F%84-%EB%B6%84%EC%84%9D</link>
            <guid>https://velog.io/@wrapping_not/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EC%99%80-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%B3%B5%EC%9E%A1%EB%8F%84-%EB%B6%84%EC%84%9D</guid>
            <pubDate>Fri, 31 Mar 2023 04:56:59 GMT</pubDate>
            <description><![CDATA[<h2 id="시간-복잡도">시간 복잡도</h2>
<p>시간 복잡도(Time Complexity)는 알고리즘 실행 속도의 측정치입니다. 보통 연산 횟수를 계산합니다. 이 연산 횟수는 입력의 크기에 따라 달라지기 때문에 입력 크기(n)를 기준으로 표기합니다.</p>
<h2 id="big-o-표기법">Big O 표기법</h2>
<p>Big O 표기법은 알고리즘의 수행 시간을 나타내는 표기법 중 하나입니다. 알고리즘의 최악 시간 복잡도를 나타냅니다. 여기서 최악 시간 복잡도란, 입력값 n에 대해 알고리즘이 가장 오래 걸리는 경우의 연산 횟수를 의미합니다. Big O 표기법은 입력값 n이 무한대로 커질 때, 알고리즘의 실행 시간이 어떤 함수 f(n)보다 빠르게 증가하지 않는다는 것을 나타냅니다.</p>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/a8a702c1-b9ef-44be-8669-62544e621c5f/image.png" alt=""></p>
<h2 id="자료구조와-알고리즘-복잡도-예시">자료구조와 알고리즘 복잡도 예시</h2>
<h3 id="배열array">배열(Array)</h3>
<ul>
<li>접근 시간: O(1)</li>
<li>검색 시간: O(n)</li>
<li>삽입 시간: O(n)</li>
<li>삭제 시간: O(n)</li>
</ul>
<h3 id="연결-리스트linked-list">연결 리스트(Linked List)</h3>
<ul>
<li>접근 시간: O(n)</li>
<li>검색 시간: O(n)</li>
<li>삽입 시간: O(1)</li>
<li>삭제 시간: O(1)</li>
</ul>
<h3 id="이진-탐색-트리binary-search-tree">이진 탐색 트리(Binary Search Tree)</h3>
<ul>
<li>접근 시간: O(log n)</li>
<li>검색 시간: O(log n)</li>
<li>삽입 시간: O(log n)</li>
<li>삭제 시간: O(log n).</li>
</ul>
<h3 id="해시-테이블hash-table">해시 테이블(Hash Table)</h3>
<ul>
<li>접근 시간: O(1)</li>
<li>검색 시간: O(1)</li>
<li>삽입 시간: O(1)</li>
<li>삭제 시간: O(1)</li>
</ul>
<h3 id="정렬-알고리즘sorting-algorithm">정렬 알고리즘(Sorting Algorithm)</h3>
<pre><code class="language-kotlin">// 샘플 코드: 정렬 알고리즘 시간 복잡도 측정하기
fun main() {
    val n = 1000000
    val lst = (0 until n).toList()

    val startTime = System.currentTimeMillis()

    // 접근 연산
    val x = lst[0]

    // 검색 연산
    val y = n - 1 in lst

    // 삽입 연산
    val newList = lst.toMutableList()
    newList.add(n)

    // 삭제 연산
    newList.removeAt(newList.lastIndex)

    // 선택 정렬
    selectionSort(lst)

    // 삽입 정렬
    insertionSort(lst)

    // 버블 정렬
    bubbleSort(lst)

    // 합병 정렬
    mergeSort(lst)

    // 퀵 정렬
    quickSort(lst)

    // 힙 정렬
    heapSort(lst)

    val endTime = System.currentTimeMillis()

    println(&quot;모든 연산에 걸린 시간: ${endTime - startTime} ms&quot;)
}

// 선택 정렬
fun selectionSort(lst: List&lt;Int&gt;): List&lt;Int&gt; {
    val result = lst.toMutableList()
    for (i in result.indices) {
        var minIndex = i
        for (j in i + 1 until result.size) {
            if (result[j] &lt; result[minIndex]) {
                minIndex = j
            }
        }
        val temp = result[i]
        result[i] = result[minIndex]
        result[minIndex] = temp
    }
    return result
}

// 삽입 정렬
fun insertionSort(lst: List&lt;Int&gt;): List&lt;Int&gt; {
    val result = lst.toMutableList()
    for (i in 1 until result.size) {
        val key = result[i]
        var j = i - 1
        while (j &gt;= 0 &amp;&amp; result[j] &gt; key) {
            result[j + 1] = result[j]
            j -= 1
        }
        result[j + 1] = key
    }
    return result
}

// 버블 정렬
fun bubbleSort(lst: List&lt;Int&gt;): List&lt;Int&gt; {
    val result = lst.toMutableList()
    for (i in 0 until result.size - 1) {
        for (j in 0 until result.size - i - 1) {
            if (result[j] &gt; result[j + 1]) {
                val temp = result[j]
                result[j] = result[j + 1]
                result[j + 1] = temp
            }
        }
    }
    return result
}

// 합병 정렬
fun mergeSort(lst: List&lt;Int&gt;): List&lt;Int&gt; {
    if (lst.size &lt;= 1) {
        return lst
    }
    val middle = lst.size / 2
    val left = lst.subList(0, middle)
    val right = lst.subList(middle, lst.size)
    return merge(mergeSort(left), mergeSort(right))
}

fun merge(left: List&lt;Int&gt;, right: List&lt;Int&gt;): List&lt;Int&gt; {
    val result = mutableListOf&lt;Int&gt;()
    var i = 0
    var j = 0
    while (i &lt; left.size &amp;&amp; j &lt; right.size) {
        if (left[i] &lt; right[j]) {
            result.add(left[i])
            i++
        } else {
            result.add(right[j])
            j++
        }
    }
    result.addAll(left.subList(i, left.size))
    result.addAll(right.subList(j, right.size))
    return result
}

// 퀵 정렬
fun quickSort(lst: List&lt;Int&gt;): List&lt;Int&gt; {
    if (lst.size &lt;= 1) {
        return lst
    }
    val pivot = lst[lst.size / 2]
    val equal = lst.filter { it == pivot }
    val less = lst.filter { it &lt; pivot }
    val greater = lst.filter { it &gt; pivot }
    return quickSort(less) + equal + quickSort(greater)
}

// 힙 정렬
fun heapSort(lst: List&lt;Int&gt;): List&lt;Int&gt; {
    val result = lst.toMutableList()
    for (i in result.size / 2 - 1 downTo 0) {
        heapify(result, result.size, i)
    }
    for (i in result.size - 1 downTo 1) {
        val temp = result[0]
        result[0] = result[i]
        result[i] = temp
        heapify(result, i, 0)
    }
    return result
}

fun heapify(lst: MutableList&lt;Int&gt;, n: Int, i: Int) {
    var largest = i
    val l = 2 * i + 1
    val r = 2 * i + 2
    if (l &lt; n &amp;&amp; lst[l] &gt; lst[largest]) {
        largest = l
    }
    if (r &lt; n &amp;&amp; lst[r] &gt; lst[largest]) {
        largest = r
    }
    if (largest != i) {
        val swap = lst[i]
        lst[i] = lst[largest]
        lst[largest] = swap
        heapify(lst, n, largest)
    }
}</code></pre>
<p>위 코드는 Kotlin을 사용하여 서로 다른 정렬 알고리즘의 시간 복잡도를 측정하는 예시입니다. 코드는 리스트의 접근, 검색, 삽입, 삭제 연산의 시간, 그리고 선택 정렬, 삽입 정렬, 버블 정렬, 합병 정렬, 퀵 정렬, 힙 정렬의 시간 복잡도를 측정합니다.</p>
<p>각 정렬 알고리즘의 시간 복잡도는 다음과 같습니다:</p>
<ul>
<li>선택 정렬: O(n^2)</li>
<li>삽입 정렬: O(n^2)</li>
<li>버블 정렬: O(n^2)</li>
<li>합병 정렬: O(n log n)</li>
<li>퀵 정렬: O(n log n)</li>
<li>힙 정렬: O(n log n)</li>
</ul>
<p>같은 문제에 대해 적절한 알고리즘을 사용하면 더 나은 성능과 효율성을 얻을 수 있습니다. 따라서 알고리즘을 설계할 때 시간 복잡도 분석을 고려하는 것이 중요합니다.</p>
<p>아래는 파이썬의 리스트를 예시로, 리스트의 길이에 따른 연산 시간을 측정하는 코드입니다.</p>
<pre><code>import time

n = 1000000
lst = [i for i in range(n)]

start = time.time()

# Access operation
x = lst[0]

# Search operation
y = n - 1 in lst

# Insert operation
lst.append(n)

# Delete operation
del lst[-1]

end = time.time()

print(&quot;Elapsed time for list operations: &quot;, end - start)
</code></pre><p>이 코드는 리스트를 사용하는 연산 중 접근, 검색, 삽입, 삭제 연산의 시간을 측정합니다. 리스트의 길이(n)를 바꿔가며 시간을 측정하여, 각각의 연산이 얼마나 오래 걸리는지를 확인할 수 있습니다.</p>
<h2 id="결론">결론</h2>
<p>알고리즘의 시간 복잡도를 분석하여 최적의 알고리즘을 선택하면, 더 효율적으로 문제를 해결할 수 있습니다. 따라서 알고리즘을 설계할 때, 시간 복잡도 분석을 고려하여야 합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS ssh Key Permission 오류]]></title>
            <link>https://velog.io/@wrapping_not/AWS-ssh-Key-Permission-%EC%98%A4%EB%A5%98</link>
            <guid>https://velog.io/@wrapping_not/AWS-ssh-Key-Permission-%EC%98%A4%EB%A5%98</guid>
            <pubDate>Sun, 26 Mar 2023 03:21:16 GMT</pubDate>
            <description><![CDATA[<h2 id="aws-서버-접속시-오류-발생">AWS 서버 접속시 오류 발생</h2>
<ul>
<li>Permission 0644 for &#39;ssh/woogies.pem&#39; are too open. 오류가 발생 되었다.</li>
<li>이 오류는 Permission에 대한 내용으로 구글에 검색 해보니 해결 방법은 간단 했다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/bccfb909-60f4-4fd7-a0b5-87a2b3123109/image.png" alt=""></p>
<h3 id="해결-코드">해결 코드</h3>
<ul>
<li>chmod 600 ssh/woogies.pem 를 터미널에 입력하고 재 접속 해보니</li>
</ul>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/ed7c9e31-59b8-4aed-8428-f70d7c03e286/image.png" alt=""></p>
<ul>
<li>정상적으로 접속이 되었다.</li>
<li>역시 오류해결은 구글신에게 물어보면 된다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[사이드 프로젝트 5일차]]></title>
            <link>https://velog.io/@wrapping_not/%EC%82%AC%EC%9D%B4%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-5%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@wrapping_not/%EC%82%AC%EC%9D%B4%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-5%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Sun, 26 Mar 2023 03:19:49 GMT</pubDate>
            <description><![CDATA[<h2 id="화면처럼-꾸미기">화면처럼 꾸미기</h2>
<ul>
<li>아래는 코드입니다.</li>
<li>디자이너가 아니기 때문에 여러 홈페이지를 통해서 디자인을 참고 했습니다.</li>
</ul>
<pre><code class="language-jsx">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;

&lt;androidx.drawerlayout.widget.DrawerLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
    xmlns:tools=&quot;http://schemas.android.com/tools&quot;
    android:id=&quot;@+id/drawer_layout&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    android:fitsSystemWindows=&quot;true&quot;
    tools:context=&quot;.MainActivity&quot;&gt;

    &lt;RelativeLayout
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;match_parent&quot;&gt;

        &lt;FrameLayout
            android:layout_width=&quot;match_parent&quot;
            android:layout_height=&quot;match_parent&quot;&gt;

            &lt;ImageView
                android:id=&quot;@+id/img_top&quot;
                android:layout_width=&quot;547dp&quot;
                android:layout_height=&quot;370dp&quot;
                android:layout_marginStart=&quot;0dp&quot;
                android:layout_marginTop=&quot;-89dp&quot;
                android:layout_marginEnd=&quot;0dp&quot;
                app:srcCompat=&quot;@drawable/top_background&quot; /&gt;

            &lt;TextView
                android:id=&quot;@+id/userinfo&quot;
                android:layout_width=&quot;3000dp&quot;
                android:layout_height=&quot;80dp&quot;
                android:layout_gravity=&quot;center_horizontal&quot;
                android:layout_marginTop=&quot;45dp&quot;
                android:gravity=&quot;center&quot;
                android:text=&quot;SEENABLOW&quot;
                android:textColor=&quot;#FFFFFF&quot;
                android:textSize=&quot;45sp&quot; /&gt;
        &lt;/FrameLayout&gt;

        &lt;GridLayout
            android:layout_width=&quot;370dp&quot;
            android:layout_height=&quot;407dp&quot;
            android:layout_alignParentTop=&quot;true&quot;
            android:layout_marginStart=&quot;20dp&quot;
            android:layout_marginTop=&quot;231dp&quot;
            android:layout_marginEnd=&quot;20dp&quot;
            android:layout_marginBottom=&quot;20dp&quot;
            android:clickable=&quot;true&quot;
            android:columnCount=&quot;2&quot;
            android:focusable=&quot;true&quot;
            android:rowCount=&quot;2&quot;&gt;

            &lt;androidx.cardview.widget.CardView
                android:layout_width=&quot;wrap_content&quot;
                android:layout_height=&quot;wrap_content&quot;
                android:layout_row=&quot;0&quot;
                android:layout_rowWeight=&quot;1&quot;
                android:layout_column=&quot;0&quot;
                android:layout_columnWeight=&quot;1&quot;
                android:layout_gravity=&quot;fill&quot;
                android:layout_margin=&quot;8dp&quot;
                android:clickable=&quot;true&quot;
                android:focusable=&quot;true&quot;
                android:foreground=&quot;?android:attr/selectableItemBackground&quot;
                app:cardCornerRadius=&quot;8dp&quot;
                app:cardElevation=&quot;8dp&quot;
                tools:ignore=&quot;DuplicateClickableBoundsCheck&quot;&gt;

                &lt;LinearLayout
                    android:layout_width=&quot;wrap_content&quot;
                    android:layout_height=&quot;wrap_content&quot;
                    android:layout_gravity=&quot;center_vertical|center_horizontal&quot;
                    android:gravity=&quot;center&quot;
                    android:orientation=&quot;vertical&quot;&gt;

                    &lt;ImageView
                        android:layout_width=&quot;wrap_content&quot;
                        android:layout_height=&quot;wrap_content&quot;/&gt;

                    &lt;TextView
                        android:layout_width=&quot;wrap_content&quot;
                        android:layout_height=&quot;wrap_content&quot;
                        android:text=&quot;시&quot;
                        android:textAlignment=&quot;center&quot;
                        android:textSize=&quot;20sp&quot;
                        android:textStyle=&quot;bold&quot; /&gt;

                &lt;/LinearLayout&gt;
            &lt;/androidx.cardview.widget.CardView&gt;

            &lt;androidx.cardview.widget.CardView
                android:layout_width=&quot;wrap_content&quot;
                android:layout_height=&quot;wrap_content&quot;
                android:layout_row=&quot;0&quot;
                android:layout_rowWeight=&quot;1&quot;
                android:layout_column=&quot;1&quot;
                android:layout_columnWeight=&quot;1&quot;
                android:layout_gravity=&quot;fill&quot;
                android:layout_margin=&quot;8dp&quot;
                android:clickable=&quot;true&quot;
                android:focusable=&quot;true&quot;
                app:cardCornerRadius=&quot;8dp&quot;
                app:cardElevation=&quot;8dp&quot;
                tools:ignore=&quot;DuplicateClickableBoundsCheck&quot;&gt;

                &lt;LinearLayout
                    android:layout_width=&quot;wrap_content&quot;
                    android:layout_height=&quot;wrap_content&quot;
                    android:layout_gravity=&quot;center_vertical|center_horizontal&quot;
                    android:gravity=&quot;center&quot;
                    android:orientation=&quot;vertical&quot;&gt;

                    &lt;ImageView
                        android:layout_width=&quot;48dp&quot;
                        android:layout_height=&quot;48dp&quot;/&gt;

                    &lt;TextView
                        android:layout_width=&quot;wrap_content&quot;
                        android:layout_height=&quot;wrap_content&quot;
                        android:text=&quot;칼럼&quot;
                        android:textAlignment=&quot;center&quot;
                        android:textSize=&quot;20sp&quot;
                        android:textStyle=&quot;bold&quot; /&gt;

                &lt;/LinearLayout&gt;
            &lt;/androidx.cardview.widget.CardView&gt;

            &lt;androidx.cardview.widget.CardView
                android:id=&quot;@+id/card_nov&quot;
                android:layout_width=&quot;wrap_content&quot;
                android:layout_height=&quot;wrap_content&quot;
                android:layout_row=&quot;1&quot;
                android:layout_rowWeight=&quot;1&quot;
                android:layout_column=&quot;0&quot;
                android:layout_columnWeight=&quot;1&quot;
                android:layout_gravity=&quot;fill&quot;
                android:layout_margin=&quot;8dp&quot;
                android:clickable=&quot;true&quot;
                android:focusable=&quot;true&quot;
                android:foreground=&quot;?android:attr/selectableItemBackground&quot;
                app:cardCornerRadius=&quot;8dp&quot;
                app:cardElevation=&quot;8dp&quot;&gt;

                &lt;LinearLayout
                    android:layout_width=&quot;wrap_content&quot;
                    android:layout_height=&quot;wrap_content&quot;
                    android:layout_gravity=&quot;center_vertical|center_horizontal&quot;
                    android:gravity=&quot;center&quot;
                    android:orientation=&quot;vertical&quot;&gt;

                    &lt;ImageView
                        android:layout_width=&quot;69dp&quot;
                        android:layout_height=&quot;52dp&quot;/&gt;

                    &lt;TextView
                        android:layout_width=&quot;wrap_content&quot;
                        android:layout_height=&quot;wrap_content&quot;
                        android:text=&quot;소설&quot;
                        android:textAlignment=&quot;center&quot;
                        android:textSize=&quot;20sp&quot;
                        android:textStyle=&quot;bold&quot; /&gt;

                &lt;/LinearLayout&gt;
            &lt;/androidx.cardview.widget.CardView&gt;

            &lt;androidx.cardview.widget.CardView
                android:id=&quot;@+id/card_poem&quot;
                android:layout_width=&quot;wrap_content&quot;
                android:layout_height=&quot;wrap_content&quot;
                android:layout_row=&quot;0&quot;
                android:layout_rowWeight=&quot;1&quot;
                android:layout_column=&quot;0&quot;
                android:layout_columnWeight=&quot;1&quot;
                android:layout_gravity=&quot;fill&quot;
                android:layout_margin=&quot;8dp&quot;
                android:clickable=&quot;true&quot;
                android:focusable=&quot;true&quot;
                android:foreground=&quot;?android:attr/selectableItemBackground&quot;
                app:cardCornerRadius=&quot;8dp&quot;
                app:cardElevation=&quot;8dp&quot;&gt;

                &lt;LinearLayout
                    android:layout_width=&quot;wrap_content&quot;
                    android:layout_height=&quot;wrap_content&quot;
                    android:layout_gravity=&quot;center_vertical|center_horizontal&quot;
                    android:gravity=&quot;center&quot;
                    android:orientation=&quot;vertical&quot;&gt;

                    &lt;ImageView
                        android:layout_width=&quot;wrap_content&quot;
                        android:layout_height=&quot;wrap_content&quot;/&gt;

                    &lt;TextView
                        android:layout_width=&quot;wrap_content&quot;
                        android:layout_height=&quot;wrap_content&quot;
                        android:text=&quot;시&quot;
                        android:textAlignment=&quot;center&quot;
                        android:textSize=&quot;20sp&quot;
                        android:textStyle=&quot;bold&quot; /&gt;

                &lt;/LinearLayout&gt;
            &lt;/androidx.cardview.widget.CardView&gt;

            &lt;androidx.cardview.widget.CardView
                android:id=&quot;@+id/card_column&quot;
                android:layout_width=&quot;wrap_content&quot;
                android:layout_height=&quot;wrap_content&quot;
                android:layout_row=&quot;0&quot;
                android:layout_rowWeight=&quot;1&quot;
                android:layout_column=&quot;1&quot;
                android:layout_columnWeight=&quot;1&quot;
                android:layout_gravity=&quot;fill&quot;
                android:layout_margin=&quot;8dp&quot;
                android:clickable=&quot;true&quot;
                android:focusable=&quot;true&quot;
                android:foreground=&quot;?android:attr/selectableItemBackground&quot;
                app:cardCornerRadius=&quot;8dp&quot;
                app:cardElevation=&quot;8dp&quot;&gt;

                &lt;LinearLayout
                    android:layout_width=&quot;wrap_content&quot;
                    android:layout_height=&quot;wrap_content&quot;
                    android:layout_gravity=&quot;center_vertical|center_horizontal&quot;
                    android:gravity=&quot;center&quot;
                    android:orientation=&quot;vertical&quot;&gt;

                    &lt;ImageView
                        android:layout_width=&quot;48dp&quot;
                        android:layout_height=&quot;48dp&quot; /&gt;

                    &lt;TextView
                        android:layout_width=&quot;wrap_content&quot;
                        android:layout_height=&quot;wrap_content&quot;
                        android:text=&quot;칼럼&quot;
                        android:textAlignment=&quot;center&quot;
                        android:textSize=&quot;20sp&quot;
                        android:textStyle=&quot;bold&quot; /&gt;

                &lt;/LinearLayout&gt;
            &lt;/androidx.cardview.widget.CardView&gt;

            &lt;androidx.cardview.widget.CardView
                android:id=&quot;@+id/card_news&quot;
                android:layout_width=&quot;wrap_content&quot;
                android:layout_height=&quot;wrap_content&quot;
                android:layout_row=&quot;1&quot;
                android:layout_rowWeight=&quot;1&quot;
                android:layout_column=&quot;1&quot;
                android:layout_columnWeight=&quot;1&quot;
                android:layout_gravity=&quot;fill&quot;
                android:layout_margin=&quot;8dp&quot;
                android:clickable=&quot;true&quot;
                android:focusable=&quot;true&quot;
                android:foreground=&quot;?android:attr/selectableItemBackground&quot;
                app:cardCornerRadius=&quot;8dp&quot;
                app:cardElevation=&quot;8dp&quot;&gt;

                &lt;LinearLayout
                    android:layout_width=&quot;wrap_content&quot;
                    android:layout_height=&quot;wrap_content&quot;
                    android:layout_gravity=&quot;center_vertical|center_horizontal&quot;
                    android:gravity=&quot;center&quot;
                    android:orientation=&quot;vertical&quot;&gt;

                    &lt;ImageView
                        android:layout_width=&quot;69dp&quot;
                        android:layout_height=&quot;52dp&quot;
                      /&gt;

                    &lt;TextView
                        android:layout_width=&quot;wrap_content&quot;
                        android:layout_height=&quot;wrap_content&quot;
                        android:text=&quot;뉴스&quot;
                        android:textAlignment=&quot;center&quot;
                        android:textSize=&quot;20sp&quot;
                        android:textStyle=&quot;bold&quot; /&gt;

                &lt;/LinearLayout&gt;
            &lt;/androidx.cardview.widget.CardView&gt;

        &lt;/GridLayout&gt;

    &lt;/RelativeLayout&gt;

    &lt;LinearLayout
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;match_parent&quot;
        android:orientation=&quot;vertical&quot;&gt;

        &lt;include layout=&quot;@layout/toolbar_layout&quot; /&gt;
    &lt;/LinearLayout&gt;

    &lt;com.google.android.material.navigation.NavigationView
        android:id=&quot;@+id/naviView&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;match_parent&quot;
        android:layout_gravity=&quot;left&quot;
        android:fitsSystemWindows=&quot;true&quot;
        app:headerLayout=&quot;@layout/navi_header&quot;
        app:menu=&quot;@menu/navi_menu&quot;/&gt;

&lt;/androidx.drawerlayout.widget.DrawerLayout&gt;</code></pre>
<h2 id="결과물">결과물!</h2>
<p>![](<a href="https://velog.velcdn.com/images/wrapping_not/post/0a7d53f3-97a0-42d8-877e-58b91e2a5ae5/image.png">https://velog.velcdn.com/images/wrapping_not/post/0a7d53f3-97a0-42d8-877e-58b91e2a5ae5/image.png</a> &quot;height=&quot;100&quot;)</p>
<h2 id="화면-기능-구현을-위해-연결하기">화면 기능 구현을 위해 연결하기</h2>
<ul>
<li>코드</li>
</ul>
<pre><code class="language-jsx">package com.example.seenablow

import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.MenuItem
import android.view.View
import android.widget.*
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.cardview.widget.CardView
import androidx.core.view.GravityCompat
import androidx.drawerlayout.widget.DrawerLayout
import com.google.android.material.navigation.NavigationView

class MainActivity : AppCompatActivity() {
    var card_nov: CardView? = null
    var card_poem: CardView? = null
    var card_news: CardView? = null
    var card_column: CardView? = null
    private var toolbar: Toolbar? = null
    private var drawerLayout: DrawerLayout? = null
    private var navigationView: NavigationView? = null
    var navi_textview: TextView? = null
    var navi_textview2: TextView? = null
    var username: String? = null
    var age: String? = null
    var gender: String? = null
    var classes: String? = null
    //var intent: Intent? = null
    //
    var isclick = false
    var navi_icon: ImageView? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //해당 액티비티를 잠금화면에 띄워줌
        setContentView(R.layout.activity_main)
        card_nov = findViewById&lt;CardView&gt;(R.id.card_nov)
        card_poem = findViewById&lt;CardView&gt;(R.id.card_poem)
        card_news = findViewById&lt;CardView&gt;(R.id.card_news)
        card_column = findViewById&lt;CardView&gt;(R.id.card_column)
        drawerLayout = findViewById&lt;DrawerLayout&gt;(R.id.drawer_layout)
        intent = getIntent()
        navigationView = findViewById&lt;View&gt;(R.id.naviView) as NavigationView
        navigationView!!.setNavigationItemSelectedListener { item: MenuItem -&gt;
            onOptionsItemSelected(
                item
            )
        }
        val nav_header_view = navigationView!!.getHeaderView(0)
        navi_textview = nav_header_view.findViewById&lt;View&gt;(R.id.user_name) as TextView
        val nav_header_view2 = navigationView!!.getHeaderView(0)
        navi_textview2 = nav_header_view2.findViewById&lt;View&gt;(R.id.userinfo) as TextView
        val nav_header_view3 = navigationView!!.getHeaderView(0)
        navi_icon = nav_header_view3.findViewById&lt;View&gt;(R.id.navi_icon) as ImageView
        toolbar = findViewById&lt;Toolbar&gt;(R.id.toolbar)
        setSupportActionBar(toolbar)
        //액션바 객체
        val actionBar = supportActionBar
        actionBar!!.setDisplayHomeAsUpEnabled(true)
        supportActionBar!!.setDisplayShowTitleEnabled(false)

        //뒤로가기 버튼 이미지 적용
        actionBar.setHomeAsUpIndicator(R.drawable.ic_menu)
        val sharedPreferences = getSharedPreferences(&quot;username&quot;, MODE_PRIVATE)
        username = sharedPreferences.getString(&quot;username&quot;, &quot;&quot;)
        age = sharedPreferences.getString(&quot;age&quot;, &quot;&quot;)
        gender = sharedPreferences.getString(&quot;gender&quot;, &quot;&quot;)
        classes = sharedPreferences.getString(&quot;class&quot;, &quot;&quot;)

    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        isclick = false
        val id = item.itemId
        if (id == R.id.menu_item1) {
        } else if (id == R.id.menu_item2) {
            Log.d(&quot;실행&quot;, &quot;ㅇㅇ&quot;)
            if (Build.VERSION.SDK_INT &gt;= 28) {
                startForegroundService(intent)
                Log.v(&quot;asdf&quot;, &quot;startService!&quot;)
            }
        }
        when (item.itemId) {
            android.R.id.home -&gt; {
                if (classes == &quot;8&quot;) {
                    navi_icon!!.setImageResource(R.drawable.uni_1color)
                } else if (classes == &quot;7&quot;) {
                    navi_icon!!.setImageResource(R.drawable.uni_2color)
                } else if (classes == &quot;6&quot;) {
                    navi_icon!!.setImageResource(R.drawable.uni_3color)
                } else if (classes == &quot;5&quot;) {
                    navi_icon!!.setImageResource(R.drawable.uni_4color)
                } else if (classes == &quot;4&quot;) {
                    navi_icon!!.setImageResource(R.drawable.uni_5color)
                } else if (classes == &quot;3&quot;) {
                    navi_icon!!.setImageResource(R.drawable.uni_6color)
                } else if (classes == &quot;2&quot;) {
                    navi_icon!!.setImageResource(R.drawable.uni_7color)
                } else if (classes == &quot;1&quot;) {
                    navi_icon!!.setImageResource(R.drawable.uni_8color)
                }
                navi_textview!!.text = username
                navi_textview2!!.text = &quot;$age 세 $gender&quot;
                drawerLayout!!.openDrawer(GravityCompat.START)
                return true
            }
        }
        return super.onOptionsItemSelected(item)
    }

    override fun onBackPressed() {
        val alert_ex = AlertDialog.Builder(this)
        alert_ex.setMessage(&quot;정말로 종료하시겠습니까?&quot;)
        alert_ex.setNegativeButton(&quot;취소&quot;) { dialog, which -&gt; }
        alert_ex.setPositiveButton(&quot;종료&quot;) { dialog, which -&gt; finishAffinity() }
        alert_ex.setTitle(&quot;Good Bye!&quot;)
        val alert = alert_ex.create()
        alert.show()
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[사이드프로젝트 4일차]]></title>
            <link>https://velog.io/@wrapping_not/%EC%82%AC%EC%9D%B4%EB%93%9C%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-4%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@wrapping_not/%EC%82%AC%EC%9D%B4%EB%93%9C%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-4%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Fri, 24 Mar 2023 05:10:51 GMT</pubDate>
            <description><![CDATA[<h1 id="django를-aws서버를-이용한-배포">Django를 AWS서버를 이용한 배포</h1>
<h2 id="개발-환경">개발 환경</h2>
<ul>
<li>mac os(13.0 Ventura)</li>
<li>Python 3.9</li>
<li>Django 4.1.5</li>
<li>Pycham 22.11.ver</li>
</ul>
<h2 id="login을-위해-db-생성과-연결할-서버를-생성">Login을 위해 DB 생성과 연결할 서버를 생성</h2>
<ol>
<li>DB 생성 (adminuser_DB 테이블 생성) </li>
</ol>
<ol>
<li>Django 서버를 생성해서 로그인 API를 만든다. (Django Ver 4.1)</li>
</ol>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/df72fddd-2adb-4782-b51a-b2608d803e3a/image.png" alt=""></p>
<p>장고를 임포트 하여 첫 시작 페이지를 만듬</p>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/69b6f40b-ec33-4c92-8d0e-70fe0acb2740/image.png" alt=""></p>
<p>python <a href="http://manage.py/">manage.py</a> startapp Login 구문을 사용해서 Login app 생성</p>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/a9899e17-2f54-4749-9fb2-f458fa6f8430/image.png" alt=""></p>
<p><a href="http://setting.py">setting.py</a> 에서 DB를 셋팅 해주고 migration을 통해 설정을저장 한다. </p>
<ul>
<li>의도치 않은 오류 발생</li>
</ul>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/45fa8954-192e-47a8-85d3-65031f57e7ac/image.png" alt=""></p>
<p>위의 포트가 이미 사용중이라는 오류가 발생했다.</p>
<p>이유는 제대로 앱이 꺼지지 않아서 그럴수있다. (ctrl + z를 사용하면 서버가 죽는게 아닌 멈춘다. 제대로 죽이려면 ctrl + c를 사용해서 서버를 죽이면 된다.)</p>
<p>이럴 경우 port 8000과 관련된 모든 프로세스를 죽이고 다시 실행시키면 된다.</p>
<p>터미널에서 &quot;<strong>sudo lsof -t -i tcp:8000 | xargs kill -9</strong>&quot;를 입력하면 된다.</p>
<p>혹은 <code>python manage.py runserver 0.0.0.0:9000</code> 이런식으로 포트를 지정해주면 된다.</p>
<h2 id="포트-연결-성공">포트 연결 성공</h2>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/4ec4687f-cdb2-4f42-adf2-dff741c83545/image.png" alt=""></p>
<h2 id="aws서버에-django-웹-배포하기">AWS서버에 django 웹 배포하기</h2>
<p>서버에서도 똑같은 패키지를 사용할수 있도록 pip3 freeze &gt;&gt; requirements.txt 명령어를 입력한다. </p>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/6691ee7c-0079-4570-a74a-9f503fc226ee/image.png" alt=""></p>
<ul>
<li>인증키의 경로를 잘 선택하거나 잘 잡아야 할거 같다. 그후 아래 명령어를 입력하면</li>
</ul>
<p>(venv) (base) weng-weng@MacBook-Pro ssh % $ ssh -i ssh/woogies.pem <a href="mailto:ubuntu@ec2-ec2-13-124-208-83.ap-northeast-2.compute.amazonaws.com">ubuntu@ec2-ec2-13-124-208-83.ap-northeast-2.compute.amazonaws.com</a></p>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/47e3a807-4685-43d5-8a17-5e2482de169f/image.png" alt=""></p>
<p>이 화면에서 Yes라고 하면</p>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/33a81c90-9ef4-47fb-bbbb-d21a3a367a6a/image.png" alt=""></p>
<h3 id="성공적으로-접속이-되었다">성공적으로 접속이 되었다!</h3>
<p>준비는 끝났고 로그인 API를 띄워서 APP의 Retrofit 통신을 확인작업을 하면되겠다.</p>
<h2 id="git에-올리기">Git에 올리기</h2>
<p>깃 설정을 하고 커밋과 푸쉬를 해주면 깃에 서버를 사용할수 있는 코드가 올라가게 된다!</p>
<p><a href="https://github.com/WrappingorNot/Django_server">https://github.com/WrappingorNot/Django_server</a></p>
<p>이제 AWS서버를 어떤 형태든지 쓸수 있게 되었다!</p>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/2d732978-91d3-4b9c-ada2-c1ffeaa6ca84/image.png" alt=""></p>
<p>AWS서버에 접속 해서 git 코드를 Clone 해주었다.</p>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/827df3ab-1303-45cc-9d1f-befdeed7c879/image.png" alt=""></p>
<p>서버에서 git clone한 프로젝트의 필요한 패키지를 전부 다운받았다,.</p>
<p>그리고 runserver 8080 포트로 열었다.</p>
<p>그전에 서버에서 접속이 될수 있도록 인바운드 규칙에 추가하자.</p>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/25ee9dea-9911-4059-ba5e-e9e18c49adc1/image.png" alt=""></p>
<p>위 주소는 서버를 통한 Django를 배포한것이다.</p>
<p>그러나 위처럼 오류가 발생되었다. setting의 ALLOWED_HOST의 설정이 안되었기 때문에 </p>
<p>아래처럼 로컬 장고에서 설정을 하고 git push를 해준다.</p>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/86b441af-26d4-41b0-842e-7f86c6122fa7/image.png" alt=""></p>
<p>다시 접속 하게끔 python3 <a href="http://manage.py">manage.py</a> runserver 0:8080입력하면 </p>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/bfd91f7a-250a-4d76-91cc-acd081dab18c/image.png" alt=""></p>
<h2 id="성공">성공!!!</h2>
<p>가상 환경시 경로가 잘되어있는지 확인하자</p>
<p>uwsgi --http :8080 --home /home/ubuntu/myvenv/ --chdir /srv/Django_server/mysite/ -w mysite.wsgi</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Django DisallowedHost 오류 ]]></title>
            <link>https://velog.io/@wrapping_not/Django-DisallowedHost-%EC%98%A4%EB%A5%98</link>
            <guid>https://velog.io/@wrapping_not/Django-DisallowedHost-%EC%98%A4%EB%A5%98</guid>
            <pubDate>Fri, 24 Mar 2023 01:40:22 GMT</pubDate>
            <description><![CDATA[<h2 id="장고-오류">장고 오류</h2>
<ul>
<li>3일차에 만들어놓은 장고 서버가 오늘 날짜로 들어가 보니 아래같은 오류가 발생하였다.<ul>
<li>구글에 검색해보니 ‘0.0.0.0’을 허용을 해야한다는 것이였다.</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/8c4d25d4-8394-422a-b635-bf56db0dda2f/image.png" alt=""></p>
<h2 id="해결하기">해결하기</h2>
<ul>
<li>setting 파일에 들어가서 ALLOW_HOSTS를 찾은 다음</li>
</ul>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/aee85010-09ab-4fc8-94a0-5473a00de79d/image.png" alt=""></p>
<ul>
<li>로컬로도 접속 할 수 있도록 허용 해주었다.</li>
</ul>
<h2 id="결과">결과</h2>
<ul>
<li>해결 완료~!</li>
</ul>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/e3d57d9f-2d12-4425-bdbb-fc65c5742cae/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[사이드 프로젝트 3일차]]></title>
            <link>https://velog.io/@wrapping_not/%EC%82%AC%EC%9D%B4%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-3%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@wrapping_not/%EC%82%AC%EC%9D%B4%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-3%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Wed, 22 Mar 2023 11:36:53 GMT</pubDate>
            <description><![CDATA[<h2 id="회원가입-화면-만들기">회원가입 화면 만들기</h2>
<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
    xmlns:tools=&quot;http://schemas.android.com/tools&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    android:background=&quot;#164A8A&quot;
    tools:context=&quot;.MainActivity&quot;
    android:layout_gravity=&quot;center&quot;
    android:focusableInTouchMode=&quot;true&quot;&gt;

    &lt;RelativeLayout
        android:id=&quot;@+id/relativeLayout&quot;
        android:layout_width=&quot;308dp&quot;
        android:layout_height=&quot;482dp&quot;
        android:layout_marginStart=&quot;24dp&quot;
        android:layout_marginEnd=&quot;24dp&quot;
        android:layout_marginBottom=&quot;100dp&quot;
        android:elevation=&quot;10dp&quot;
        android:background=&quot;@drawable/edittext_background&quot;
        app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
        app:layout_constraintEnd_toEndOf=&quot;parent&quot;
        app:layout_constraintHorizontal_bias=&quot;0.49&quot;
        app:layout_constraintStart_toStartOf=&quot;parent&quot;&gt;

        &lt;LinearLayout
            android:layout_width=&quot;298dp&quot;
            android:layout_height=&quot;473dp&quot;
            android:layout_marginStart=&quot;10dp&quot;
            android:layout_marginTop=&quot;10dp&quot;
            android:layout_marginEnd=&quot;10dp&quot;
            android:layout_marginBottom=&quot;10dp&quot;
            android:orientation=&quot;vertical&quot;&gt;

            &lt;TextView

                android:id=&quot;@+id/textView2&quot;
                android:layout_width=&quot;wrap_content&quot;
                android:layout_height=&quot;wrap_content&quot;
                android:layout_alignParentStart=&quot;true&quot;
                android:layout_alignParentTop=&quot;true&quot;
                android:layout_marginStart=&quot;68dp&quot;
                android:layout_marginTop=&quot;22dp&quot;
                android:gravity=&quot;center_horizontal&quot;
                android:lineSpacingExtra=&quot;10sp&quot;
                android:text=&quot;Create an Account&quot;
                android:textColor=&quot;#004648&quot;
                android:textSize=&quot;20sp&quot;
                android:textStyle=&quot;bold&quot; /&gt;

            &lt;EditText
                android:id=&quot;@+id/edt_id&quot;
                android:layout_width=&quot;match_parent&quot;
                android:layout_height=&quot;70dp&quot;
                android:layout_marginTop=&quot;20dp&quot;
                android:hint=&quot;ID&quot;&gt;&lt;/EditText&gt;

            &lt;EditText
                android:id=&quot;@+id/edt_pw&quot;
                android:layout_width=&quot;match_parent&quot;
                android:layout_height=&quot;70dp&quot;
                android:layout_marginTop=&quot;20dp&quot;
                android:hint=&quot;Password&quot;&gt;&lt;/EditText&gt;

            &lt;EditText
                android:id=&quot;@+id/edt_major&quot;
                android:layout_width=&quot;match_parent&quot;
                android:layout_height=&quot;70dp&quot;
                android:layout_marginTop=&quot;20dp&quot;
                android:hint=&quot;전공&quot;&gt;&lt;/EditText&gt;

            &lt;EditText
                android:id=&quot;@+id/edt_place&quot;
                android:layout_width=&quot;match_parent&quot;
                android:layout_height=&quot;70dp&quot;
                android:layout_marginTop=&quot;20dp&quot;
                android:hint=&quot;근무지&quot;&gt;&lt;/EditText&gt;

        &lt;/LinearLayout&gt;

    &lt;/RelativeLayout&gt;

    &lt;androidx.appcompat.widget.AppCompatButton
        android:id=&quot;@+id/button&quot;
        android:layout_width=&quot;300dp&quot;
        android:layout_height=&quot;48dp&quot;
        android:layout_marginTop=&quot;20dp&quot;
        android:background=&quot;@drawable/button_white&quot;
        android:text=&quot;Sign up&quot;
        android:textColor=&quot;#004648&quot;
        android:textSize=&quot;18sp&quot;
        app:layout_constraintEnd_toEndOf=&quot;@+id/relativeLayout&quot;
        app:layout_constraintStart_toStartOf=&quot;@+id/relativeLayout&quot;
        app:layout_constraintTop_toBottomOf=&quot;@+id/relativeLayout&quot; /&gt;

&lt;/androidx.constraintlayout.widget.ConstraintLayout&gt;
</code></pre><ul>
<li><p>XML 코드!</p>
</li>
<li><p>아래는 코드의 결과!</p>
<p> <img src="https://velog.velcdn.com/images/wrapping_not/post/b8f2221d-9a4d-45c3-b399-01fadbae1f6b/image.png" alt=""></p>
<ul>
<li>아래는 액티비티 코드! (각자의 기능 구현은 서버를 구성하고 연결해줄 예정이다)
<img src="https://velog.velcdn.com/images/wrapping_not/post/e54d8835-bce2-4d55-bd1d-5ab654c81a65/image.png" alt=""></li>
</ul>
</li>
</ul>
<h2 id="aws서버-구성">AWS서버 구성</h2>
<h2 id="개발환경">개발환경</h2>
<ul>
<li>mac os (13.0 Ventura)</li>
<li>AWS EC2 로 서버 생성</li>
</ul>
<p><a href="https://www.youtube.com/watch?v=Pv2yDJ2NKQA">AWS - EC2 기본 사용법</a></p>
<ul>
<li>위의 영상을 참고 하여 생성</li>
</ul>
<h2 id="목표">목표</h2>
<ul>
<li>Django 를 서버에 띄우기</li>
<li>Android App을 통해 서버 접속할 수 있게 한다.</li>
</ul>
<h2 id="aws">AWS</h2>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/60e632df-ea5f-4a8b-8ecf-d7b0bc58382e/image.png" alt=""></p>
<p>간단한 설명 그림 </p>
<h2 id="사용하려는-이유">사용하려는 이유</h2>
<ol>
<li>확장성이 좋다</li>
<li>탄력성이 좋다</li>
<li>높은 접근성</li>
<li>장애 허용성 </li>
</ol>
<h2 id="인스턴스-생성">인스턴스 생성</h2>
<ul>
<li>인스턴스 시작버튼을 눌러서 생성한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/d61e004f-6f72-4052-918f-1fd92116242a/image.png" alt=""></p>
<h2 id="server-선택">Server 선택</h2>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/1a05f5cf-4a4a-4898-bffc-152f605b294e/image.png" alt=""></p>
<p>20.04 버전 우분투 사용 </p>
<p>인스턴스 유형은 t2.micro</p>
<h3 id="amazon-linux-와-ubuntu의-차이점">Amazon Linux 와 Ubuntu의 차이점</h3>
<ul>
<li>아마존은 돈만 낸다면 어떤 지원이든 편하게 받을수 있다</li>
<li>Ubuntu는 많은 개발자들이 전세계에 있기 때문에 Stack overflow나 여러 개발 커뮤니티에서 도움을 얻을수 있다</li>
</ul>
<p>→ Ubuntu를 선택하게 되었다. </p>
<p>인스턴스는 1개로 정했다. ₩(인스턴스란 클라우딩 컴퓨터이며, 갯수를 늘리면 컴퓨터의 갯수도 늘어난다.) </p>
<h3 id="인스턴스-생성-완료">인스턴스 생성 완료</h3>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/ffdf15f3-e582-4315-88d5-956b4829e56a/image.png" alt=""></p>
<p>인스턴스 생성이 완료 되었다.</p>
<h2 id="중요">중요!</h2>
<p>키페어를 생성 했다면 키페어 파일이 다운로드 된다.</p>
<p>나중에 이 파일을 잃어버리게 되면 다시는 인스턴스에 접속 할수 없게 되니 잃어버리지 않도록 하자.</p>
<h2 id="연결-하기">연결 하기</h2>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/73df72eb-2cd1-49dc-a348-eb0709b7ba0f/image.png" alt=""></p>
<p>연결 버튼을 누른다.</p>
<h3 id="연결-성공">연결 성공</h3>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/8304345d-2ee4-4615-899a-2bb982152102/image.png" alt=""></p>
<ul>
<li>이 화면에서 인스턴스들을 운용, 사용할수 있다.</li>
<li>사용하고 있는 컴퓨터에서 사용하려면 SSH 클라이언트 기능을 사용하면 된다.</li>
</ul>
<h3 id="누구나-접속-할수-있도록-설정하기">누구나 접속 할수 있도록 설정하기</h3>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/89e4fa65-4967-4e60-9c82-b5b597e172c2/image.png" alt=""></p>
<ul>
<li>sudo apt update 명령어를 이용하여 최신버전으로 업데이트 시켜준다</li>
</ul>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/1908ef0d-4179-4010-8cd9-2402de845218/image.png" alt=""></p>
<ul>
<li>sudo apt install apache2 를 통해 apache를 설치하면 내게 주어진 웹서버 주소를 통해 누구나 내가 만든 서버로 접속 할 수 있게 된다.</li>
<li>이제 나에게 주어진 IP주소를 입력하면 접속 할수 있다.</li>
</ul>
<h3 id="접속방법">접속방법</h3>
<ul>
<li>바로 접속은 안된다. → 방화벽 설정을 끝내야 사용가능 (웹에서 사용하는 80번 포트를 안열었기 때문)</li>
</ul>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/691794ca-5c34-4df9-a63b-f2b50c2c9105/image.png" alt=""></p>
<ul>
<li>인바운드 규칙<ul>
<li>최소한으로 열어야 한다</li>
</ul>
</li>
<li>아웃바운드 규칙<ul>
<li>전체 가 열려있어야 한다.</li>
</ul>
</li>
</ul>
<p>인바운드 규칙을 추가하고, HTTP로 설정한다음 0.0.0.0/0 까지 지정해주면 어떤 IP든지 접속할수 있도록 하게 된다.  </p>
<p>다시 한번더 접속하게 되면 아래처럼 나오게 된다.</p>
<h2 id="접속성공">접속성공</h2>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/d4636311-c443-47f0-9c7d-865463525118/image.png" alt=""></p>
<h3 id="가격">가격</h3>
<p>1년동안은 프리티어로 무료로 사용가능 하다.</p>
<p><a href="https://aws.amazon.com/ko/free/?trk=fa2d6ba3-df80-4d24-a453-bf30ad163af9&amp;sc_channel=ps&amp;s_kwcid=AL!4422!3!563761819834!e!!g!!aws&amp;ef_id=Cj0KCQiAw8OeBhCeARIsAGxWtUzywAJYqRxPzJqEwYNJQET_A2m9pqGzPK4GJnMqvHNZ4PooOKSpBzkaAuCFEALw_wcB:G:s&amp;s_kwcid=AL!4422!3!563761819834!e!!g!!aws&amp;all-free-tier.sort-by=item.additionalFields.SortRank&amp;all-free-tier.sort-order=asc&amp;awsf.Free%20Tier%20Types=*all&amp;awsf.Free%20Tier%20Categories=*all">무료 클라우드 컴퓨팅 서비스 - AWS 프리 티어</a></p>
<p>이 페이지에서 1년이 지난후에 구매해야 한다. 서비스를 지속적으로 사용하려면 구매 필수…</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프래그먼트 다루기]]></title>
            <link>https://velog.io/@wrapping_not/%ED%94%84%EB%9E%98%EA%B7%B8%EB%A8%BC%ED%8A%B8-%EB%8B%A4%EB%A3%A8%EA%B8%B0-w0trfnen</link>
            <guid>https://velog.io/@wrapping_not/%ED%94%84%EB%9E%98%EA%B7%B8%EB%A8%BC%ED%8A%B8-%EB%8B%A4%EB%A3%A8%EA%B8%B0-w0trfnen</guid>
            <pubDate>Wed, 22 Mar 2023 11:12:05 GMT</pubDate>
            <description><![CDATA[<p>안드로이드에서 프래그먼트(Fragment)란 액티비티(Activity) 내에서 화면 UI 일부를 나타내는 작은 조각입니다. 프래그먼트는 액티비티와 비슷한 생명주기를 가지며, 액티비티 내에서 여러 개의 프래그먼트를 조합하여 화면을 구성할 수 있습니다.
<img src="https://velog.velcdn.com/images/wrapping_not/post/89a24219-bcde-441d-be03-81f80b9b63b3/image.png" alt=""></p>
<ul>
<li>프래그먼트는 서로 다른 크기의 화면을 가진 기기에서 하나의 액티비티로 서로 다른 레이아웃을 구성할 수 있도록 설계되었습니다.</li>
<li>목록 프래그먼트와 상세 프래그먼트가 있을 때 태블릿 같은 큰화면에서는 두 프래그먼트를 한 화면에 표시하고 스마트폰 처럼 작은 화면에서는 먼저 목록 프래그먼트만 표시한 후에 목록을 클릭 하면 상세 가 나타나는 구조 입니다.</li>
<li>뷰가 하나만 필요 할 때는 프래그먼트를 사용하지 않습니다.</li>
</ul>
<h2 id="프래그먼트-생명주기">프래그먼트 생명주기</h2>
<p>프래그먼트의 생명주기는 다음과 같습니다.</p>
<ol>
<li>onAttach() : 프래그먼트가 액티비티에 붙을 때 호출됩니다.</li>
<li>onCreate() : 프래그먼트가 생성될 때 호출됩니다.</li>
<li>onCreateView() : 프래그먼트의 UI를 그리기 위해 호출됩니다.</li>
<li>onActivityCreated() : 프래그먼트가 액티비티와 연결되었을 때 호출됩니다.</li>
<li>onStart() : 프래그먼트가 화면에 표시될 때 호출됩니다.</li>
<li>onResume() : 프래그먼트가 화면에 표시된 후 호출됩니다.</li>
<li>onPause() : 프래그먼트가 일시적으로 화면에서 사라질 때 호출됩니다.</li>
<li>onStop() : 프래그먼트가 화면에서 완전히 사라질 때 호출됩니다.</li>
<li>onDestroyView() : 프래그먼트의 UI가 제거될 때 호출됩니다.</li>
<li>onDestroy() : 프래그먼트가 제거될 때 호출됩니다.</li>
<li>onDetach() : 프래그먼트가 액티비티에서 분리될 때 호출됩니다.</li>
</ol>
<h2 id="결론">결론</h2>
<p>프래그먼트는 안드로이드에서 화면을 구성하는 중요한 요소 중 하나입니다. 액티비티와 비슷한 생명주기를 가지며, 액티비티 내에서 여러 개의 프래그먼트를 조합하여 다양한 UI를 구성할 수 있습니다.</p>
<h3 id=""></h3>
<h2 id="프래그먼트-만들기">프래그먼트 만들기</h2>
<ul>
<li>onCreateView() 메서드는 리사이클러뷰의 onCreateViewHolder() 메서드 처럼 동작합니다. 
→ 액티비티가 프래그먼트를 요청하면 onCreateView() 메서드를 통해 뷰를 만들어 보여줍니다.</li>
<li>inflate() 메서드는 리사이클러뷰 처럼 동일하게 동작합니다.</li>
<li>BlankFragment를 생성하고 아래와 같이 코드를 작성 합니다.</li>
</ul>
<pre><code class="language-kotlin">class ListFragment : Fragment() {



    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_list, container, false)
    }

}</code></pre>
<ul>
<li>inflater: 레이아웃 파일을 로드하기위한 인플레이터를 기본으로 제공합니다.</li>
<li>container: 프래그먼트 레이아웃이 배치되는 부모 레이아웃(액티비티 레이아웃 입니다)</li>
<li>savedInstanceState: 상태값을 저장하기 위한 보조 도구, 액티비티의 onCreate와 동일하게 동작합니다.</li>
</ul>
<p>프래그먼트에서 액티비티의 레이아웃을 inflate 하기 위해서는 onCreateView() 메서드에서 LayoutInflater를 사용합니다. 액티비티와 연결된 레이아웃을 inflate 하려면 container 매개변수에 액티비티의 레이아웃을 전달하면 됩니다.</p>
<p>또한, 프래그먼트에서 버튼과 텍스트뷰를 사용하기 위해서는 inflate된 레이아웃의 View 객체를 먼저 가져와야 합니다. 이후 findViewById()를 사용하여 버튼과 텍스트뷰를 찾아와서 사용할 수 있습니다.</p>
<p>아래는 액티비티와 연결된 레이아웃에 텍스트뷰와 버튼을 띄우는 샘플 코드입니다.</p>
<pre><code>class ExampleFragment : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        val view = inflater.inflate(R.layout.fragment_example, container, false)

        // TextView와 Button을 찾아온다
        val textView = view.findViewById&lt;TextView&gt;(R.id.textview)
        val button = view.findViewById&lt;Button&gt;(R.id.button)

        // Button 클릭 시 TextView에 텍스트를 추가한다
        button.setOnClickListener {
            textView.text = &quot;버튼이 클릭되었습니다.&quot;
        }

        return view
    }
}
</code></pre><p>위 코드에서 R.layout.fragment_example은 액티비티와 연결된 레이아웃 파일의 이름입니다. 이를 적절하게 수정해야 합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[컨테이너: 목록 만들기]]></title>
            <link>https://velog.io/@wrapping_not/%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-%EB%AA%A9%EB%A1%9D-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@wrapping_not/%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-%EB%AA%A9%EB%A1%9D-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Wed, 22 Mar 2023 08:44:19 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/wrapping_not/post/a5dac77c-f2e2-46a2-9bd9-9622cb193964/image.png" alt=""></p>
<h2 id="listview-사용하기">ListView 사용하기</h2>
<p>ListView는 안드로이드에서 가장 많이 사용되는 목록 뷰 중 하나입니다. ListView를 사용하면 단순한 목록부터 복잡한 목록까지 쉽게 구현할 수 있습니다.</p>
<h3 id="1-xml-레이아웃에-listview-추가하기">1. XML 레이아웃에 ListView 추가하기</h3>
<p>ListView를 사용하려면 먼저 XML 레이아웃 파일에 ListView를 추가해야 합니다. 예를 들어, activity_main.xml 파일에 ListView를 추가하려면 다음과 같이 작성합니다.</p>
<pre><code>&lt;ListView
    android:id=&quot;@+id/list_view&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot; /&gt;
</code></pre><h3 id="2-데이터-소스-생성하기">2. 데이터 소스 생성하기</h3>
<p>ListView에 표시할 데이터를 생성합니다. 이 예제에서는 문자열 배열을 사용합니다.</p>
<pre><code>val items = arrayOf(&quot;Apple&quot;, &quot;Banana&quot;, &quot;Orange&quot;, &quot;Grapes&quot;)</code></pre><h3 id="3-어댑터-생성하기">3. 어댑터 생성하기</h3>
<p>ListView의 데이터를 관리하는 어댑터를 생성합니다. ArrayAdapter를 사용하면 간단하게 문자열 배열을 ListView에 표시할 수 있습니다.</p>
<pre><code>ArrayAdapter&lt;String&gt; adapter = new ArrayAdapter&lt;String&gt;(this, android.R.layout.simple_list_item_1, items);
</code></pre><h3 id="4-listview에-어댑터-설정하기">4. ListView에 어댑터 설정하기</h3>
<p>ListView에 어댑터를 설정합니다.</p>
<pre><code>ListView listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);
</code></pre><h2 id="recyclerview-사용하기">RecyclerView 사용하기</h2>
<p>RecyclerView는 안드로이드에서 최근에 등장한 목록 뷰입니다. ListView보다 더 유연하고 성능도 좋습니다.</p>
<h3 id="1-xml-레이아웃에-recyclerview-추가하기">1. XML 레이아웃에 RecyclerView 추가하기</h3>
<p>RecyclerView를 사용하려면 먼저 XML 레이아웃 파일에 RecyclerView를 추가해야 합니다. 예를 들어, activity_main.xml 파일에 RecyclerView를 추가하려면 다음과 같이 작성합니다.</p>
<pre><code>&lt;androidx.recyclerview.widget.RecyclerView
    android:id=&quot;@+id/recycler_view&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot; /&gt;
</code></pre><h3 id="2-데이터-소스-생성하기-1">2. 데이터 소스 생성하기</h3>
<p>ListView와 마찬가지로 RecyclerView에 표시할 데이터를 생성합니다. 이 예제에서는 문자열 배열을 사용합니다.</p>
<pre><code>String[] items = new String[] {&quot;Apple&quot;, &quot;Banana&quot;, &quot;Orange&quot;, &quot;Grapes&quot;};
</code></pre><h3 id="3-어댑터-생성하기-1">3. 어댑터 생성하기</h3>
<p>RecyclerView의 데이터를 관리하는 어댑터를 생성합니다. RecyclerView.Adapter를 상속받는 어댑터를 만듭니다.</p>
<pre><code>public class MyAdapter extends RecyclerView.Adapter&lt;MyAdapter.ViewHolder&gt; {

    private String[] items;

    public MyAdapter(String[] items) {
        this.items = items;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.textView.setText(items[position]);
    }

    @Override
    public int getItemCount() {
        return items.length;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        TextView textView;

        public ViewHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(android.R.id.text1);
        }
    }
}
</code></pre><h3 id="4-recyclerview에-어댑터-설정하기">4. RecyclerView에 어댑터 설정하기</h3>
<p>RecyclerView에 어댑터를 설정합니다.</p>
<pre><code>RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(new MyAdapter(items));
</code></pre><p>이렇게 ListView와 RecyclerView를 사용하여 안드로이드에서 목록을 만들 수 있습니다.</p>
<h2 id="안드로이드-컨테이너-스피너-만들기">안드로이드 컨테이너: 스피너 만들기</h2>
<h3 id="1-xml-레이아웃에-spinner-추가하기">1. XML 레이아웃에 Spinner 추가하기</h3>
<p>Spinner를 사용하려면 먼저 XML 레이아웃 파일에 Spinner를 추가해야 합니다. 예를 들어, activity_main.xml 파일에 Spinner를 추가하려면 다음과 같이 작성합니다.</p>
<pre><code>&lt;Spinner
    android:id=&quot;@+id/spinner&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot; /&gt;
</code></pre><h3 id="2-데이터-소스-생성하기-2">2. 데이터 소스 생성하기</h3>
<p>Spinner에 표시할 데이터를 생성합니다. 이 예제에서는 문자열 배열을 사용합니다.</p>
<pre><code>// 데이터 소스 생성하기
val items = arrayOf(&quot;Apple&quot;, &quot;Banana&quot;, &quot;Orange&quot;, &quot;Grapes&quot;)
</code></pre><h3 id="3-어댑터-생성하기-2">3. 어댑터 생성하기</h3>
<p>Spinner의 데이터를 관리하는 어댑터를 생성합니다. ArrayAdapter를 사용하면 간단하게 문자열 배열을 Spinner에 표시할 수 있습니다.</p>
<pre><code>// 어댑터 생성하기
val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, items)
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
</code></pre><h3 id="4-spinner에-어댑터-설정하기">4. Spinner에 어댑터 설정하기</h3>
<p>Spinner에 어댑터를 설정합니다.</p>
<pre><code>
// Spinner에 어댑터 설정하기
val spinner = findViewById&lt;Spinner&gt;(R.id.spinner)
spinner.adapter = adapter
</code></pre><p>이렇게 Spinner를 사용하여 안드로이드에서 선택할 수 있는 목록을 만들 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[생명 주기 콜백의 이해]]></title>
            <link>https://velog.io/@wrapping_not/%EC%83%9D%EB%AA%85-%EC%A3%BC%EA%B8%B0-%EC%BD%9C%EB%B0%B1%EC%9D%98-%EC%9D%B4%ED%95%B4</link>
            <guid>https://velog.io/@wrapping_not/%EC%83%9D%EB%AA%85-%EC%A3%BC%EA%B8%B0-%EC%BD%9C%EB%B0%B1%EC%9D%98-%EC%9D%B4%ED%95%B4</guid>
            <pubDate>Wed, 22 Mar 2023 08:19:52 GMT</pubDate>
            <description><![CDATA[<ul>
<li>액티비티는 인스턴스 생성과 동시에 생성과 관련된 생명 주기 메서드가 순차적으로 호출됩니다.</li>
<li>finish() 메서드나 뒤로가기로 액티비티를 종료하면 소멸과 관련된 생명주기 메서드가 순차적으로 호출됩니다.</li>
</ul>
<h2 id="액티비티-생명-주기">액티비티 생명 주기</h2>
<ul>
<li>onCreate(): 액티비티가 생성될 때 호출됩니다. 여기서 액티비티 초기화를 수행합니다.</li>
<li>onStart(): 액티비티가 사용자에게 보여지기 전에 호출됩니다.</li>
<li>onResume(): 액티비티가 포그라운드에 위치하고 있을 때 호출됩니다. 이 시점에서 애니메이션 및 오디오 재생과 같은 리소스를 할당하는 것이 좋습니다.</li>
<li>onPause(): 액티비티가 일시 중지되었을 때 호출됩니다. 포그라운드에 위치하지 않지만 화면에 여전히 보이는 경우도 있습니다.</li>
<li>onStop(): 액티비티가 더 이상 사용자에게 표시되지 않을 때 호출됩니다.</li>
<li>onDestroy(): 액티비티가 소멸될 때 호출됩니다. 리소스 해제 및 전체적인 정리를 수행합니다.</li>
</ul>
<h2 id="프레그먼트-생명-주기">프레그먼트 생명 주기</h2>
<ul>
<li>onAttach(): 프래그먼트가 액티비티에 붙을 때 호출됩니다.</li>
<li>onCreate(): 프래그먼트가 생성될 때 호출됩니다. 여기서 초기화를 수행합니다.</li>
<li>onCreateView(): 뷰를 생성하고 반환합니다. 여기서 UI 구성 요소를 초기화합니다.</li>
<li>onActivityCreated(): 액티비티에서 프래그먼트의 onCreate() 메서드 호출이 완료된 후에 호출됩니다.</li>
<li>onStart(): 프래그먼트가 사용자에게 보여지기 전에 호출됩니다.</li>
<li>onResume(): 프래그먼트가 포그라운드에 위치하고 있을 때 호출됩니다. 이 시점에서 애니메이션 및 오디오 재생과 같은 리소스를 할당하는 것이 좋습니다.</li>
<li>onPause(): 프래그먼트가 일시 중지되었을 때 호출됩니다. 포그라운드에 위치하지 않지만 화면에 여전히 보이는 경우도 있습니다.</li>
<li>onStop(): 프래그먼트가 더 이상 사용자에게 표시되지 않을 때 호출됩니다.</li>
<li>onDestroyView(): 프래그먼트의 UI가 제거됩니다. 여기서 뷰와 관련된 리소스를 해제합니다.</li>
<li>onDestroy(): 프래그먼트가 소멸될 때 호출됩니다. 리소스 해제 및 전체적인 정리를 수행합니다.</li>
<li>onDetach(): 프래그먼트가 액티비티에서 분리될 때 호출됩니다.</li>
</ul>
<h2 id="액티비티-백스택">액티비티 백스택</h2>
<ul>
<li>백스택은 액티비티 또는 화면 컴포넌트를 담는 안드로이드의 저장 공간입니다.</li>
<li>새로운 액티비티가 시작되면 이전 액티비티는 백스택에 저장됩니다. 이전 액티비티는 사용자가 뒤로가기 버튼을 누르거나 finish() 메서드를 호출하여 종료될 수 있습니다. 사용자가 뒤로가기 버튼을 누르면 백스택에서 가장 최근에 저장된 액티비티가 화면에 표시됩니다. 이것은 액티비티를 백그라운드에서 실행하고 다시 포그라운드로 가져오는 데 사용됩니다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/e5808217-2ea6-4555-a24b-47b4cf81811a/image.png" alt=""></p>
<h2 id="태스크와-프로세스">태스크와 프로세스</h2>
<ul>
<li>태스크(Task)는 어플에서 실행되는 프로세스를 관리하는 작업 단위입니다.</li>
<li>안드로이드에서 태스크는 다른 프로세스의 액티비티를 담을 수 있습니다.</li>
<li>안드로이드는 서로 다른 어플리케이션의 액티비티를 공유 할 수 있는데 카메라와 갤러리 액티비티를 예로 들수 있습니다. 카메라 기능을 간단한 코드로 호출해서 사용하명 실제로능 카메라 앱의 독자적인 프로세스가 실행되고 카메라 액티비티 또한 카메라 앱의 프로세스에 의해 처리됩니다.</li>
<li>인텐트를 통해 카메라앱에 전달하는 코드를 구현하면 다음과 같습니다.</li>
</ul>
<pre><code class="language-kotlin">fun openCamera() {
    val intent - Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    activityResult.launch(intent)
}</code></pre>
<ul>
<li><p>카메라를 사용하기 위한 인텐트를 시스템으로 전달하면 카메라 액티비티가 다른 앱이 있기 때문에 프로세스를 새로 생성합니다.</p>
<p>  → 호출된 카메라 액티비티가 새로운 프로세스를 통해 동작하지만 하나의 작업 단위인 태스크로 묶입니다. 결국 하나의 앱처럼 동일한 태스크로 묶이고 백스택에 쌓이게 됩니다. </p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/3c2de51e-9d5d-470f-a0fd-5805e04e464b/image.png" alt=""></p>
<ul>
<li>같은 태스크의 백스택에 쌓이기 때문에 뒤로가기 버튼을 누르면 같은 앱의 액티비티 처럼 백스택에서 제거되고 , 홈버튼을 누르면 마치 하나의 태스크 전체가 백그라운드로 이동합니다.</li>
</ul>
<h2 id="액티비티-태스크-관리하기">액티비티 태스크 관리하기</h2>
<p>액티비티 태스크는 두 가지 방법으로 관리할 수 있습니다. 먼저는 매니패스트의 설정으로 관리하는 방법입니다. </p>
<p><activity>태그 안의 속성으로 사용할 수 있습니다. </p>
<p>⇒ <activity android:name=”.MainActivity” android:luanchMode=”singleInstance”></activity></p>
<ul>
<li>launchMode: 액티비티의 launchMode 속성을 이용하여 태스크 관리를 할 수 있습니다. launchMode에는 <code>standard</code>, <code>singleTop</code>, <code>singleTask</code>, <code>singleInstance</code>가 있으며, 각각 다른 태스크 관리 방식을 가집니다.</li>
<li>Intent Flag: Intent Flag를 이용하여 태스크 관리를 할 수 있습니다. <code>FLAG_ACTIVITY_NEW_TASK</code>, <code>FLAG_ACTIVITY_CLEAR_TOP</code>, <code>FLAG_ACTIVITY_SINGLE_TOP</code> 등이 있으며, 각각 다른 태스크 관리 방식을 가집니다.</li>
<li>TaskAffinity: TaskAffinity 속성을 이용하여 액티비티가 속할 태스크를 지정할 수 있습니다. TaskAffinity 속성을 이용하여 액티비티가 속한 태스크의 관리를 세부적으로 조정할 수 있습니다.</li>
</ul>
<p>태스크 관리를 잘 이용하면 앱의 사용자 경험을 개선할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[사이드 프로젝트 2일차
]]></title>
            <link>https://velog.io/@wrapping_not/%EC%82%AC%EC%9D%B4%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-2%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@wrapping_not/%EC%82%AC%EC%9D%B4%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-2%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Tue, 21 Mar 2023 13:19:59 GMT</pubDate>
            <description><![CDATA[<h2 id="로그인-화면-제작하기">로그인 화면 제작하기!</h2>
<ul>
<li>XML 코드</li>
</ul>
<pre><code class="language-kotlin">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
    android:orientation=&quot;vertical&quot;
    android:gravity=&quot;center_horizontal&quot;&gt;

    &lt;TextView
        android:layout_width=&quot;300dp&quot;
        android:layout_height=&quot;300dp&quot;
        android:elevation=&quot;10dp&quot;
        android:fontFamily=&quot;sans-serif-black&quot;
        android:gravity=&quot;center&quot;
        android:includeFontPadding=&quot;false&quot;
        android:text=&quot;GLO;&quot;
        android:textColor=&quot;#1957A3&quot;
        android:textSize=&quot;100dp&quot; /&gt;

    &lt;RelativeLayout
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;match_parent&quot;
        android:layout_marginLeft=&quot;-10dp&quot;
        android:layout_marginTop=&quot;15dp&quot;&gt;

        &lt;androidx.cardview.widget.CardView
            android:id=&quot;@+id/cv&quot;
            android:layout_width=&quot;match_parent&quot;
            android:layout_height=&quot;wrap_content&quot;
            android:layout_marginLeft=&quot;-25dp&quot;
            android:layout_marginTop=&quot;15dp&quot;
            android:layout_marginRight=&quot;50dp&quot;
            app:cardCornerRadius=&quot;70dp&quot;
            app:cardElevation=&quot;5dp&quot;&gt;

            &lt;RelativeLayout
                android:layout_width=&quot;360dp&quot;
                android:layout_height=&quot;wrap_content&quot;
                android:layout_marginLeft=&quot;26dp&quot;
                android:padding=&quot;8dp&quot;&gt;

                &lt;EditText
                    android:id=&quot;@+id/edt_id&quot;
                    android:layout_width=&quot;match_parent&quot;
                    android:layout_height=&quot;wrap_content&quot;
                    android:layout_marginStart=&quot;15dp&quot;
                    android:layout_marginTop=&quot;15dp&quot;
                    android:layout_marginEnd=&quot;15dp&quot;
                    android:layout_marginBottom=&quot;15dp&quot;
                    android:background=&quot;@android:color/transparent&quot;
                    android:drawableLeft=&quot;@drawable/ic_baseline_person_24&quot;
                    android:drawablePadding=&quot;30dp&quot;
                    android:hint=&quot;Username&quot;
                    android:inputType=&quot;text&quot;
                    android:padding=&quot;10dp&quot; /&gt;

                &lt;View
                    android:id=&quot;@+id/view1&quot;
                    android:layout_width=&quot;match_parent&quot;
                    android:layout_height=&quot;2dp&quot;
                    android:layout_below=&quot;@+id/edt_id&quot;
                    android:background=&quot;#71D2D2D2&quot; /&gt;

                &lt;EditText
                    android:id=&quot;@+id/edt_pw&quot;
                    android:layout_width=&quot;match_parent&quot;
                    android:layout_height=&quot;wrap_content&quot;
                    android:layout_below=&quot;@+id/view1&quot;
                    android:layout_marginStart=&quot;15dp&quot;
                    android:layout_marginTop=&quot;15dp&quot;
                    android:layout_marginEnd=&quot;15dp&quot;
                    android:layout_marginBottom=&quot;15dp&quot;
                    android:background=&quot;@android:color/transparent&quot;
                    android:drawableLeft=&quot;@drawable/ic_baseline_lock_24&quot;

                    android:drawablePadding=&quot;30dp&quot;
                    android:hint=&quot;Password&quot;
                    android:inputType=&quot;textPassword&quot;
                    android:padding=&quot;10dp&quot; /&gt;

            &lt;/RelativeLayout&gt;

        &lt;/androidx.cardview.widget.CardView&gt;

        &lt;RelativeLayout
            android:layout_width=&quot;wrap_content&quot;
            android:layout_height=&quot;wrap_content&quot;

            android:layout_alignTop=&quot;@+id/cv&quot;
            android:layout_alignRight=&quot;@+id/cv&quot;
            android:layout_alignBottom=&quot;@+id/cv&quot;
            android:layout_marginRight=&quot;-118dp&quot;

            android:elevation=&quot;20dp&quot;&gt;

            &lt;androidx.appcompat.widget.AppCompatButton
                android:id=&quot;@+id/btLogin&quot;

                android:layout_width=&quot;144dp&quot;
                android:layout_height=&quot;144dp&quot;
                android:layout_alignParentStart=&quot;true&quot;
                android:layout_centerVertical=&quot;true&quot;

                android:layout_marginStart=&quot;144dp&quot;

                android:layout_marginLeft=&quot;190dp&quot;

                android:background=&quot;@drawable/btn_login1&quot;

                android:drawableLeft=&quot;@drawable/ic_baseline_arrow_forward_24&quot;

                android:elevation=&quot;50dp&quot;

                android:shadowRadius=&quot;30&quot;
                android:text=&quot;&quot;
                android:textColor=&quot;@color/white&quot;
                android:textSize=&quot;20sp&quot;&gt;

            &lt;/androidx.appcompat.widget.AppCompatButton&gt;

        &lt;/RelativeLayout&gt;

        &lt;RelativeLayout
            android:layout_width=&quot;wrap_content&quot;
            android:layout_height=&quot;wrap_content&quot;&gt;

        &lt;/RelativeLayout&gt;

        &lt;androidx.appcompat.widget.AppCompatButton
            android:id=&quot;@+id/user_regis&quot;
            android:layout_width=&quot;wrap_content&quot;
            android:layout_height=&quot;wrap_content&quot;
            android:layout_below=&quot;@+id/cv&quot;
            android:layout_marginLeft=&quot;90dp&quot;
            android:layout_marginTop=&quot;30dp&quot;
            android:background=&quot;@drawable/btn_white_left&quot;
            android:text=&quot;user Register&quot;
            android:textColor=&quot;#FFFFFF&quot;
            android:textSize=&quot;14sp&quot; /&gt;

        &lt;androidx.appcompat.widget.AppCompatButton
            android:id=&quot;@+id/admin_regis&quot;
            android:layout_width=&quot;wrap_content&quot;
            android:layout_height=&quot;wrap_content&quot;
            android:layout_below=&quot;@+id/cv&quot;
            android:layout_marginLeft=&quot;210dp&quot;

            android:layout_marginTop=&quot;30dp&quot;

            android:background=&quot;@drawable/btn_white_right&quot;
            android:text=&quot;admin Register&quot;
            android:textColor=&quot;#1957A3&quot;
            android:textSize=&quot;14sp&quot; /&gt;

    &lt;/RelativeLayout&gt;

&lt;/LinearLayout&gt;</code></pre>
<h2 id="액티비티와-연결-하기">액티비티와 연결 하기!</h2>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/2e376dfe-dc38-42d8-b4f2-c3c380749281/image.png" alt=""></p>
<ul>
<li>viewBinding을 사용해서 각 텍스트뷰의 명들과 버튼을 바인딩 시켰습니다.</li>
<li>뷰바인딩을 쓰면 나중에 코드유지 보수하기 쉽도록 하기 위함입니다.</li>
<li>디자인은 잘 못하지만 깔끔하게 만들어 보았습니다.</li>
</ul>
<h1 id="결과물">결과물</h1>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/8fdbf5f8-54e2-4bf5-a878-6accfa274938/image.png" alt=""></p>
<h3 id="다음에-할일">다음에 할일</h3>
<ul>
<li>목록 화면 만들기</li>
<li>데이터 크롤링 하기</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[사이드 프로젝트(Based on Tinder) 1일차]]></title>
            <link>https://velog.io/@wrapping_not/%EC%82%AC%EC%9D%B4%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8Based-on-Tinder-1%EC%9D%BC%EC%B0%A8-co0su0bm</link>
            <guid>https://velog.io/@wrapping_not/%EC%82%AC%EC%9D%B4%EB%93%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8Based-on-Tinder-1%EC%9D%BC%EC%B0%A8-co0su0bm</guid>
            <pubDate>Mon, 20 Mar 2023 13:16:04 GMT</pubDate>
            <description><![CDATA[<ul>
<li>틴더처럼 카드뷰를 통해 앱을 한번 만들어 보려고 한다.</li>
<li>카드뷰를 활용해서 데이터를 띄우기</li>
<li>원하는 데이터 Retrofit을 통해 전달 받기 </li>
<li>문맹률 줄이기</li>
</ul>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/92784d44-9352-495b-b43e-b0403b3eb338/image.png" alt=""></p>
<h3 id="카드뷰를-먼저-만들기-위한-작업-진행">카드뷰를 먼저 만들기 위한 작업 진행</h3>
<ul>
<li>아래 블로그를 참고해서 밑작업을 시작 했다.</li>
</ul>
<p><a href="https://velog.io/@ginee_park/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-Activity%EC%97%90%EC%84%9C-RecylerView-CardView-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0-Kotlin">[안드로이드] Activity에서 RecylerView + CardView 연결하기 (Kotlin)</a></p>
<pre><code>class MainActivity : AppCompatActivity() {
    //databinding
    private lateinit var binding: ActivityMainBinding

    //CardView를 담을 리사이클러 뷰를 lateinit으로 미리 선언해줍니다.
    private lateinit var reCyclerView: RecyclerView
    private lateinit var viewAdapter: RecyclerView.Adapter&lt;*&gt;
    private lateinit var viewManager: RecyclerView.LayoutManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // 1. LinearLayout으로 쌓기위해 초기화
        viewManager = LinearLayoutManager(this, RecyclerView.HORIZONTAL,true )
        // 2. 미리 만들 어댑처를 초기화 한다.
        viewAdapter = MyAdapter()

        // 3. 만들어놓은 리사이클러뷰에 어댑터를 붙이기!
        reCyclerView =binding.recycleView.apply{
// use this setting to improve performance if you know that changes
            // in content do not change the layout size of the RecyclerView
            setHasFixedSize(true)
            // use a linear layout manager
layoutManager= viewManager
            // specify an viewAdapter (see also next example)
adapter= viewAdapter
    }

}
    // 액티비티가 파괴될 때..
    override fun onDestroy() {
        // onDestroy 에서 binding class 인스턴스 참조를 정리해주어야 한다.

        super.onDestroy()
    }</code></pre><ul>
<li>findviewbyID 보다 ViewBinding을 시켜서 보다 쉽고 간결하게 코드를 써보았다.</li>
<li>여기엔 안썼지만 어댑터도 필요하고, 레이아웃도 짜야 한다.
<img src="https://velog.velcdn.com/images/wrapping_not/post/4a147bfe-739c-45c2-91d6-a867dd778db4/image.png" alt=""></li>
</ul>
<ul>
<li>코드의 결과물</li>
<li>조금더 꾸며서 발전 시켜봐야 겠다.</li>
</ul>
<h3 id="다음-할일">다음 할일</h3>
<ul>
<li>회원가입 화면 구성</li>
<li>간단한 심리검사 페이지 구성(리사이클러 뷰를 통해 만들것)</li>
<li>전체 화면 구성 (프래그먼트를 사용할 예정)</li>
<li>DB 구성 및 AWS서버 구성</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[스코프 함수
]]></title>
            <link>https://velog.io/@wrapping_not/%EC%8A%A4%EC%BD%94%ED%94%84-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@wrapping_not/%EC%8A%A4%EC%BD%94%ED%94%84-%ED%95%A8%EC%88%98</guid>
            <pubDate>Mon, 20 Mar 2023 08:50:34 GMT</pubDate>
            <description><![CDATA[<h1 id=""></h1>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/58a82aeb-c60f-453b-b614-55508ecd5d7d/image.png" alt=""></p>
<p>코틀린에서는 스코프 함수라는 특별한 함수가 제공됩니다. 스코프 함수는 객체의 속성에 접근하거나 메서드를 호출하는 등의 작업을 보다 간결하게 처리할 수 있는 기능을 제공합니다.</p>
<ul>
<li>코드를 축약해서 표현할 수 있도록 도와주는 함수, 영역 함수라고도 합니다.</li>
<li>함수처럼 사용은 아하며, run, let처럼 괄호 없이 일종의 키워드로 사용할 수 있습니다.</li>
<li>Safe Call남용을 막아주는 역할도 하기 때문에 많이 사용하는 요소 입니다.</li>
</ul>
<p>스코프 함수에는 다음과 같은 종류가 있습니다.</p>
<h2 id="1-let">1. let</h2>
<p>let 함수는 null이 아닌 객체에 대해서만 수행되며, 객체를 파라미터로 받습니다. 람다식 내에서는 해당 객체를 it 키워드로 참조할 수 있습니다. 반환값은 람다식의 마지막 구문의 결과값입니다.</p>
<pre><code>val name: String? = &quot;John Doe&quot;
name?.let {
    println(it.length) // name이 null이 아닐 때만 실행
}
</code></pre><h2 id="2-also">2. also</h2>
<p>also 함수는 객체를 파라미터로 받고, 람다식 내에서 해당 객체를 it 키워드로 참조할 수 있습니다. 반환값은 해당 객체 자체입니다.</p>
<pre><code>val list = mutableListOf&lt;String&gt;()
list.also {
    println(&quot;List has been created.&quot;)
}.add(&quot;apple&quot;)
</code></pre><h2 id="3-apply">3. apply</h2>
<p>apply 함수는 객체를 파라미터로 받고, 람다식 내에서 해당 객체를 this 키워드로 참조할 수 있습니다. 반환값은 해당 객체 자체입니다.</p>
<pre><code>val person = Person(&quot;John Doe&quot;).apply {
    age = 30
    gender = &quot;Male&quot;
}
</code></pre><h2 id="4-run">4. run</h2>
<p>run 함수는 let 함수와 유사하지만, 해당 객체를 this 키워드로 참조할 수 있습니다. 반환값은 람다식의 마지막 구문의 결과값입니다.</p>
<pre><code>val result = &quot;John Doe&quot;.run {
    println(length)
    length
}
</code></pre><h2 id="5-with">5. with</h2>
<p>with 함수는 객체를 파라미터로 받고, 람다식 내에서 해당 객체를 this 키워드로 참조할 수 있습니다. 반환값은 람다식의 마지막 구문의 결과값입니다.</p>
<pre><code>val person = Person(&quot;John Doe&quot;)
with(person) {
    age = 30
    gender = &quot;Male&quot;
}
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[지연 초기화]]></title>
            <link>https://velog.io/@wrapping_not/%EC%A7%80%EC%97%B0-%EC%B4%88%EA%B8%B0%ED%99%94</link>
            <guid>https://velog.io/@wrapping_not/%EC%A7%80%EC%97%B0-%EC%B4%88%EA%B8%B0%ED%99%94</guid>
            <pubDate>Mon, 20 Mar 2023 08:38:43 GMT</pubDate>
            <description><![CDATA[<h1 id="코틀린-지연-초기화">코틀린 지연 초기화</h1>
<p>코틀린에서는 변수를 선언할 때 즉시 초기화를 해야 하는데, 때로는 초기화를 뒤로 미루고 싶은 경우가 있습니다. 이때 사용하는 것이 지연 초기화입니다.</p>
<h2 id="lateint">lateint</h2>
<p>lateinit은 &#39;late initialization&#39;의 약자로, 변수를 선언할 때 초기화하지 않고, 추후에 초기화하는 기능입니다.</p>
<p>lateinit 키워드를 사용하여 변수를 선언할 때 초기화를 하지 않아도 되는 장점이 있습니다. 이는 예를 들어, 객체의 생성자에서 초기화할 수 없는 경우에도 사용할 수 있습니다.</p>
<pre><code>lateinit var name: String

fun initializeName() {
    name = &quot;John&quot;
}
</code></pre><p>위 코드에서는 lateinit으로 선언된 name 변수를 선언할 때 초기화하지 않았습니다. 대신, 추후 initializeName() 함수를 호출하여 name 변수를 초기화합니다.</p>
<h3 id="nullable로-선언하는-방법">Nullable로 선언하는 방법</h3>
<ul>
<li>일반적인 선언방식입니다. 처음에는 null을 입력해두고, 클래스의 다른 메서드 영역에서 값을 입력 합니다.</li>
</ul>
<pre><code class="language-kotlin">class Person{
    var name: String? = null
    init{
        name = &quot;Lionel&quot;
    }
    fun process() {
        name?.plus(&quot;Messi&quot;)
        print(&quot;이름의 길이 = ${name?.legth}&quot;)
        print(&quot;이름의 첫 글자 = ${name?.substring(0,1}&quot;)
    }
}</code></pre>
<h3 id="lateinit-특징">lateinit 특징</h3>
<ul>
<li>변수를 선언할 때 즉시 초기화하지 않아도 됨</li>
<li>추후 초기화 가능</li>
<li>nullable로 선언하지 않음</li>
</ul>
<h2 id="lazy">lazy</h2>
<p>lazy는 변수를 최초로 사용할 때에만 초기화하는 기능입니다. 이를 통해 불필요한 초기화를 하지 않고 성능을 높일 수 있습니다.</p>
<pre><code>val name: String by lazy {
    println(&quot;초기화&quot;)
    &quot;John&quot;
}

fun main() {
    println(name)
    println(name)
}
</code></pre><p>위 코드에서는 name 변수를 선언할 때 lazy 키워드를 사용하여 초기화를 뒤로 미루었습니다. 따라서, name 변수를 최초로 사용할 때에만 초기화가 수행됩니다.</p>
<p>이를 통해, 성능이 더 중요한 상황에서 lazy를 사용하여 불필요한 초기화를 줄일 수 있습니다.</p>
<h3 id="lazy특징">Lazy특징</h3>
<ul>
<li>선언 시에 초기화 코드를 함께 작성하기 때문에 따로 초기화 할 필요 없습니다.</li>
<li>lazy로 선언된 변수가 최초 호출되는 시점에 by lazy{} 안에 넣은 값으로 초기화 됩니다. 클래스가 초기화 되더라도 바로 초기화 되지 않고 호출되는 순간 초기화 됩니다.</li>
<li>최초 호출 되는 시점에 초기화 되기 때문에 초기화 리소스가 너무 크면 전체 처리속도에 영향을 미칠수 있으니 복잡한 코드 같은 경우엔 미리 초기화 하는것이 좋습니다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Null Safety]]></title>
            <link>https://velog.io/@wrapping_not/Null-Safety</link>
            <guid>https://velog.io/@wrapping_not/Null-Safety</guid>
            <pubDate>Mon, 20 Mar 2023 07:51:32 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/wrapping_not/post/a46c50f8-f4f1-40a5-bc00-40024ac78127/image.png" alt=""></p>
<p>Null safety란 코틀린에서 null 값을 다룰 때 발생하는 오류를 줄이고 안정적인 코드를 작성하기 위한 기능입니다.</p>
<p>코틀린에서는 기본적으로 null 값을 허용하지 않으며, null 값을 다루기 위해서는 nullable 타입을 사용해야 합니다. nullable 타입은 해당 변수에 null 값을 할당할 수 있도록 해줍니다.</p>
<p>하지만 nullable 타입을 사용할 경우, null 값을 처리하지 않고 그대로 사용하면 NullPointerException이 발생할 수 있습니다. 이를 방지하기 위해 코틀린에서는 안전한 호출(Safe call) 연산자인 ?.와 엘비스 연산자(?:)를 제공합니다.</p>
<p>?. 연산자는 해당 변수가 null이 아닐 때만 호출하고, null일 경우 null을 반환합니다. 엘비스 연산자(?:)는 해당 변수가 null일 경우 대체값을 반환합니다.</p>
<p>또한 코틀린에서는 null 체크를 강제하는 Non-null 타입을 제공합니다. 이를 사용하면 해당 변수에 null 값을 할당할 수 없어 NullPointerException을 방지할 수 있습니다.</p>
<p>이러한 null safety 기능을 적절히 활용하면 안정적이고 오류가 적은 코드를 작성할 수 있습니다.</p>
<h3 id="변수에-null-허용">변수에 null 허용</h3>
<pre><code class="language-kotlin">var nullable: String? //타입 다음에 물음표를 붙여 null 값을 입력할 수 있다.
nullable = null

var notNullable = String
notNullable = null //일반 변수엔 Null을 입력할 수 없습니다. </code></pre>
<h3 id="함수-파라미터에-null-허용">함수 파라미터에 null 허용</h3>
<pre><code>fun printLength(str: String?) {
    println(str?.length ?: &quot;null&quot;)
}

fun main() {
    val str: String? = null
    printLength(str)
}
</code></pre><p>위 코드는 <code>printLength</code> 함수를 정의하고, <code>main</code> 함수에서 <code>printLength</code> 함수를 호출하는 코드입니다.</p>
<p><code>printLength</code> 함수는 nullable한 <code>String</code> 타입의 매개변수 <code>str</code>을 받아 해당 문자열의 길이를 출력합니다. 이 때, <code>str?.length</code>와 같이 안전한 호출 연산자 <code>?.</code>를 사용하여 <code>str</code>이 null일 경우 <code>null</code>을 반환하도록 합니다. 또한, <code>?:</code> 연산자를 사용하여 <code>str?.length</code>가 null일 경우 대체값인 <code>&quot;null&quot;</code>을 반환하도록 합니다.</p>
<p><code>main</code> 함수에서는 nullable한 <code>String</code> 타입의 변수 <code>str</code>을 null로 초기화하고, <code>printLength</code> 함수를 호출합니다. 이 때, <code>printLength</code> 함수에서 안전한 호출 연산자와 엘비스 연산자를 사용하여 <code>str</code>이 null일 경우 <code>&quot;null&quot;</code>을 출력합니다.</p>
<h3 id="함수의-리턴-타입에-null-허용">함수의 리턴 타입에 null 허용</h3>
<p>함수의 리턴타입에 물음표를 붙여서 null 허용 여부를 설정 할 수 있습니다.</p>
<pre><code class="language-kotlin">fun nullReturn(): String?{
        reutn null
    }</code></pre>
<h3 id="안전한-호출-연산자---엘비스-연산자-">안전한 호출 연산자 ?. &amp; 엘비스 연산자 (?:)</h3>
<p>안전한 호출 연산자인 ?.은 해당 변수가 null이 아닐 때만 호출하고, null일 경우 null을 반환합니다. 또한, 엘비스 연산자(?:)는 해당 변수가 null일 경우 대체값을 반환합니다.</p>
<pre><code>var nullable: String? //타입 다음에 물음표를 붙여 null 값을 입력할 수 있다.
nullable = null

var notNullable = String
notNullable = null //일반 변수엔 Null을 입력할 수 없습니다.

fun printLength(str: String?) {
    println(str?.length ?: &quot;null&quot;)
}

fun nullReturn(): String?{
    return null
}
</code></pre><p>위 코드는 nullable한 <code>String</code> 타입의 변수 <code>nullable</code>을 선언하고, null 값을 할당하는 코드입니다. 또한, 일반적인 <code>String</code> 타입의 변수 <code>notNullable</code>은 null 값을 할당할 수 없습니다.</p>
<p><code>printLength</code> 함수는 nullable한 <code>String</code> 타입의 매개변수 <code>str</code>을 받아 해당 문자열의 길이를 출력합니다. 이 때, <code>str?.length</code>와 같이 안전한 호출 연산자 <code>?.</code>를 사용하여 <code>str</code>이 null일 경우 <code>null</code>을 반환하도록 합니다. 또한, <code>?:</code> 연산자를 사용하여 <code>str?.length</code>가 null일 경우 대체값인 <code>&quot;null&quot;</code>을 반환하도록 합니다.</p>
<p><code>nullReturn</code> 함수는 nullable한 <code>String</code> 타입의 값을 리턴하며, 이를 통해 null 값을 리턴할 수 있음을 보여줍니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[코틀린 설계 도구 (패키지, 추상화, 인터페이스, 제네릭)]]></title>
            <link>https://velog.io/@wrapping_not/%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%84%A4%EA%B3%84-%EB%8F%84%EA%B5%AC-%ED%8C%A8%ED%82%A4%EC%A7%80-%EC%B6%94%EC%83%81%ED%99%94-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EC%A0%9C%EB%84%A4%EB%A6%AD</link>
            <guid>https://velog.io/@wrapping_not/%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%84%A4%EA%B3%84-%EB%8F%84%EA%B5%AC-%ED%8C%A8%ED%82%A4%EC%A7%80-%EC%B6%94%EC%83%81%ED%99%94-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EC%A0%9C%EB%84%A4%EB%A6%AD</guid>
            <pubDate>Mon, 20 Mar 2023 07:13:08 GMT</pubDate>
            <description><![CDATA[<p>객체지향 프로그래밍은 구현(실제 로직을 갖는 코딩)과 설계(껍데기만 있는 코딩)으로 구분할 수 있습니다.</p>
<h2 id="패키지">패키지</h2>
<p>컴퓨터 언어에서 패키지 사용의 목적이 설계라고 볼수 있습니다. 패키지는 클래스와 소스 파일을 관리 하기 위한 디렉토리 구조의 저장 공간 입니다.</p>
<p>코틀린에서 패키지는 물리적인 디렉토리 구조로 표현됩니다. 패키지 이름은 소문자로 작성되며, 점(<code>.</code>)으로 구분됩니다. 패키지 내에는 클래스, 함수, 프로퍼티 등이 포함될 수 있습니다. 패키지를 선언할 때는 <code>package</code> 키워드를 사용합니다.</p>
<p>예를 들어, <code>org.example.myproject</code> 패키지 내에 <code>MyClass</code>라는 클래스를 선언하려면 다음과 같이 작성합니다.</p>
<pre><code>package org.example.myproject

class MyClass {
  // ...
}
</code></pre><p>패키지를 지정하지 않으면 기본 패키지가 사용됩니다.</p>
<h2 id="추상화">추상화</h2>
<p>추상화는 객체 지향 프로그래밍에서 중요한 개념 중 하나입니다. 추상화는 객체의 공통적인 특징을 뽑아내어 인터페이스나 추상 클래스 등으로 정의하는 것을 말합니다. 추상화를 통해 객체들 사이의 공통점을 찾는 것이 가능하며, 이를 바탕으로 코드의 유지보수성이나 재사용성을 높일 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/a92dd851-8a6c-44f5-8bb8-8eb2c5485e59/image.png" alt=""></p>
<p>코틀린에서 추상화는 인터페이스나 추상 클래스를 사용하여 구현됩니다. 인터페이스는 객체의 동작 방식을 정의하는 일종의 계약서 역할을 하며, 추상 클래스는 추상 메서드와 구현된 메서드를 모두 포함할 수 있는 클래스입니다. 추상 클래스를 사용하면 공통적인 로직을 구현하고, 상속받은 클래스에서 필요한 부분만 구현할 수 있습니다.</p>
<ul>
<li>쉽게 설명하면 클래스 설계 과정에서 구현해야 하는 메서드의 이름만 명시 하고 구현은 나중에 하는것을 이야기 합니다.</li>
<li>Activity클래스가 상속 받는 클래스중 Context클래스는 abstract로 설계되어있습니다.</li>
</ul>
<p>예를 들어, 다음은 추상 클래스와 인터페이스를 사용하여 추상화를 구현한 코드입니다.</p>
<pre><code>// 추상 클래스
abstract class Animal {
    abstract fun makeSound()
    fun eat() {
        println(&quot;먹는다&quot;)
    }
}

// 인터페이스
interface Flyable {
    fun fly()
}

// 구현 클래스
class Dog: Animal() {
    override fun makeSound() {
        println(&quot;멍멍&quot;)
    }
}

class Bird: Animal(), Flyable {
    override fun makeSound() {
        println(&quot;짹짹&quot;)
    }

    override fun fly() {
        println(&quot;날다&quot;)
    }
}
</code></pre><h3 id="추상화-주의-할-점">추상화 주의 할 점</h3>
<ul>
<li>과도한 추상화는 코드의 복잡도를 증가시킬 수 있습니다. 따라서 필요 이상으로 추상화를 사용하지 않도록 주의해야 합니다.</li>
<li>추상화된 개념을 명확히 정의하고 문서화해야 합니다. 이를 통해 추상화된 개념에 대한 이해도를 높이고, 코드의 가독성을 향상시킬 수 있습니다.</li>
<li>추상화된 개념은 실제로 사용되는 곳에서 검증되어야 합니다. 따라서 코드를 작성하기 전에 프로토타입을 만들어 테스트하는 것이 좋습니다.</li>
<li>추상 클래스는 독립적으로 인스턴스와 할 수 없기 때문에 구현 단계가 고려되지 않는다면 잘못된 설계가 될 수 있습니다.</li>
</ul>
<h2 id="인터페이스">인터페이스</h2>
<p>인터페이스는 객체 지향 프로그래밍에서 중요한 개념 중 하나로, 클래스나 객체가 어떤 메서드를 구현해야 하는지를 정의하는 일종의 계약서 역할을 합니다. 인터페이스는 클래스와 마찬가지로 추상적인 개념이기 때문에 직접 인스턴스화할 수 없습니다. 하지만 인터페이스를 구현하는 클래스를 만들고 해당 클래스를 인스턴스화하여 사용할 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/9ac0ea88-d7bb-49fc-a7ec-08a4f8250cb0/image.png" alt=""></p>
<p>코틀린에서 인터페이스는 <code>interface</code> 키워드를 사용하여 정의됩니다. 인터페이스 내에서는 메서드 또는 프로퍼티를 선언할 수 있으며, 기본적으로 추상 메서드로 선언됩니다. 인터페이스 내에서 구현된 메서드는 없지만, 디폴트 구현을 제공할 수도 있습니다.</p>
<p>예를 들어, 다음은 <code>Runnable</code> 인터페이스를 구현하는 클래스의 예시 코드입니다.</p>
<pre><code>interface Runnable {
    fun run()
}

class MyRunnable : Runnable {
    override fun run() {
        println(&quot;Hello, World!&quot;)
    }
}

val thread = Thread(MyRunnable())
thread.start()
</code></pre><p>이 예시 코드에서 <code>MyRunnable</code> 클래스는 <code>Runnable</code> 인터페이스를 구현합니다. <code>Runnable</code> 인터페이스는 <code>run</code> 메서드를 선언하고 있으며, <code>MyRunnable</code> 클래스에서는 <code>run</code> 메서드를 구현합니다. <code>thread.start()</code> 메서드를 호출하면, <code>MyRunnable</code> 클래스의 <code>run</code> 메서드가 실행됩니다.</p>
<h2 id="추상화와-인터페이스의-차이점">추상화와 인터페이스의 차이점</h2>
<ul>
<li>개념 클래스 중에 실행 코드가 한 줄이라도 있으면 추상화, 코드없이 메서드 이름만 나열되어 있으면 인터페이스 입니다.</li>
</ul>
<h2 id="접근제한자">접근제한자</h2>
<p>코틀린에서 정의되는 클래스, 인터페이스, 메서트, 프로퍼티는 모두 접근 제한자를 가질 수 있습니다. </p>
<p>함수형 언어라는 특성으로 기존 객체지향에서 접근 제한자의 기준으로 삼았던 패키지 대신에 모듈 개념이 도입되었습니다. internal 접근 제한자로 모듈 간에 접근을 제한할 수 있습니다.</p>
<ul>
<li>접근 제한자의 종류</li>
</ul>
<table>
<thead>
<tr>
<th>접근 제한자</th>
<th>대상</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>public</td>
<td>클래스, 인터페이스, 메서드, 프로퍼티</td>
<td>어디서든지 접근 가능(기본적용)</td>
</tr>
<tr>
<td>internal</td>
<td>모듈 내부</td>
<td>같은 모듈 내에서만 접근 가능</td>
</tr>
<tr>
<td>protected</td>
<td>클래스 내부, 하위 클래스</td>
<td>클래스 내부와 하위 클래스에서만 접근 가능</td>
</tr>
<tr>
<td>private</td>
<td>클래스 내부</td>
<td>같은 클래스 내부에서만 접근 가능</td>
</tr>
<tr>
<td>- public: 어디서든지 접근 가능합니다. 아무런 접근 제한자가 지정되지 않으면 기본값으로 public이 지정됩니다.</td>
<td></td>
<td></td>
</tr>
</tbody></table>
<pre><code>class Example {
    public var name: String = &quot;John&quot;
}
</code></pre><ul>
<li>internal: 같은 모듈 내에서만 접근 가능합니다.</li>
</ul>
<pre><code>internal class Example {
    internal fun printHello() {
        println(&quot;Hello&quot;)
    }
}
</code></pre><ul>
<li>protected: 클래스 내부와 하위 클래스에서만 접근 가능합니다.</li>
</ul>
<pre><code>open class Example {
    protected var name: String = &quot;John&quot;
}

class SubExample : Example() {
    fun printName() {
        println(name)
    }
}
</code></pre><ul>
<li>private: 같은 클래스 내부에서만 접근 가능합니다.</li>
</ul>
<pre><code>class Example {
    private var name: String = &quot;John&quot;
    fun printName() {
        println(name)
    }
}
</code></pre><h2 id="제네릭">제네릭</h2>
<p>제네릭은 입력되는 값의 타입을 자유롭게 사용하기 위한 설계도구입니다.</p>
<p>제네릭(Generic)은 입력되는 값의 타입을 자유롭게 사용하기 위한 설계도구입니다. 제네릭을 사용하면 클래스나 함수의 타입을 일반화할 수 있습니다. 이를 통해 클래스나 함수를 만들 때 타입에 대한 제약이 없어지므로, 코드의 재사용성이 높아집니다.</p>
<p>제네릭을 사용하는 방법은 다음과 같습니다.</p>
<pre><code>class ClassName&lt;T&gt; {
    var variable: T
}
</code></pre><p>위의 예시에서 <code>T</code>는 제네릭 타입 매개변수입니다. <code>T</code>는 어떤 타입이든 될 수 있습니다. <code>ClassName</code> 클래스를 사용할 때, <code>T</code> 대신 구체적인 타입을 지정해줘야 합니다.</p>
<pre><code>val obj = ClassName&lt;String&gt;()
obj.variable = &quot;Hello, World!&quot;
</code></pre><p>위의 예시에서 <code>obj</code> 변수는 <code>ClassName</code> 클래스의 인스턴스입니다. <code>ClassName</code> 클래스는 제네릭 클래스이므로, <code>obj</code> 변수 선언에서 제네릭 타입 매개변수 <code>T</code>를 <code>String</code>으로 지정해줍니다. 따라서 <code>obj</code> 변수의 <code>variable</code> 프로퍼티는 <code>String</code> 타입이 됩니다.</p>
<p>제네릭을 사용하는 가장 일반적인 예시 중 하나는 컬렉션입니다. 다음은 <code>List</code> 인터페이스를 구현하는 <code>ArrayList</code> 클래스에서 제네릭을 사용한 예시입니다.</p>
<pre><code>val list: ArrayList&lt;String&gt; = ArrayList()
list.add(&quot;Hello&quot;)
list.add(&quot;Kotlin&quot;)
println(list)
</code></pre><p>위의 예시에서 <code>list</code> 변수는 <code>ArrayList</code> 클래스의 인스턴스입니다. <code>ArrayList</code> 클래스는 <code>List</code> 인터페이스를 구현하고 있으며, 제네릭 타입 매개변수로 <code>String</code>을 사용하고 있습니다. 따라서 <code>list</code> 변수는 <code>String</code> 타입을 요소로 갖는 리스트입니다. <code>list.add()</code> 메서드를 사용하여 요소를 추가할 수 있으며, <code>println(list)</code>를 호출하여 리스트의 내용을 출력할 수 있습니다.</p>
<p>제네릭을 사용하면 타입에 대한 제약이 없어지므로 코드의 재사용성이 높아집니다. 또한, 컴파일 시점에 타입 검사가 이루어지므로, 런타임에 발생할 수 있는 오류를 방지할 수 있습니다.</p>
<ol>
<li><p>함수에서 제네릭 사용하기</p>
<pre><code> fun &lt;T&gt; List&lt;T&gt;.slice(indices: IntRange): List&lt;T&gt; {
     // ...
 }
</code></pre><p> 이 경우, 함수 이름 앞에 <code>&lt;T&gt;</code>를 작성하면 제네릭 함수를 선언할 수 있습니다. 여기서 <code>T</code>는 함수가 인수로 받는 타입을 나타냅니다.</p>
</li>
<li><p>클래스에서 제네릭 사용하기</p>
<pre><code> class Box&lt;T&gt;(t: T) {
     var value = t
 }
</code></pre><p> 이 경우, 클래스 이름 뒤에 <code>&lt;T&gt;</code>를 작성하면 제네릭 클래스를 선언할 수 있습니다. 여기서 <code>T</code>는 클래스가 인스턴스화될 때 사용되는 타입을 나타냅니다.</p>
</li>
<li><p>인터페이스에서 제네릭 사용하기</p>
<pre><code> interface List&lt;T&gt; {
     // ...
 }
</code></pre><p> 이 경우, 인터페이스 이름 뒤에 <code>&lt;T&gt;</code>를 작성하면 제네릭 인터페이스를 선언할 수 있습니다. 여기서 <code>T</code>는 인터페이스가 구현될 때 사용되는 타입을 나타냅니다.</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[오버라이드와 익스텐션]]></title>
            <link>https://velog.io/@wrapping_not/%EC%98%A4%EB%B2%84%EB%9D%BC%EC%9D%B4%EB%93%9C%EC%99%80-%EC%9D%B5%EC%8A%A4%ED%85%90%EC%85%98</link>
            <guid>https://velog.io/@wrapping_not/%EC%98%A4%EB%B2%84%EB%9D%BC%EC%9D%B4%EB%93%9C%EC%99%80-%EC%9D%B5%EC%8A%A4%ED%85%90%EC%85%98</guid>
            <pubDate>Mon, 20 Mar 2023 06:08:32 GMT</pubDate>
            <description><![CDATA[<h1 id="오버라이드">오버라이드</h1>
<p>코틀린에서 클래스 상속은 자바와 비슷한 방식으로 동작합니다. 자식 클래스는 부모 클래스의 메소드를 오버라이드할 수 있습니다. 이는 부모 클래스에 정의된 메소드를 자식 클래스에서 새로운 구현으로 대체하는 것을 의미합니다.</p>
<p><img src="https://velog.velcdn.com/images/wrapping_not/post/b7081c52-c4f7-42ba-a031-ef5ef301867e/image.png" alt=""></p>
<p>코틀린에서는 override 키워드를 사용하여 메소드를 오버라이드할 수 있습니다. 오버라이드된 메소드는 부모 클래스의 메소드와 이름, 매개변수, 반환 유형이 동일해야 합니다. 그러나 자식 클래스에서는 메소드 구현을 변경할 수 있습니다.</p>
<p>다음은 <code>Animal</code> 클래스를 상속받아 <code>Cat</code> 클래스에서 <code>makeSound()</code> 메소드를 오버라이드하는 예시 코드입니다.</p>
<pre><code>open class Animal {
    open fun makeSound() {
        println(&quot;The animal makes a sound&quot;)
    }
}

class Cat : Animal() {
    override fun makeSound() {
        println(&quot;Meow&quot;)
    }
}
</code></pre><p>이 예시에서 <code>Animal</code> 클래스의 <code>makeSound()</code> 메소드는 <code>open</code> 키워드로 선언되었기 때문에, <code>Cat</code> 클래스에서 이를 오버라이드할 수 있습니다. <code>Cat</code> 클래스에서 오버라이드된 <code>makeSound()</code> 메소드는 &quot;Meow&quot;를 출력합니다.</p>
<h2 id="오버라이드-주의-할-점">오버라이드 주의 할 점</h2>
<ul>
<li>부모 클래스의 메소드를 오버라이드할 때는 이름, 매개변수, 반환 유형이 모두 일치해야 합니다.</li>
<li>자식 클래스에서 오버라이드된 메소드는 부모 클래스의 메소드를 대체합니다.</li>
<li>하지만, 자식 클래스에서는 오버라이드된 메소드를 확장할 수 있습니다. 이때 <code>super</code> 키워드를 사용하여 부모 클래스의 메소드를 호출할 수 있습니다.</li>
<li>자식 클래스에서 <code>open</code> 키워드를 사용하여 오버라이드할 수 있는 메소드를 선언해야 합니다. 만약 부모 클래스에서 메소드가 <code>final</code>로 선언되어 있다면, 오버라이드할 수 없습니다.</li>
</ul>
<h1 id="익스텐션">익스텐션</h1>
<p>코틀린에서는 또한 익스텐션(Extension)이라는 기능이 있습니다. 익스텐션은 이미 존재하는 클래스에 새로운 기능을 추가합니다. 이를 통해 기존 클래스의 코드를 수정하지 않고도 새로운 기능을 추가할 수 있습니다.</p>
<p>익스텐션을 사용하려면 클래스 이름 뒤에 점(.)을 붙이고, 새로운 메소드 이름을 정의합니다. 이를 활용하여 기존 클래스에 새로운 메소드를 추가할 수 있습니다. 새로운 메소드는 클래스 내부의 다른 메소드와 같은 방식으로 작동합니다.</p>
<p>코틀린의 오버라이드와 익스텐션은 각각 클래스 상속과 클래스 확장을 위한 강력한 기능입니다. 코드의 재사용성을 높이고, 새로운 기능을 추가하거나 기존 기능을 수정할 수 있는 유연성을 제공합니다.</p>
<p>다음은 <code>String</code> 클래스에 <code>addExclamation()</code> 메소드를 추가하는 익스텐션 예시 코드입니다.</p>
<pre><code>fun String.addExclamation(): String {
    return &quot;$this!&quot;
}
</code></pre><p>이 예시에서 <code>String</code> 클래스에 <code>addExclamation()</code> 메소드를 추가하고 있습니다. <code>addExclamation()</code> 메소드는 문자열 뒤에 느낌표를 추가하여 반환합니다. 이제 <code>String</code> 클래스의 인스턴스에서 <code>addExclamation()</code> 메소드를 호출할 수 있습니다.</p>
<pre><code>val greeting = &quot;Hello&quot;
println(greeting.addExclamation()) // 출력: &quot;Hello!&quot;
</code></pre><p>위 예시에서 <code>addExclamation()</code> 메소드를 사용하여 &quot;Hello!&quot;를 출력합니다.</p>
<h2 id="익스텐션-주의-할-점">익스텐션 주의 할 점</h2>
<ul>
<li>익스텐션은 클래스의 기능을 수정하는 것이 아니라 기존 클래스에 새로운 함수를 추가하는 것입니다.</li>
<li>익스텐션에서는 클래스의 프로퍼티에 접근할 수 없습니다.</li>
<li>익스텐션 함수를 호출할 때, 클래스 내부의 멤버 함수와 같은 이름의 함수가 있다면, 멤버 함수가 호출됩니다.</li>
<li>익스텐션 함수는 클래스 내부의 private 멤버에 접근할 수 없습니다.</li>
<li>뷰- 액티비티를 연결해 뷰를 바로 쓸수 있다는 장점이 있지만 안드로이드 스튜디오 4.1 버전 이후 부터는 추천을 안하고 있습니다. 뷰를 바로 사용하고 싶다면, DataBinding을 이용하는것이 좋습니다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[오브젝트]]></title>
            <link>https://velog.io/@wrapping_not/%EC%98%A4%EB%B8%8C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@wrapping_not/%EC%98%A4%EB%B8%8C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Mon, 20 Mar 2023 05:59:39 GMT</pubDate>
            <description><![CDATA[<h2 id="오브젝트란">오브젝트란?</h2>
<p>오브젝트는 클래스의 인스턴스를 만들어 내지 않고, 고유한 인스턴스를 바로 생성하는 것이 가능한 싱글톤 패턴의 구현 방법 중 하나입니다. 코틀린에서는 <code>object</code> 키워드를 사용하여 오브젝트를 생성할 수 있습니다. 이를 사용하면 인스턴스를 생성하기 위한 보일러플레이트 코드를 줄일 수 있으며, 코드의 가독성과 유지보수성을 향상시킬 수 있습니다.</p>
<ul>
<li>자바에서는 static과 같은 역활</li>
<li>예시 코드</li>
</ul>
<pre><code class="language-kotlin">object Pig{
    var name: String = &quot;Pinky&quot;
        fun printName(){
            Log.d(&quot;class&quot;, &quot;Pig의 이름은 ${name}입니다.&quot;)
        }
}</code></pre>
<ul>
<li>오브젝트 코드 블록 안의 프로퍼티와 베서드는 클래스명에 도트 연산자를 붙여서 생성자 없이 직접 호출 가능합니다.</li>
<li>주의 할 점은 클래스명을 그대로 사용하기 때문에 호출하는 클래스명의 첫글자가 대문자 입니다.</li>
<li>object는 클래스와 다르게 앱 전체에 1개만 생성됩니다.</li>
</ul>
<h2 id="컴패니언-오브젝트">컴패니언 오브젝트</h2>
<p>컴패니언 오브젝트는 클래스 내부에 선언되는 오브젝트로, 클래스의 인스턴스와는 별개로 생성되며 해당 클래스와 관련된 유틸리티 메서드나 프로퍼티를 담을 수 있습니다. 컴패니언 오브젝트를 선언하면 해당 클래스의 이름으로 접근할 수 있는 &quot;정적&quot; 멤버 변수나 메서드를 선언할 수 있습니다. 코틀린에서는 <code>companion object</code> 키워드를 사용하여 컴패니언 오브젝트를 생성할 수 있습니다.</p>
<ul>
<li>컴패니언 오브젝트의 멤버 변수와 메서드는 클래스명을 사용하여 직접 호출할 수 있습니다.</li>
<li>컴패니언 오브젝트 내부에서 선언된 멤버 변수와 메서드는 private으로 선언되어 있는 멤버 변수와 메서드를 사용할 수 있습니다.</li>
<li>컴패니언 오브젝트는 클래스와 마찬가지로 생성자를 가질 수 있습니다.</li>
<li>클래스 내부에는 하나의 컴패니언 오브젝트만 선언할 수 있습니다.</li>
<li>예시 코드</li>
</ul>
<pre><code class="language-kotlin">class MyClass {
    companion object {
        *val myProperty = &quot;Hello, World!&quot;
        fun myMethod() {
            println(&quot;This is a companion object method.&quot;)
        }*
    }
}

MyClass.*myProperty = &quot;Hi&quot;*
MyClass.*myMethod() -&gt; &quot;This is a companion object method.&quot;*</code></pre>
<p>위 코드에서 <code>MyClass.myProperty</code>와 <code>MyClass.myMethod()</code>를 이용하여 컴패니언 오브젝트의 멤버에 접근할 수 있습니다.</p>
]]></description>
        </item>
    </channel>
</rss>