<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jzzn_a.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Mon, 02 Sep 2024 09:49:19 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jzzn_a.log</title>
            <url>https://velog.velcdn.com/images/jxxn_a/profile/d9352626-2fa8-4252-be9c-b512bdabfba2/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jzzn_a.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jxxn_a" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Compose와 XML의 차이점]]></title>
            <link>https://velog.io/@jxxn_a/Compose</link>
            <guid>https://velog.io/@jxxn_a/Compose</guid>
            <pubDate>Mon, 02 Sep 2024 09:49:19 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/jxxn_a/post/d7fb7e31-e114-402d-bc28-b255636a4671/image.png" alt=""></p>
<h3 id="compose와-xml의-차이점-3가지">Compose와 Xml의 차이점 3가지</h3>
<blockquote>
<p> ** 1. 문법과 접근방식**</p>
</blockquote>
<ol>
<li>XML</li>
</ol>
<ul>
<li>태그와 속성으로 UI 구조를 정의한다.</li>
<li>정적인 구조를 선언하며, 시각적인 디자인과 논리적인 동작은 별도의 파일에 작성한다.</li>
</ul>
<ol start="2">
<li>Compose</li>
</ol>
<ul>
<li>함수 호출을 통해 UI를 선언적으로 작성한다.</li>
<li>UI와 상태를 함께 정의하며, 코드로 UI 구조와 동작을 표현할 수 있다.</li>
</ul>
<hr>
<blockquote>
<p><strong>2. 가독성과 유지보수</strong></p>
</blockquote>
<ol>
<li>XML</li>
</ol>
<ul>
<li>복잡한 UI를 나타내기 위해서는 많은 태그와 속성이 필요할 수 있다.</li>
<li>중첩된 구조로 인해 가독성이 저하되고, 디자인과 논리가 분리되어 유지보수가 어려울 수 있다.</li>
</ul>
<ol start="2">
<li>Compose</li>
</ol>
<ul>
<li>간결한 코드로 UI를 표현하기 때문에 가독성이 높다.</li>
<li>UI요소와 상태를 같은 파일에서 관리하기 때문에 유지보수가 간편하다.</li>
</ul>
<hr>
<blockquote>
<p><strong>3. 애니메이션과 상호작용</strong></p>
</blockquote>
<ol>
<li>XML</li>
</ol>
<ul>
<li>애니메이션과 상호작용을 하기 위해선 별도의 XML 파일이 필요하다.</li>
</ul>
<ol start="2">
<li>Compose</li>
</ol>
<ul>
<li>Compose 자체에 내장된 애니메이션 및 인터렉션 기능을 제공하며, UI와 상호작용을 더욱 쉽게 구현할 수 있다.</li>
</ul>
<hr>
<blockquote>
<p><strong>Compose에서 달라진 점!</strong></p>
</blockquote>
<ul>
<li>XML에서는 리사이클러뷰를 위해 xml과 Adapter, View Holder 파일을 만들어주어야했는데 Compose에서는 LazyColumn을 통해 간단하게 리스트를 만들 수 있다.</li>
</ul>
<hr>
<p><strong>참고한 블로그</strong>
<a href="https://medium.com/playkeyboard/%EC%9A%B0%EB%A6%AC%EA%B0%80-android-compose%EB%A5%BC-%ED%83%9D%ED%95%9C-%EC%9D%B4%EC%9C%A0-%ED%94%8C%EB%A0%88%EC%9D%B4%ED%82%A4%EB%B3%B4%EB%93%9C-%EC%9D%B4%EC%95%BC%EA%B8%B0-7c4dbb9f6f1d">https://medium.com/playkeyboard/%EC%9A%B0%EB%A6%AC%EA%B0%80-android-compose%EB%A5%BC-%ED%83%9D%ED%95%9C-%EC%9D%B4%EC%9C%A0-%ED%94%8C%EB%A0%88%EC%9D%B4%ED%82%A4%EB%B3%B4%EB%93%9C-%EC%9D%B4%EC%95%BC%EA%B8%B0-7c4dbb9f6f1d</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[OOP] SOLID 원칙 - ISP(인터페이스분리원칙)]]></title>
            <link>https://velog.io/@jxxn_a/OOP-SOLID-%EC%9B%90%EC%B9%99-ISP%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EB%B6%84%EB%A6%AC%EC%9B%90%EC%B9%99</link>
            <guid>https://velog.io/@jxxn_a/OOP-SOLID-%EC%9B%90%EC%B9%99-ISP%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EB%B6%84%EB%A6%AC%EC%9B%90%EC%B9%99</guid>
            <pubDate>Wed, 21 Aug 2024 10:43:43 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/jxxn_a/post/cc07b181-6452-4d80-a3b2-3ba0e49b3560/image.png" alt=""></p>
<h2 id="isp-interface-segregation-priciple---인터페이스분리원칙">ISP (Interface Segregation Priciple) - 인터페이스분리원칙</h2>
<ul>
<li>클라이언트는 사용하지 않는 인터페이스에 의존을 강요당해서는 안된다.</li>
<li>클라이언트를 기준으로 인터페이스를 분리하라는 뜻이다.</li>
<li>클라이언트 : 인터페이스를 사용하는 프로그래밍 요소인데, 보통 인터페이스를 구현하는 클래스를 의미한다.</li>
<li>객체지향 프로그래밍 특징 중 <strong>&#39;캡슐화&#39;</strong>에 해당되는 것 같다. (+ 모듈화)</li>
</ul>
<hr>
<h2 id="💫-isp-위반-예시">💫 ISP 위반 예시</h2>
<pre><code class="language-kotlin">interface Vehicle {
    fun start()
    fun stop()
    fun accelerate()
    fun brake()
    fun openDoor()
    fun closeDoor()
    fun turnOnHeadlights()
    fun turnOffHeadlights()
}</code></pre>
<ul>
<li>인터페이스에 너무 많은 메서드가 포함되어있어 <strong>유지 및 보수가 어렵다.</strong></li>
<li>인터페이스는 클라이언트가 <strong>사용하지 않는 메서드에 의존하지 않도록</strong> 분리되어야한다.<h2 id="💫-isp-예시">💫 ISP 예시</h2>
<pre><code class="language-kotlin">interface Drivable {
  fun start()
  fun stop()
  fun accelerate()
  fun brake()
}
</code></pre>
</li>
</ul>
<p>interface Openable {
    fun openDoor()
    fun closeDoor()
    // 문 열고 닫기
}</p>
<p>interface Lightable {
    fun turnOnHeadlights()
    fun turnOffHeadlights()
    // 라이트 켜고 끄기
}</p>
<p>class Car : Drivable, Openable, Lightable {
    override fun start() {
    }</p>
<pre><code>override fun stop() {
}

override fun accelerate() {
}

override fun brake() {
}

override fun openDoor() {
}

override fun closeDoor() {
}

override fun turnOnHeadlights() {
}

override fun turnOffHeadlights() {
}</code></pre><p>}</p>
<p>fun main() {
    val car = Car()
    car.start()
    car.accelerate()
    car.openDoor()
    car.turnOnHeadlights()
    }</p>
<p>```</p>
<h2 id="💫-isp를-지키기-위해-지양해야할-점">💫 ISP를 지키기 위해 지양해야할 점</h2>
<p>🪐안정된 소프트웨어 아키텍처를 위해서는 변동성이 큰 구현체에 의존하는 일을 지양하고, 안정된 추상 인터페이스를 사용하는 것이 좋다. 구현체에 의존하는 인터페이스는 ISP 원칙을 위반할 수 있기 때문이다.
🪐 ISP 원칙은 인터페이스에 대한 단일 책임을 강조하는 설계원칙이므로 인터페이스에 대한 단일 책임을 지향하지 않는다면 ISP 원칙을 위반하게 된다.
🪐 너무 큰 인터페이스를 만들게 되면 클라이언트가 사용하지 않는 메서드에 의존하게 되어 ISP 원칙을 위반하게 된다.</p>
<hr>
<p>참고한 블로그</p>
<ul>
<li><a href="https://cbs5295.medium.com/oop-solid-%EC%9B%90%EC%B9%994-isp-interface-segregation-principle-553152b9145b">https://cbs5295.medium.com/oop-solid-%EC%9B%90%EC%B9%994-isp-interface-segregation-principle-553152b9145b</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[정보처리기사 필기 서버인증]]></title>
            <link>https://velog.io/@jxxn_a/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%84%9C%EB%B2%84%EC%9D%B8%EC%A6%9D</link>
            <guid>https://velog.io/@jxxn_a/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%84%9C%EB%B2%84%EC%9D%B8%EC%A6%9D</guid>
            <pubDate>Sun, 07 Jul 2024 14:47:57 GMT</pubDate>
            <description><![CDATA[<h1 id="시스템-구축관리">시스템 구축관리</h1>
<blockquote>
<h4 id="서버-인증---보안-서버">서버 인증 - 보안 서버</h4>
</blockquote>
<p><strong>인증 (Authentication)</strong></p>
<ul>
<li>다중 사용자 컴퓨터 시스템이나 네트워크 시스템에서 로그인을 요청한 사용자의 정보를 확인하고 접근 권한을 인증하는 보안 절차</li>
</ul>
<blockquote>
<p><strong>인증 유형</strong></p>
</blockquote>
<p><strong>(1) 지식기반인증(Something You Know)</strong>
: 사용자가 기억하고 있는 정보를 기반으로 인증을 수행하는 것
<strong>(1-1) 지식기반인증 예시</strong>
: 고정된 패스워드, 패스워드 프레이즈, 아이핀</p>
<hr>
<p><strong>(2) 소유기반인증(Something You Have)</strong>
: 사용자가 소유하고 있는 것을 기반으로 인증하고 수행하는 것
<strong>(2-1) 소유기반인증 예시</strong>
: 신분증, 메모리 카드, 토큰, 스마트 카드, OTP</p>
<hr>
<p><strong>(3) 생체기반인증(Something You Are)</strong>
: 사용자의 고유한 생체 정보를 기반으로 인증을 수행하는 것
<strong>(3-1) 생체기반인증 예시</strong>
: 지문, 홍채/망막, 얼굴, 음성, 정맥 등</p>
<hr>
<p><strong>(4) 특징기반인증</strong>
: 행위기반인증(Something You Do)사용자의 행동 정보를 이용해 인증 수행
<strong>(4-1) 특징기반인증 예시</strong>
: 서명, 동작</p>
<hr>
<p><strong>(5) 위치기반인증(Somewhere You Are)</strong>
: 인증을 시도한느 위치의 적절성 확인
<strong>(5-1) 위치기반인증 예시</strong>
: 콜백, GPS 또는 IP 주소를 이용한 위치 기반인증</p>
<hr>
<p>*<em>참고한 블로그 :
*</em><a href="https://potato-potahto.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC5%EC%A0%95%EB%B3%B4%EC%8B%9C%EC%8A%A4%ED%85%9C-%EA%B5%AC%EC%B6%95-%EA%B4%80%EB%A6%AC%EC%8B%9C%EC%8A%A4%ED%85%9C-%EB%B3%B4%EC%95%88-%EA%B5%AC%EC%B6%95%EC%84%9C%EB%B2%84-%EC%9D%B8%EC%A6%9D">https://potato-potahto.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC5%EC%A0%95%EB%B3%B4%EC%8B%9C%EC%8A%A4%ED%85%9C-%EA%B5%AC%EC%B6%95-%EA%B4%80%EB%A6%AC%EC%8B%9C%EC%8A%A4%ED%85%9C-%EB%B3%B4%EC%95%88-%EA%B5%AC%EC%B6%95%EC%84%9C%EB%B2%84-%EC%9D%B8%EC%A6%9D</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[OOP] SOLID 원칙 - LSP(리스코프치환원칙)]]></title>
            <link>https://velog.io/@jxxn_a/OOP-SOLID-%EC%9B%90%EC%B9%99-LSP%EB%A6%AC%EC%8A%A4%EC%BD%94%ED%94%84%EC%B9%98%ED%99%98%EC%9B%90%EC%B9%99</link>
            <guid>https://velog.io/@jxxn_a/OOP-SOLID-%EC%9B%90%EC%B9%99-LSP%EB%A6%AC%EC%8A%A4%EC%BD%94%ED%94%84%EC%B9%98%ED%99%98%EC%9B%90%EC%B9%99</guid>
            <pubDate>Sat, 25 Nov 2023 12:05:58 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/jxxn_a/post/492e503f-e598-46ce-a7e2-d4d54f4a6e0b/image.png" alt=""></p>
<h2 id="lsp-liscov-substitution-principle---리스코프치환원칙">LSP (Liscov Substitution Principle) - 리스코프치환원칙</h2>
<ul>
<li>상위클래스의 객체가 사용하는 메서드는 하위클래스의 객체가 무엇인지 상관없이, 하위클래스의 객체도 사용할 수 있어야한다.
=&gt; 상위클래스의 객체를 하위클래스의 객체로 치환해도 상위클래스를 사용하는 프로그램은 정상적으로 동작해야한다는 점이다.</li>
<li>상위클래스의 특징은 그대로 갖고있으면서 + 되는 것이다.</li>
<li>객체지향 프로그래밍의 특징 중 <strong>&#39;상속&#39;,&#39;다형성&#39;</strong>에 해당되는 것 같다.</li>
</ul>
<hr>
<h2 id="💫-lsp-위반-예시">💫 LSP 위반 예시</h2>
<p><img src="https://velog.velcdn.com/images/jxxn_a/post/2dda95d1-325f-4065-beb7-eeaa07f726c3/image.png" alt=""></p>
<ul>
<li>수학적으로는 &#39;정사각형이면 직사각형이다&#39;라는 명제가 성립한다.</li>
</ul>
<hr>
<p><strong>[ 클래스 설계 ]</strong></p>
<pre><code class="language-kotlin">open class Rectangle {
     open var width : Int = 1
     open var height : Int = 1
}

class square : Rectangle () {
   override var width : Int = super.width
           get() = super.width
           set(value) {
             field = value
             height = value
            }


   override var height : Int = super.height
           get() = super.height
           set(value) {
              field = value
              width = value
           }
}</code></pre>
<ul>
<li><p>하지만, 직사각형 클래스에 폭보다 높이를 더 길게 만들어주는 기능이 필요하다면?</p>
<pre><code class="language-kotlin">fun increaseHeight(rec : Retangle) {
 if(rec.height &lt;= rec.width) {
   rec.height = rec.width + 10
 }
}</code></pre>
</li>
<li><p>위 함수를 Rectangle의 하위클래스인 square 클래스 객체가 사용한다면 높이가 더 길어지지 않는다. 이는 IncreaseHeight()함수가 Rectangle의 확장에 열려있지 않다는 뜻이다.
=&gt; &#39;정사각형은 직사각형이다.&#39;라는 명제가 성립하지만, 프로그램을 짤 때 &#39;square 객체는 Rectangle 객체이다.&#39;로 설계하는 것은 문제가 있다.</p>
</li>
<li><p>다형성에서 하위클래스는 인터페이스 규약을 다 지켜야한다.
(예시) 자동차 인터페이스의 엑셀은 앞으로 가라는 기능이 있는데 갑자기 뒤로가게 한다면 LSP 위반이다. 느리더라도 앞으로 가야 LSP에 위반되지 않는다.</p>
</li>
</ul>
<hr>
<h2 id="💫-lsp를-지키기-위해-지양해야할-점">💫 LSP를 지키기 위해 지양해야할 점</h2>
<ul>
<li>상위클래스의 명세를 벗어나는 것(Down Casting)
=&gt; 코드적으로는 문제없지만, 추상화한 타입을 그 하위 타입의 객체로 변환했을 때 예상한대로 동작하지 않는다는 것을 방지하는 것이 LSP 원칙을 지키는 이유이다.</li>
</ul>
<p>🪐 하위 타입을 정의할 때는 상위 타입의 명세를 지켜야 LSP를 지킬 수 있다. 따라서 상위 타입에 명세를 명확하게 잘 기록해야한다.</p>
<p>🪐 DownCasting을 사용하면 OCP를 위반하기도 하지만, LSP를 위반하기도 한다.상위 타입 객체를 하위 타입의 객체로 바꿨을 때 모든 하위 타입에 대해 잘 동작하지 않을 가능성이 크기 때문이다. 상위 타입의 객체가 하위타입인지 확인하는 코드를 사용하는 것은 상위 클래스가 제대로 추상화 되지 않았다는 것을 의미한다.</p>
<hr>
<p>참고한 블로그</p>
<ul>
<li><a href="https://cbs5295.medium.com/oop-solid-%EC%9B%90%EC%B9%993-lsp-liscov-substitution-principle-f098b6932b4b">https://cbs5295.medium.com/oop-solid-%EC%9B%90%EC%B9%993-lsp-liscov-substitution-principle-f098b6932b4b</a></li>
<li><a href="https://hckcksrl.medium.com/solid-%EC%9B%90%EC%B9%99-182f04d0d2b">https://hckcksrl.medium.com/solid-%EC%9B%90%EC%B9%99-182f04d0d2b</a></li>
<li><a href="https://velog.io/@yoho98/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EA%B0%9C%EB%B0%9C-5%EC%9B%90%EC%B9%99SOLID#ocpopen-closed-principle--%EA%B0%9C%EB%B0%A9-%ED%8F%90%EC%87%84-%EC%9B%90%EC%B9%99">https://velog.io/@yoho98/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EA%B0%9C%EB%B0%9C-5%EC%9B%90%EC%B9%99SOLID#ocpopen-closed-principle--%EA%B0%9C%EB%B0%A9-%ED%8F%90%EC%87%84-%EC%9B%90%EC%B9%99</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[OOP] SOLID 원칙 - OCP (개방폐쇄의원칙)]]></title>
            <link>https://velog.io/@jxxn_a/OOP-SOLID-%EC%9B%90%EC%B9%99-OCP-%EA%B0%9C%EB%B0%A9%ED%8F%90%EC%87%84%EC%9D%98%EC%9B%90%EC%B9%99</link>
            <guid>https://velog.io/@jxxn_a/OOP-SOLID-%EC%9B%90%EC%B9%99-OCP-%EA%B0%9C%EB%B0%A9%ED%8F%90%EC%87%84%EC%9D%98%EC%9B%90%EC%B9%99</guid>
            <pubDate>Thu, 23 Nov 2023 15:14:40 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/jxxn_a/post/e08e0217-647c-41a0-93fb-1cae7897dc1b/image.png" alt=""></p>
<h2 id="ocp-open-closed-principle---개방폐쇄의원칙">OCP (Open Closed Principle) - 개방폐쇄의원칙</h2>
<ul>
<li>개방폐쇄의 원칙을 의미하며, 소프트웨어의 요소들은 확장에는 열려있어야하고, 변경에는 닫혀있어야한다.</li>
<li>기능이 확장 될 때 기존에 작성된 코드는 변경되지 않아야한다.</li>
<li>객체지향 프로그래밍의 특징 중 <strong>&#39;추상화&#39;, &#39;상속&#39;, &#39;다형성&#39;</strong>에 해당되는 것 같다.</li>
</ul>
<p><strong>- (예시)</strong> 캐릭터 하나를 생성한다고 할 때, 각 캐릭터들의 움직임이 다를 경우 움직임의 패턴 구현을 하위 클래스에 맡기면 캐릭터의 수정은 필요가 없고(close), 움직임의 패턴만 재정의하면 된다.(open)</p>
<hr>
<h3 id="💫-ocp-구조">💫 OCP 구조</h3>
<p><img src="https://velog.velcdn.com/images/jxxn_a/post/92d8f1ff-8730-4ca8-83da-8c85453d1a44/image.png" alt=""></p>
<ul>
<li>FileByteSource는 파일에서 Byte를 읽어오는 역할을 하는 클래스</li>
<li>SocketByteSource는 소켓에서 Byte를 읽어오는 역할을 하는 클래스
=&gt; ByteSource를 구현하는 FileByteSource와 SocketByteSource는 ByteSource를 상속받고, 다형성에 의해 ByteSource 객체의 참조값을 저장할 수 있는 변수에는 ByteSource의 하위타입까지 담을 수 있다.</li>
</ul>
<hr>
<h3 id="💫-ocp-구조에서-기능-추가">💫 OCP 구조에서 기능 추가</h3>
<p><img src="https://velog.velcdn.com/images/jxxn_a/post/c8ae7c2a-7cbd-4de7-a3cf-170c80cc3a32/image.png" alt=""></p>
<ul>
<li>MemoryByteSource 클래스 내에서는 ByteSource의 메서드를 반드시 재정의해야하고,  FileByteSource 혹은 SocketByteSource 와는 다르게 메모리에서 ByteSource를 읽어오도록 만들 수 있다.</li>
<li>또한, ByteSource를 사용하는 곳에서는 ByteSource로 추상화되어 있기 때문에 이를 하위 타입으로 강제 캐스팅하지 않았던 이상 기존 코드는 변경하지 않아도 동작시킬 수 있다.</li>
</ul>
<hr>
<h3 id="💗-ocp를-지키는-핵심-개념">💗 OCP를 지키는 핵심 개념</h3>
<p><strong>1) 상속과 다형성이 확장에 열려있도록 한다.</strong></p>
<ul>
<li>FileByteSource, SocketByteSource은 ByteSource라는 하나의 인터페이스를 구현하게하며, 확장에 열려있게 한다.</li>
<li>또한, ByteSource 인터페이스를 구현하는 클래스가 ByteSource 타입으로 사용될 수 있게하는 Polymorphic Subtypes와 Method Overriding이라는 다형성이 확장에 열려있도록 만든다. (런타임에 해당 하위 클래스 타입으로 바인딩되기 때문에 가능하다.)</li>
</ul>
<p><strong>2) 추상화는 변경에 닫혀있도록 한다.</strong></p>
<ul>
<li>FlowController 클래스 입장에서는 Collect라는 함수를 사용할 때 받는 인자가 FileByteSource인지 SocketByteSource인지 알 필요없이 추상화 된 Byte Source라는 인자만을 사용하여 변경에는 닫혀있도록 한다.</li>
</ul>
<hr>
<h3 id="🚨-ocp를-지키기-위해-지양해야-할-점---down-casting">🚨 OCP를 지키기 위해 지양해야 할 점 - Down Casting</h3>
<p><img src="https://velog.velcdn.com/images/jxxn_a/post/fcbe4882-c882-4168-ab19-ec94493be59f/image.png" alt=""></p>
<ul>
<li>FileByteSource, SocketByteSource, MemorySource 등이 ByteSource로 변환된다. (UpCasting)</li>
<li>이 과정은 크게 문제는 없지만, 설계한 추상화가 깨지면서 확장될 때 수정해야 할 가능성이 생기기 때문에 더이상 닫혀있지 않게 된다.</li>
<li>만약 꼭 필요한 경우 타입 캐스팅 이후에 실행하는 메서드가 변화대상이 아니도록 코드를 작성해야한다.</li>
</ul>
<hr>
<p><strong>참고한 블로그</strong></p>
<ul>
<li><a href="https://cbs5295.medium.com/oop-solid-%EC%9B%90%EC%B9%992-ocp-open-closed-principle-3e3f4fba6e3f">https://cbs5295.medium.com/oop-solid-%EC%9B%90%EC%B9%992-ocp-open-closed-principle-3e3f4fba6e3f</a></li>
<li><a href="https://hckcksrl.medium.com/solid-%EC%9B%90%EC%B9%99-182f04d0d2b">https://hckcksrl.medium.com/solid-%EC%9B%90%EC%B9%99-182f04d0d2b</a></li>
<li><a href="https://velog.io/@yoho98/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EA%B0%9C%EB%B0%9C-5%EC%9B%90%EC%B9%99SOLID">https://velog.io/@yoho98/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EA%B0%9C%EB%B0%9C-5%EC%9B%90%EC%B9%99SOLID</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[OOP] SOLID 원칙 - SRP (단일책임원칙)]]></title>
            <link>https://velog.io/@jxxn_a/OOP-SOLID-%EC%9B%90%EC%B9%99-SRP-%EB%8B%A8%EC%9D%BC%EC%B1%85%EC%9E%84%EC%9B%90%EC%B9%99</link>
            <guid>https://velog.io/@jxxn_a/OOP-SOLID-%EC%9B%90%EC%B9%99-SRP-%EB%8B%A8%EC%9D%BC%EC%B1%85%EC%9E%84%EC%9B%90%EC%B9%99</guid>
            <pubDate>Wed, 22 Nov 2023 15:33:01 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/jxxn_a/post/7575ed4c-958f-408d-a4c3-2b2855c99304/image.png" alt=""></p>
<h2 id="srp-single-responsibility-principle---단일책임원칙">SRP (Single Responsibility Principle) - 단일책임원칙</h2>
<ul>
<li>클래스는 <strong>하나의 책임만</strong>을 가져야한다는 원칙
예시) 데이터를 로드하는 클래스, 데이터를 보여주는 클래스, 데이터를 관리하는 클래스의 책임이 분리되어야 기능변경 시 코드 변경을 최소화 할 수 있다.</li>
<li>객체지향 프로그래밍의 특징 중 &#39;<strong>캡슐화</strong>&#39;에 해당되는 것 같다.</li>
</ul>
<hr>
<h3 id="💫-srp-구조">💫 SRP 구조</h3>
<h3 id="-💗-srp가-잘-적용된-구조">** 💗 SRP가 잘 적용된 구조**</h3>
<ul>
<li>DataDisplayer : 데이터를 보여주는 클래스</li>
<li>DataLoader : 데이터를 로드하는 클래스</li>
<li>Data : 데이터를 관리하는 클래스</li>
</ul>
<pre><code class="language-kotlin">Class DataDisplayer {
   fun display() {
   ...
   }
}

Class DataLoader {
   fun load() {
   ...
   }
}


Class Data {
   fun someProperty () {
   ...
   }
}</code></pre>
<hr>
<h3 id="-💗-srp가-위반된-구조">** 💗 SRP가 위반된 구조**</h3>
<ul>
<li>display() : 데이터를 로드하고 보여주는 함수</li>
<li>loadHtml() : HTML로 작성된 소스를 로드하는 함수</li>
<li>parseDataToGuiData() : HTML으로부터 로드된 데이터를 시각적인 데이터로 변환해주는 함수</li>
<li>updateGui() : 사용자에게 보여 줄 데이터를 GuiData 타입 객체를 사용하여 시각적으로 업데이트 하는 함수</li>
</ul>
<pre><code class="language-kotlin">class DataViewer {
  fun display() {
   ...
  fun loadHtml() {
   ...
  }
  fun updateGui(data:String) {
   ...
  }
  fun parseDataToGuiData(data:String) {
   ...
  }
}</code></pre>
<p>🚨 <strong>문제점</strong></p>
<ul>
<li>DataViewer Class는 Data를 보여주어야하는 클래스로 보이지만 실제로는 HTML 데이터 로드, 로드된 HTML 데이터를 GuiData로 변환, GuiData를 사용하여 화면에 보이는 데이터 변경을 하기 때문에 단일책임원칙을 위반한다.</li>
<li>오류 발생 시 DataType 같은 부분을 하나씩 전부 변경해주어야하고, 놓친 부분이 생긴다면 또 다시 오류와 마주하게 된다.</li>
</ul>
<hr>
<h3 id="-✨-클래스를-정의하기-위해서-">** ✨ 클래스를 정의하기 위해서 **</h3>
<ul>
<li>클래스를 정의하기 위해 단일 책임을 갖도록 설계하는 방법은 변경되지 않는 범위가 무엇인지 구분하고, 클래스의 이름만으로도 어떤 역할을 하는지 알 수 있도록 작성하는 것이 유지 및 보수를 하는데 중요하다.</li>
</ul>
<hr>
<p><strong>참고한 블로그</strong></p>
<ul>
<li><a href="https://cbs5295.medium.com/oop-solid-%EC%9B%90%EC%B9%991-srp-single-responsibility-principle-733f418ca5d">https://cbs5295.medium.com/oop-solid-%EC%9B%90%EC%B9%991-srp-single-responsibility-principle-733f418ca5d</a></li>
<li><a href="https://hckcksrl.medium.com/solid-%EC%9B%90%EC%B9%99-182f04d0d2b">https://hckcksrl.medium.com/solid-%EC%9B%90%EC%B9%99-182f04d0d2b</a></li>
<li><a href="https://velog.io/@yoho98/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EA%B0%9C%EB%B0%9C-5%EC%9B%90%EC%B9%99SOLID#ocpopen-closed-principle--%EA%B0%9C%EB%B0%A9-%ED%8F%90%EC%87%84-%EC%9B%90%EC%B9%99">https://velog.io/@yoho98/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EA%B0%9C%EB%B0%9C-5%EC%9B%90%EC%B9%99SOLID#ocpopen-closed-principle--%EA%B0%9C%EB%B0%A9-%ED%8F%90%EC%87%84-%EC%9B%90%EC%B9%99</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[WIL(14)]]></title>
            <link>https://velog.io/@jxxn_a/WIL14</link>
            <guid>https://velog.io/@jxxn_a/WIL14</guid>
            <pubDate>Fri, 17 Nov 2023 00:18:48 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="6주차-회고-노트">6주차 회고 노트</h3>
<p>2023.11.13 ~ 2023.11.17 Android App 최종 팀프로젝트 6주차</p>
</blockquote>
<blockquote>
<p>📌 <strong>트러블 슈팅</strong></p>
</blockquote>
<p>🐶 : <code>registerForActivityResult</code> 사용 시 프래그먼트의 생명주기를 고려하여 onDestroy에서 제거</p>
<p>🐰</p>
<ul>
<li>게시물을 최신순으로 정렬을 하려고 reverse를 사용하니 데이터의 구조가 꼬여서 제대로 불러오지 못해서 shuffle을 통해 게시물을 랜덤으로 보이게하는 것으로 변경</li>
<li>새로고침 및 다른 페이지에서 다시 홈피드로 돌아오면 스크롤이 상단에 위치한 게 아닌 상단, 중간, 하단 왔다갔다 하면서 위치했던 부분을 scrollToPosition(0)으로 해결했습니다.</li>
</ul>
<p>🐑 : 엑티비티 간 스택문제로 인한 오류 해결을 위해 clear top 대신 single top을 사용하여 해결</p>
<p>🐮 : 실시간으로 앱이 동기화가 되어 잦은 렉을 유발하여 refresh를 이용해 새로고침스크롤, 다른페이지끼리 이동할때에만 실시간정보가 입력되도록 해결</p>
<blockquote>
<p>📌 <strong>이번 주 한 일</strong></p>
</blockquote>
<p><strong>🍎 팀 전체</strong></p>
<ul>
<li>버그 수정</li>
<li>11/15 배포 반려 후 다시 신청</li>
<li>발표자료 준비</li>
<li>시연영상 촬영</li>
</ul>
<p><strong>🍎 팀원 개인</strong></p>
<p>🐶 : 버그 수정(마이 피드 좋아요 목록 없을 때 빈 화면 출력), 최종 발표 PPT 제작, 시연 영상 편집, 앱 배포 심사</p>
<p>🐰 : MypageFragment 프로필 사진 변경 시 즉시 적용, HomeFragment 게시물 랜덤, HomeFragment 새로고침 시 스크롤 맨 상단으로 고정, 댓글 삭제 기능 &amp; 프로필 사진 변경 Firebase 경로 변경</p>
<p>🐑 : 액티비티 간 스택 오류 해결, 진아님과 함께 프로필 즉각 반영 적용</p>
<p>🐮 : 스피너와 검색어의 정보가 다른 페이지를 다녀와도 유지되고 새로고침 할 때에만 초기화되게 설정, 초기 프로필 작성을 안하고 앱을 껐을 때 자동로그인이 되었던 문제 해결</p>
<blockquote>
<p>** 📌 프로젝트에 적용했던 핵심 기술 목록 및 의사결정 과정**</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jxxn_a/post/f118b430-ae4e-42ab-9fc7-354ad314bf2d/image.png" alt=""><img src="https://velog.velcdn.com/images/jxxn_a/post/1af2fdaf-e8e3-4239-b113-ffef77034922/image.png" alt=""></p>
<hr>
<pre><code>최종프로젝트 마무리 및 내일배움캠프 수료!

6주간 함께했던 24/7 팀원들 모두에게 정말 감사합니다.

많이 부족한 부리더였지만 끝까지 잘 이끌어주신 리더님과 끝까지 최고였던 팀원들 덕분에

어느 때보다도 더 몰입해서 프로젝트를 진행할 수 있었고, 무엇보다 즐겁게 코딩을 할 수

있었던 것 같습니다. :)

언제 어디서든 좋은 일만 항상 가득했으면 좋겠고, 함께 만든 앱인만큼 더 좋은 기능들을

추가해서 꾸준히 업데이트 해보자구요! 화이팅팅팅💗💗</code></pre><pre><code>또한 제가 내일배움캠프를 수료하기 전까지 만난 모든 분들께도 진심으로 감사드립니다.

정말 지쳐서 모든 걸 포기하고 싶을 때 붙잡아주시고, 옆에서 든든하게 이끌어주신 모든 분들

덕분에 한 걸음 더 성장하면서 최종프로젝트까지 잘 마무리 짓고 수료할 수 있었습니다.

항상 그때 받았던 위로와 진심어린 조언들을 잘 간직하면서 항상 끊임없이 성장하고

더 좋은 앱을 만들기 위해 노력하는 개발자가 되겠습니다! 감사합니다 💖

앞으로의 모든 일에 행운만 가득하시길🍀</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[최종 팀프로젝트 TIL(29)]]></title>
            <link>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL29</link>
            <guid>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL29</guid>
            <pubDate>Fri, 17 Nov 2023 00:15:29 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>🐱 With All My Animal 🐶</strong>
<strong>💡 [ 29일차 11/17일 ] 💡</strong></p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jxxn_a/post/97472209-cf9c-4b9b-b132-6c59d3f400cc/image.png" alt=""></p>
<blockquote>
<p>📌 <strong>오늘의 기술면접 질문 Q&amp;A</strong></p>
</blockquote>
<h3 id="1-상속이-무엇일까요"><strong>1) 상속이 무엇일까요?</strong></h3>
<ul>
<li><p>한 클래스의 특성을 다른 클래스가 물려받는 것을 의미한다.</p>
</li>
<li><p>상속을 통해 코드의 재사용성을 높이고, 코드의 구조를 개선할 수 있습니다.</p>
</li>
<li><p>open 키워드를 사용하여 클래스를 상속 가능한 상태로 만들 수 있다.</p>
</li>
</ul>
<pre><code class="language-kotlin">open class Animal {
    open fun eat() {
        println(&quot;Animal is eating&quot;)
    }
}

class Dog: Animal() {
    override fun eat() {
        println(&quot;Dog is eating&quot;)
    }
}

class Cat: Animal() {
    override fun eat() {
        println(&quot;Cat is eating&quot;)
    }
}
</code></pre>
<hr>
<h3 id="2-안드로이드에서-다국어-다양한-언어-지원은-어떻게-구현하나요"><strong>2) 안드로이드에서 다국어 (다양한 언어) 지원은 어떻게 구현하나요?</strong></h3>
<ul>
<li><p>resource를 사용하여 다국어를 지원한다.</p>
</li>
<li><p>resource는 앱에서 사용되는 정적인 콘텐츠를 의미하며, 텍스트/이미지/레이아웃 등이 포함된다.</p>
</li>
<li><p>res/strings.xml 파일에 작성해준다.</p>
<pre><code class="language-kotlin">&lt;resources&gt;
  &lt;string name=&quot;hello&quot;&gt;안녕&lt;/string&gt;
&lt;/resources&gt;</code></pre>
</li>
<li><p>res/string-en 파일을 생성한 뒤 작성해준다.</p>
<pre><code class="language-kotlin">&lt;resources&gt;
  &lt;string name=&quot;hello&quot;&gt;Hello&lt;/string&gt;
&lt;/resources&gt;</code></pre>
</li>
<li><p>그 다음 적용 할 부분에 다음과 같이 작성해준다.</p>
<pre><code class="language-kotlin">val greeting = getString(R.string.hello)</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종 팀프로젝트 TIL(28)]]></title>
            <link>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL28</link>
            <guid>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL28</guid>
            <pubDate>Thu, 16 Nov 2023 05:35:59 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h4 id="🐱-with-all-my-animal-🐶">🐱 With All My Animal 🐶</h4>
<p>💡 <strong>[ 28일차 11/16일 ]</strong> 💡</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jxxn_a/post/a98d78ad-b7ea-45f9-8406-b3b70c59b1d9/image.png" alt=""></p>
<blockquote>
<p>📌 <strong>오늘의 기술면접 질문 Q&amp;A</strong></p>
</blockquote>
<h3 id="1-오버로딩과-오버라이딩의-차이"><strong>1) 오버로딩과 오버라이딩의 차이</strong></h3>
<h3 id="🍒-오버로딩">🍒 오버로딩</h3>
<ul>
<li>같은 이름의 메소드를 사용하지만, 메소드마다 다른 용도로 사용되며 그 결과물도 다르게 구현할 수 있게 만드는 것이다.<pre><code class="language-kotlin">fun add(a: Int, b: Int) : Int {
  return a + b
}
</code></pre>
</li>
</ul>
<p>fun add(a: Int, b: Int, c: Int) : Int {
    return a + b + c
}</p>
<pre><code>---
### 🍒 오버라이딩
- 부모클래스에서 상속받은 자식클래스가 부모클래스에서 만들어진 메소드를 자신의 입맛에 맞게 다시 재정의해서 사용하는 것이다.

```kotlin
// 모든 클래스와 메소드가 final로 선언되어있어서 상속이나 오버라이딩이 불가능하기 때문에
// 클래스나 메소드를 상속 또는 오버라이딩 하려면 &#39;open&#39; 키워드가 있어야한다.

open class Parent {
   open fun hello() {
      println(&quot;Hello from Parent&quot;)
   }
}

class Child : Parent() {
    override fun hello() {
         println(&quot;Hello from Child&quot;)
    }
}</code></pre><hr>
<h3 id="2-deep-links와-app-links의-차이점을-설명해주세요"><strong>2) Deep Links와 App Links의 차이점을 설명해주세요</strong></h3>
<h3 id="🍊-deep-links">🍊 Deep Links</h3>
<ul>
<li><p>앱의 특정 페이지나 컨텐츠를 직접 가르키는 URL이다.</p>
</li>
<li><p>사용자가 앱의 특정 부분에 바로 접근 할 수 있다.</p>
</li>
<li><p>다른 앱 또는 웹 브라우저에서 링크를 클릭 했을 때 앱을 실행하며 해당 링크를 처리하는 앱이 2개 이상이 있다면 다이얼로그로 사용자에게 선택하여 실행할 수있게 보여준다.</p>
</li>
<li><p>하지만, Deep Links는 앱이 설치되어 있지 않으면 웹 페이지로 리디렉션된다.</p>
</li>
<li><p>URL 형식 : (예시) &quot;myapp://section/page&quot; 처럼 형식이 자유롭다.</p>
<ul>
<li>http 스킴 뿐만 아니라, 앱 고유의 스킴을 사용할 수있다.</li>
</ul>
</li>
<li><p>앱 마케팅에서 많이 활용된다.</p>
</li>
<li><p>연결 할 수 있는 앱이 없을 경우에는 폴백 URL을 설정하여 사용자에게 해당 앱을 설치하라는 안내페이지나 관련 콘텐츠가 담긴 웹페이지를 보여준다.</p>
</li>
</ul>
<pre><code class="language-kotlin">// android Manifest
&lt;activity android:name=&quot;.ViewProductActivity&quot;&gt;
    &lt;intent-filter&gt;
        &lt;action android:name=&quot;android.intent.action.VIEW&quot; /&gt;
        &lt;category android:name=&quot;android.intent.category.DEFAULT&quot; /&gt;
        &lt;category android:name=&quot;android.intent.category.BROWSABLE&quot; /&gt;
        &lt;data android:scheme=&quot;http&quot; 
            android:host=&quot;www.mystore.com&quot; 
            android:pathPrefix=&quot;/product&quot; /&gt;
    &lt;/intent-filter&gt;
&lt;/activity&gt;
</code></pre>
<hr>
<h3 id="🍊-app-links">🍊 App Links</h3>
<ul>
<li><p>Android 6.0(API 23)에서 도입된 기능이다.</p>
</li>
<li><p>인증된 웹사이트 URL 을 기반으로 하는 DeepLink이다.</p>
</li>
<li><p>앱과 웹 사이트를 보다 더 강하게 연결해준다.</p>
</li>
<li><p>링크 클릭 시 앱이 설치되어 있다면 즉시 열어서 보여주고 없다면 웹으로 이동한다. (다이얼로그는 나타나지 않는다)</p>
</li>
<li><p>앱 링크를 통해 사용자의 경험을 더욱 원활하게 만드는 것이 가능하다.</p>
</li>
<li><p>URL 형식 : (예시) &quot;<a href="http://www.mysite.com/page&quot;">http://www.mysite.com/page&quot;</a> 와 같은 형식이다.</p>
<ul>
<li>반드시 https 스킴을 사용해야하며, 이는 App Link의 보안 강화를 위한 조치이기 때문이다.</li>
</ul>
</li>
</ul>
<pre><code class="language-kotlin">// android Manifest
&lt;activity android:name=&quot;.ViewProductActivity&quot;&gt;

// App Links를 사용하려면 intent-filter에 android:autoVerify=&quot;true&quot;가 들어가야한다.
    &lt;intent-filter android:autoVerify=&quot;true&quot;&gt;
        &lt;action android:name=&quot;android.intent.action.VIEW&quot; /&gt;
        &lt;category android:name=&quot;android.intent.category.DEFAULT&quot; /&gt;
        &lt;category android:name=&quot;android.intent.category.BROWSABLE&quot; /&gt;
        &lt;data android:scheme=&quot;https&quot; 
            android:host=&quot;www.mystore.com&quot; 
            android:pathPrefix=&quot;/product&quot; /&gt;
    &lt;/intent-filter&gt;
&lt;/activity&gt;
</code></pre>
<hr>
<h3 id="🍊-deeplink와-applink의-차이점-">*<em>🍊 DeepLink와 AppLink의 차이점 *</em></h3>
<p><strong>1) Intent URL scheme</strong></p>
<ul>
<li>Deep Link : http, https 또는 custom cheme</li>
<li>App Link : http 또는 https가 필요</li>
</ul>
<p><strong>2) Intent action</strong></p>
<ul>
<li>Deep Link : 아무 액션이나 가능함 </li>
<li>App Link : android.intent.action.VIEW가 필요</li>
</ul>
<p><strong>3) Intent category</strong></p>
<ul>
<li>Deep Link : 아무 카테고리나 가능함</li>
<li>App Link : android.intent.category.BROWSABLE과 android.intent.category.DEFAULT가 필요함</li>
</ul>
<p><strong>4) 링크 인증</strong></p>
<ul>
<li>Deep Link : 없음</li>
<li>App Link : HTTP 웹사이트 내에 제공된 Digital Asset Link가 필요함</li>
</ul>
<p><strong>5) 사용자 경험</strong></p>
<ul>
<li>Deep Link : 링크를 눌렀을 때 사용자가 어떤 앱을 실행할 지 다이얼로그가 나타남</li>
<li>App Link : 다이얼로그가 없으며, 웹사이트 링크를 통해 앱을 구동함</li>
</ul>
<p><strong>6) 호환성</strong></p>
<ul>
<li>Deep Link : 모든 버전에서 가능함</li>
<li>App Link : android 6.0 이상</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종 팀프로젝트 TIL(27)]]></title>
            <link>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL27</link>
            <guid>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL27</guid>
            <pubDate>Wed, 15 Nov 2023 05:43:05 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>🐱 <strong>With All My Animal</strong> 🐶
💡 <strong>[ 27일차 11/15일 ]</strong> 💡</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jxxn_a/post/dc86a574-1b1d-483d-8de5-371b89c3eb39/image.png" alt=""></p>
<blockquote>
<p>📌 <strong>오늘의 기술면접 질문 Q&amp;A</strong></p>
</blockquote>
<h3 id="1-패키지는-무엇일까요"><strong>1) 패키지는 무엇일까요?</strong></h3>
<ul>
<li><p>파일의 최상단에 위치하며 다음과 같이 선언된다.</p>
<pre><code class="language-kotlin">package com.kittyandpuppy.withallmyanimal</code></pre>
</li>
<li><p>package는 서로 관련된 클래스, 함수, 프로퍼티 등을 그룹화 하는 방법을 제공한다.</p>
</li>
<li><p>코드의 구조를 체계적으로 관리하고, 같은 이름의 다른 클래스나 함수들이 서로 충돌하는 것을 방지하는 역할을 한다.</p>
</li>
<li><p>아래와 같이 선언하면 해당 파일의 모든 클래스, 함수, 프로퍼티는 com.kittyandpuppy.withallmyanimal.home package에 속하게 된다.</p>
<pre><code class="language-kotlin">package com.kittyandpuppy.withallmyanimal.home</code></pre>
</li>
<li><p>package 내에 있는 클래스나 함수를 사용하려면, 해당 package를 import 해야한다.
예시) </p>
<pre><code class="language-kotlin">import com.kittyandpuppy.withallmyanimal.home</code></pre>
</li>
</ul>
<hr>
<h3 id="2-contentprovider는-무엇인가요"><strong>2) ContentProvider는 무엇인가요?</strong></h3>
<ul>
<li><p>안드로이드에서 데이터를 관리하고 다른 애플리케이션과 공유하는 기능을 제공하는 컴포넌트이다.</p>
</li>
<li><p>애플리케이션 간의 데이터 공유를 가능하게 하며, 데이터를 읽고 쓰는데 필요한 인터페이스를 제공한다. (데이터 읽기, 쓰기, 업데이트, 삭제 등의 기능 제공)</p>
</li>
<li><p>데이터의 보안성을 유지하면서도 다른 애플리케이션과의 상호작용을 가능하게 하므로, 안드로이드 시스템에서 중요한 역할을 수행한다.
예시) 사진, 연락처 등의 데이터를 다른 애플리케이션과 공유할 수 있다.</p>
</li>
<li><p>URI(Uniform Resource Identifier)를 통해 데이터에 접근하며 이 URI는 ContentProvider를 식별하는데 사용된다. 데이터는 테이블 형식으로 저장되며, 각 테이블은 고유의 URI를 가지고 있다.</p>
</li>
<li><p>SQL 데이터베이스, 파일 시스템, 웹 또는 앱이 생성하거나 복원할 수있는 모든 저장 위치에 데이터를 저장할 수 있다.</p>
</li>
<li><p>데이터 보안을 위해 권한 관리를 제공하며, 다른 앱이 ContentProvider의 데이터에 접근하려면 권한이 필요하다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종 팀프로젝트 TIL(26)]]></title>
            <link>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL26</link>
            <guid>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL26</guid>
            <pubDate>Tue, 14 Nov 2023 06:11:11 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>🐱 <strong>With All My Animal</strong> 🐶
💡 <strong>[ 26일차 11/14일 ]</strong> 💡</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jxxn_a/post/e21c0c44-563c-4fc8-a54f-8dbfc8648c99/image.png" alt=""></p>
<blockquote>
<p>📌 <strong>오늘의 기술면접 질문 Q&amp;A</strong></p>
</blockquote>
<h3 id="1접근제어자는-어떤게-있을까요">1)접근제어자는 어떤게 있을까요?</h3>
<h3 id="✨-접근제어자란">✨ 접근제어자란?</h3>
<ul>
<li>클래스, 인터페이스, 함수, 프로퍼티의 가시성을 제한할 때 사용한다.</li>
<li>접근제어자를 통해 캡슐화 등의 객체지향 프로그래밍 원칙을 잘 지킬 수 있게 돕는다.</li>
</ul>
<hr>
<h3 id="🚀-private">🚀 Private</h3>
<ul>
<li>Private 접근 제한자가 붙은 멤버는 해당 클래스 내부에서만 접근이 가능하다.</li>
<li>Private가 붙은 최상위 함수나 프로퍼티는 해당 파일 내에서만 접근이 가능하다.</li>
</ul>
<hr>
<h3 id="🚀-protected">🚀 Protected</h3>
<ul>
<li>protected 접근 제한자는 private랑 유사하지만, 하위 클래스에서는 접근이 가능하다.</li>
<li>상위 함수나 프로퍼티에는 protected를 사용할 수없다.</li>
</ul>
<hr>
<h3 id="🚀-internal">🚀 Internal</h3>
<ul>
<li>internal 접근 제한자는 같은 모듈 내에서는 접근이 가능하다.</li>
<li>모듈은 ntelliJ IDEA의 모듈, Maven의 프로젝트, Gradle의 소스 세트 등을 의미한다.</li>
</ul>
<hr>
<h3 id="🚀-public">🚀 Public</h3>
<ul>
<li>public 접근 제한자는 어디서든 접근이 가능하게 한다.</li>
<li>별도의 접근 제한자를 지정하지 않으면 public으로 간주한다.</li>
</ul>
<hr>
<h3 id="2-foreground-service와--background-service의-차이점이-무엇인가요">2) foreground service와  background service의 차이점이 무엇인가요?</h3>
<h3 id="✨-service란">✨ Service란?</h3>
<ul>
<li>Android에서 Service는 주로 백그라운드에서 실행되는 오래 실행되는 작업을 위한 구성요소이다.</li>
<li>Service는 사용자 인터페이스를 가지지 않고, 서비스를 실행하는 Activity가 종료되더라도 백그라운드에서 계속 실행될 수 있다.</li>
</ul>
<hr>
<h3 id="🚀-foreground-service">🚀 foreground service</h3>
<ul>
<li>사용자에게 가시적인 작업을 수행한다.</li>
<li>사용자의 직접적인 상호작용이 필요한 작업이거나 중단되어서는 안되는 작업을 수행 할 때 사용된다.</li>
<li>foreground service는 항상 알림을 통해 사용자에게 자신의 존재를 알려야한다.</li>
<li>예시) 음악 재생, 파일 다운로드 등</li>
</ul>
<hr>
<h3 id="🚀-background-service">🚀 background service</h3>
<ul>
<li>사용자에게 직접적으로 보이지 않는 작업을 수행한다.</li>
<li>주로 사용자가 직접적으로 인지하지 못하는 작업을 수행할 때 사용된다.</li>
<li>사용자의 눈에 띄지 않기 때문에 시스템의 메모리 부족 상황에서는 시스템에 의해 종료될 수 있다.</li>
<li>예시) 데이터 동기화, 알림 체크 등</li>
</ul>
<hr>
<blockquote>
<p>📌 ** App 안에서 발생한 오류 **</p>
</blockquote>
<h3 id="🚨-startforresult">🚨 startForResult</h3>
<ul>
<li><p><strong>에러가 발생하는 시기</strong></p>
<ul>
<li>HomepageFragment에서 게시물을 클릭했을 때</li>
<li>MypageFragment에서 내가 쓴 게시물을 클릭했을 때 등등</li>
</ul>
</li>
<li><p><strong>해결 방안</strong>: 초기화 방식과 변수 선언 방식 변경하기</p>
</li>
<li><p><strong>수정 전 코드</strong></p>
<pre><code class="language-kotlin">private val startForResult =
      registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -&gt;
          if (result.resultCode == Activity.RESULT_OK) {
              Log.d(TAG, result.resultCode.toString())
              deletedKey = result.data?.getStringExtra(&quot;deletedPostKey&quot;)
                  ?: return@registerForActivityResult
              rvAdapter?.deletePost(deletedKey)
          }
      }
</code></pre>
</li>
</ul>
<hr>
<pre><code>    private fun setUpRecyclerView() {
    rvAdapter = HomeRVAdapter(boardList) { intent -&gt;
        startForResult.launch(intent)
    }</code></pre><pre><code>
- **수정 후 코드**
```kotlin
private var startForResult: ActivityResultLauncher&lt;Intent&gt;? = null
-------------------------------------------------------------------------------------------------------
 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        Log.d(TAG, &quot;viewCreated 불리니&quot;)
        startForResult =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -&gt;
                if (result.resultCode == Activity.RESULT_OK) {
                    Log.d(TAG, result.resultCode.toString())
                    deletedKey = result.data?.getStringExtra(&quot;deletedPostKey&quot;)
                        ?: return@registerForActivityResult
                    rvAdapter?.deletePost(deletedKey)
                }
            }
-------------------------------------------------------------------------------------------------------
private fun setUpRecyclerView() {
        rvAdapter = HomeRVAdapter(boardList) { intent -&gt;
            startForResult?.launch(intent)
        }
        binding.rvHome.apply {
            setHasFixedSize(true)
        _binding = null
    }

    override fun onDestroy() {
        startForResult = null
        super.onDestroy()
    }</code></pre><hr>
<h3 id="🚨-arrayindexoutofboundsexception--length10-index-1">🚨 ArrayIndexOutOfBoundsException : length=10; index=-1</h3>
<ul>
<li><p><strong>에러가 발생하는 시기</strong></p>
<ul>
<li>MypageFragment Like List 클릭했을 때</li>
</ul>
</li>
<li><p>** 에러가 발생한 이유 **</p>
<ul>
<li>인덱스 범위를 벗어나는 접근을 시도했을 때 발생한다.</li>
<li>RecyclerView에서 adapterPosition은 현재 View Holder가 binding 되어있는 아이템의 위치를 나타내지만, 아이템이 아직 binding 되지 않았거나, binding이 해제되었을 경우에는 -1이 되어 인덱스의 범위를 벗어나는 접근이 되어버린다.</li>
<li>adapterPosition이 유효하다는 것은 ViewHolder가 binding 된 상태라는 의미이지만, 그것이 반드시 list에 데이터가 있음을 보장하지 않는다.</li>
</ul>
</li>
</ul>
<ul>
<li><strong>해결 방안</strong>: 접근 전에 해당 인덱스가 유효한지를 항상 확인하는 로직을 추가한다.</li>
</ul>
<pre><code class="language-kotlin">init {
            binding.root.setOnClickListener {

            // 아래 두 줄 추가하기
                val position = adapterPosition
                if (position != RecyclerView.NO_POSITION &amp;&amp; list.size &gt; position) {

                    val clickedItem = list[adapterPosition]
                    val uid = clickedItem.uid
                    val key = clickedItem.key
                    val category = clickedItem.category</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종 팀프로젝트 TIL(25)]]></title>
            <link>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL25</link>
            <guid>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL25</guid>
            <pubDate>Mon, 13 Nov 2023 05:45:51 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h4 id="🐱-with-all-my-animal-🐶">🐱 With All My Animal 🐶</h4>
<p>💡 <strong>[ 25일차 11/13일 ]</strong> 💡</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jxxn_a/post/ad40d085-91e4-4ff0-810a-94d88b02f29c/image.png" alt=""></p>
<blockquote>
<p>📌 <strong>오늘의 기술면접 질문 Q&amp;A</strong></p>
</blockquote>
<h3 id="1-디폴트-파라미터에-대해서-설명해주세요장단점">1) 디폴트 파라미터에 대해서 설명해주세요(장/단점)</h3>
<h3 id="-⭐-장점">** ⭐ 장점**</h3>
<p><strong>- 함수 오버로딩을 줄여준다.</strong>
    - 같은 이름의 함수를 여러 개 만들지 않고도 다양한 인자 조합으로 함수를 호출 할 수 있기 때문에 코드의 중복을 줄이고 가독성을 향상 시킬 수 있다.</p>
<p><strong>- 유연성을 증가시킨다.</strong>
    - 함수를 호출하는 쪽에서 필요한 인자만 제공하고 나머지 인자는 디폴트 값으로 사용할 수 있기 때문에 함수 호출이 더 유연해진다.</p>
<h3 id="⭐-단점"><strong>⭐ 단점</strong></h3>
<p><strong>- 가독성을 저해할 수 있다.</strong>
    - 함수 호출 시, 어떤 인자가 생략되었는지, 어떤 인자가 디폴트 값으로 사용되는지 명확하게 알기 어렵기 때문에 코드를 읽는 사람은 혼란스러울 수있다.</p>
<p><strong>- 잘못된 디폴트 값이 사용될 수 있다.</strong>
    - 디폴트 파라미터의 값이 잘못 설정되었을 경우, 예상치 못한 동작이나 버그를 발생시킬 수 있기 때문에 디폴트 파라미터의 값을 신중하게 설정하고 관리해야한다.</p>
<h3 id="🚨-인자란-">*<em>🚨 인자란? *</em></h3>
<pre><code class="language-kotlin">fun add(a: Int, b: Int): Int {
    return a + b
}

fun main() {
    val result = add(3, 5)  // 3이랑 5가 인자
    println(result)
}

// 출력: 8
</code></pre>
<h3 id="-🚨-디폴트-파라미터의-예시-">** 🚨 디폴트 파라미터의 예시 **</h3>
<pre><code class="language-kotlin">// 디폴트 파라미터를 가진 함수 선언
fun greet(name: String, greeting: String = &quot;Hello&quot;) {
    println(&quot;$greeting, $name!&quot;)
}

fun main() {
    // 모든 파라미터에 값을 전달
    greet(&quot;Mina&quot;, &quot;Hi&quot;) // 출력: &quot;Hi, Mina!&quot;

    // 디폴트 파라미터인 greeting에 값을 전달하지 못함
    greet(&quot;Mina&quot;) // 출력: &quot;Hello, Mina!&quot;
}
</code></pre>
<hr>
<h3 id="2-안드로이드-앱에서-데이터-저장-방법에-대해-설명하세요">2) 안드로이드 앱에서 데이터 저장 방법에 대해 설명하세요</h3>
<h3 id="🌠-shared-preferences"><strong>🌠 Shared Preferences</strong></h3>
<ul>
<li>간단한 키와 값을 쌍으로하여 데이터를 저장하는데 사용된다.</li>
<li>사용자의 설정 정보나 간단한 데이터를 저장할 때 주로 사용된다.</li>
<li>각 앱마다 독립적으로 저장되며, 다른 앱에서 접근 할 수 없다.</li>
<li>사용자의 개인 정보와 같은 데이터를 저장하는데 적합하다.</li>
</ul>
<hr>
<h3 id="-🌠-internal-storage">** 🌠 Internal Storage**</h3>
<ul>
<li>Android 시스템에서 앱 별로 할당되는 저장공간이다.</li>
<li>각 앱은 자신의 Internal Storage 영역에 파일을 생성하고 사용할 수 있다.</li>
<li>이 영역의 파일은 해당 앱에서만 접근이 가능하며,다른 앱이 접근 할 수 없는 영역에 데이터를 저장하는 방법이다.</li>
</ul>
<hr>
<h3 id="🌠-external-storage"><strong>🌠 External Storage</strong></h3>
<ul>
<li>android 시스템에서 제공하는 추가적인 저장공간을 가르킨다. (내장메모리나 SD카드와 같은 물리적 저장소를 포함 할 수 있다.)</li>
<li>공용 영역에 저장하여 다른 앱이 접근 할 수 있도록 하는 방법이다.</li>
<li>사용자가 접근 할 수 있고 사진이나 음악처럼 크기가 크고 공유해야하는 데이터를 저장할 때 사용된다.</li>
</ul>
<hr>
<h3 id="🌠-sqlite-database"><strong>🌠 SQLite Database</strong></h3>
<ul>
<li>안드로이드에서 제공하는 경량 데이터베이스로 복잡한 구조를 가진 데이터를 저장하고 관리할 때 사용된다.</li>
<li>서버가 필요없는 데이터베이스이다.</li>
<li>파일 기반의 데이터베이스로 모든 데이터를 단일 파일에 저장한다.</li>
<li>앱의 데이터를 구조적이고 효율적으로 저장할 수 있게 해주며, SQL문을 사용하여 데이터를 조작할 수 있다.</li>
</ul>
<hr>
<h3 id="🌠-firebase-realtime-database--firestore"><strong>🌠 Firebase Realtime Database / FireStore</strong></h3>
<ul>
<li>Firebase에서 제공하는 NoSQL 클라우드 데이터베이스이다.</li>
<li>두 데이터 모두 실시간으로 데이터를 동기화하고 저장할 수 있다.</li>
<li>오프라인에서도 앱이 작동하도록 지원한다.</li>
</ul>
<blockquote>
<p>** 📌 Firebase Realtime Database와 FireStore**</p>
</blockquote>
<p><strong>1) Firebase Realtime Database</strong></p>
<ul>
<li>Firebase Realtime Database는 JSON 형태로 데이터를 저장하며, 모든 데이터는 싱글 트리에 저장된다.</li>
<li>실시간으로 데이터를 동기화하므로 사용자는 항상 최신 상태의 데이터를 볼 수있다.</li>
<li>오프라인에서도 앱이 작동하도록 지원하며, 다시 온라인 상태가 되면 데이터가 동기화된다.</li>
<li>단점으로는 데이터 모델링과 복잡한 쿼리에 제한이 있고, 데이터가 크게 증가 할 경우 스케일링에 제한이 있다.</li>
</ul>
<p>*<em>2) FireStore *</em></p>
<ul>
<li>Firebase Realtime Database의 단점을 해결하기 위한 새로운 데이터 베이스이다.</li>
<li>데이터를 문서와 컬렉션으로 구조화하여 저장하고, 직관적인 데이터 모델링을 가능하게 한다.</li>
<li>풍부한 쿼리 기능을 제공하며, 데이터베이스 스케일링이 더욱 용이하다.</li>
<li>실시간 데이터 동기화 및 오프라인 지원기능을 가지고 있다.</li>
</ul>
<hr>
<h3 id="-🌠-datastore">** 🌠 DataStore**</h3>
<ul>
<li>android Jetpack의 일부로 앱의 데이터를 안전하게 저장하는데 사용되는 새로운 데이터 저장 방법이다.</li>
<li>Shared Preferences의 대체제로 개발되었다.</li>
<li>Preferences DataStore와 Proto DataStore 두 가지 형태로 제공된다.</li>
<li>Flow를 사용하여 비동기적으로 데이터를 읽어오고 저장하며 메인 스레드에서 안전하게 데이터를 읽고 쓸 수 있도록 해준다.</li>
<li>데이터의 일관성을 보장하며, 데이터를 읽고 쓰는 동안 데이터 충돌을 방지한다.</li>
<li>네트워크 연결이 없는 상황에서도 잘 동작하며, 네트워크가 연결되면 변경사항이 동기화된다.</li>
<li>Shared Preferences에서 DataStore로 데이터를 쉽게 마이그레이션 할 수있다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[WIL(13)]]></title>
            <link>https://velog.io/@jxxn_a/WIL13</link>
            <guid>https://velog.io/@jxxn_a/WIL13</guid>
            <pubDate>Sat, 11 Nov 2023 15:06:45 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="5주차-회고-노트">5주차 회고 노트</h3>
<p>2023.11.06 ~ 2023.11.10 Android App 최종 팀프로젝트 5주차</p>
</blockquote>
<blockquote>
<p>📌 <strong>트러블 슈팅</strong></p>
</blockquote>
<p>🐶 : 좀 더 효율적으로 코드를 구성할 수 있는 방법이 무엇인지 모르겠음
🐰 : 어떤 코드를 써야 좀 더 좋은 코드가 완성되고, 문제가 발생했을 때 해결이 되는지 모르겠음
🐑 : 버그나 기술적인 의사결정 때 관련 지식이 부족해서 빠른해결을 하지 못함
🐮 : 코드가 좀 더 최적화된 효율적으로? 짜고싶은데 어떻게해야할지 잘 모르겠습니다.</p>
<blockquote>
<p>📌 <strong>이번 주 한 일</strong></p>
</blockquote>
<ul>
<li>** 팀 전체**<ul>
<li>버그 수정</li>
<li>배포 준비</li>
<li>PPT 방향성 논의</li>
<li>시연 영상 시놉시스 논의</li>
</ul>
</li>
</ul>
<p><strong>- 팀원 개인</strong>
🐶 : 버그 수정(게시글 수정, 전체 동기화, 이미지 변경 즉각 반영) / 앱 빌드 / 개발자 계정 생성 / 앱 배포
🐰 : 버그수정(삭제된 태그가 피드에서 보이는 버그 수정, 일지 수정 시 태그를 수정하지 않고 저장을 할 경우 중복된 태그가 있다는 토스트 버그 수정) / 기기의 테마가 다크모드여도 라이트모드로 볼 수 있게 제한
🐑 : 버그수정(마이페이지 이미지 바로 반영) / 검색 키보드 내림
🐮 : 검색과 스피너의 정보가 다른 페이지를 갔다가와도 정보가 유지되는 기능 / 홈피드에서 위에서 아래로 당겼을때 새로고침되는 기능</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종 팀프로젝트 TIL(24)]]></title>
            <link>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL24</link>
            <guid>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL24</guid>
            <pubDate>Fri, 10 Nov 2023 06:54:26 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h4 id="🐱-with-all-my-animal-🐶">🐱 With All My Animal 🐶</h4>
<p>💡 **[ 24일차 11/10일 ] ** 💡</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jxxn_a/post/2719dad2-027a-43e1-acb5-95024158adac/image.png" alt=""></p>
<blockquote>
<p><strong>📌 오늘의 기술면접 질문 Q&amp;A</strong></p>
</blockquote>
<h3 id="1-in-키워드에-대해-설명해주세요-">*<em>1) in 키워드에 대해 설명해주세요. *</em></h3>
<h3 id="💫--반복문에서의-사용">💫 ** 반복문에서의 사용**</h3>
<ul>
<li>list나 다른 반복 가능한 객체를 순회하는데 사용된다.<pre><code class="language-kotlin">var numbers = listOf(1, 2, 3, 4, 5)
</code></pre>
</li>
</ul>
<p>for (number in numbers) {
   println(number)
}</p>
<p>// 출력
1, 2, 3, 4, 5</p>
<pre><code>---
### 💫 ** 범위 표현에서의 사용 **
- 범위를 정의할 때 &#39;..&#39; 연산자를 사용하며, 여기서 &#39;in&#39;은 범위에 속한 각 요소를 순회한다.
```kotlin
val range = 6..10

for (number in range) {
   println(number)
}

// 출력
6, 7, 8, 9, 10</code></pre><hr>
<h3 id="💫--컬렉션에-특정-요소가-포함되어-있는지-확인할-때-사용-">💫 ** 컬렉션에 특정 요소가 포함되어 있는지 확인할 때 사용 **</h3>
<ul>
<li>&#39;in&#39;은 컬렉션 특정 요소에 포함되어 있는지를 확인할 때 사용된다.<pre><code class="language-kotlin">val numbers = listOf(1, 2, 3, 4, 5)
</code></pre>
</li>
</ul>
<p>if (3 in numbers) {
  println(&quot;3은 리스트 안에 있습니다.&quot;)
}</p>
<p>// 출력
3은 리스트 안에 있습니다.</p>
<pre><code>---
### 💫 ** when 표현식에서의 사용 **
- &#39;when&#39; 표현식에서 패턴 매칭에 사용되어 특정 범위나 값의 유효성을 확인할 수 있다.
```kotlin
val result = when (x) {
   in 1..10 -&gt; &quot;x는 1과 10 사이에 있습니다.&quot;
   in validValues -&gt; &quot;x는 리스트에 포함되어 있습니다.&quot;
   else -&gt; &quot;x는 범위에 있지 않습니다.&quot;
 }</code></pre><hr>
<h3 id="2-recyclerview-adapter에서-반드시-구현해야하는-세가지-메소드가-무엇인가요-">*<em>2) RecyclerView Adapter에서 반드시 구현해야하는 세가지 메소드가 무엇인가요? *</em></h3>
<h3 id="🪐--oncreateviewholder-">🪐 ** onCreateViewHolder **</h3>
<ul>
<li>&#39;onCreateViewHolder는 viewHolder를 생성하고 초기화하는 역할을 한다.</li>
<li>viewHolder는 RecyclerView 내의 각 item View를 나타난다.</li>
</ul>
<pre><code class="language-kotlin">override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
// viewHolder 생성 및 초기화하는 코드가 들어가야한다.
}</code></pre>
<hr>
<h3 id="🪐--onbindviewholder-">🪐 ** onBindViewHolder **</h3>
<ul>
<li>onBindViewHolder&#39;는 ViewHolder에 데이터를 Binding하는 역할을 한다.</li>
<li>목록에서 특정 위치의 아이템 데이터를 가져와서 viewHolder에 설정한다.</li>
<li>스크롤 시에 재사용되는 ViewHolder에 새로운 데이터를 Binding 하는데 사용된다.<pre><code class="language-kotlin">override fun onBindViewHolder(holder: ViewHolder, position: Int) {
// viewHolder에 데이터를 binding하는 코드가 들어가야한다.
}</code></pre>
</li>
</ul>
<hr>
<h3 id="🪐--getitemcount-">🪐 ** getItemCount **</h3>
<ul>
<li>&#39;getItemCount&#39;는 RecyclerView에 표시 할 아이템의 개수를 반환한다.</li>
<li>RecyclerView는 이 값에 따라 몇 번째 아이템까지 그리는지 결정하므로 정확한 아이템 수를 반환해야한다.<pre><code class="language-kotlin">override fun getItemCount(): Int {
// 아이템의 총 개수를 반환하는 코드가 들어가야한다.
}</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종 팀프로젝트 TIL(23)]]></title>
            <link>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL23</link>
            <guid>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL23</guid>
            <pubDate>Thu, 09 Nov 2023 11:47:45 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h4 id="🐱-with-all-my-animal-🐶">🐱 With All My Animal 🐶</h4>
<p>💡 <strong>[ 23일차 11/9일 ]</strong> 💡</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jxxn_a/post/709b908c-33fe-4ac0-90ea-d1a25c520bfa/image.png" alt=""></p>
<blockquote>
<p>📌 <strong>오늘의 기술면접 질문 Q&amp;A</strong></p>
</blockquote>
<h3 id="1-when문은-어떨-때-사용하나요-">*<em>1) when문은 어떨 때 사용하나요? *</em></h3>
<ul>
<li><p>when은 범위가 제한되고 값도 특정할 수 있는 경우에 사용합니다.</p>
<ul>
<li>요일 데이터 : 월, 화, 수, 목, 금, 토, 일</li>
<li>월 데이터: 1월 .. 12월</li>
</ul>
</li>
<li><p>if문과의 차이점은 우선 조건을 검사하여 수행한다는 점은 비슷하지만, if랑 달리 when은 조건식이 아닌 조건을 검사할 값을 넣는다는 점이다.
즉, when에는 참이나 거짓이 아닌 변수가 들어간다.</p>
</li>
</ul>
<pre><code class="language-kotlin">fun main() {
    val x = 5

    when (x) {
        1 -&gt; println(&quot;x는 1이다&quot;)
        2, 3 -&gt; println(&quot;x는 2 또는 3이다&quot;)
        in 4..10 -&gt; println(&quot;x는 4와 10 사이에 있다&quot;)
        else -&gt; println(&quot;x는 다른 수이다&quot;)
    }
}

// 출력
x는 4와 10 사이에 있다</code></pre>
<hr>
<h3 id="⭐-표현식-when-">⭐ *<em>표현식 when *</em></h3>
<p>🌠 ** if문 **</p>
<pre><code class="language-kotlin">fun isPromotionTarget(addToCart: Boolean, rates: Int): Boolean {
    if (rates &lt; 2) { return false }
    if (rates &gt; 3) { return false }
    if (rates == 3) { return true }
    return addToCart &amp;&amp; rates == 2
}</code></pre>
<p>🌠 ** when문 **</p>
<pre><code class="language-kotlin">fun isPromotionTarget(addToCart: Boolean, rates: Int) = when {
    rates &lt; 2 -&gt; false
    rates &gt; 3 -&gt; false
    rates == 3 -&gt; true
    else -&gt; addToCart &amp;&amp; rates == 2
}</code></pre>
<p>=&gt; if문에 비해 when문이 더 나은 가독성과 유지보수성을 제공한다.
=&gt; when문은 if문에 비해서 간결하다.</p>
<p>🌠 ** kotlin 컴파일러 **
: when이 표현식으로 사용 될 때 else 부분이 존재하는지, 표현식이 가능한 입력에 대해 값을 생성하는지 검증한다.</p>
<p>🌠 ** when에 인자를 전달하는 예시 **</p>
<pre><code class="language-kotlin">fun whatToDo(dayOfWeek: Any) = when (dayOfWeek) {
    &quot;Saturday&quot;, &quot;Sunday&quot; -&gt; &quot;Relax&quot;
    in listOf(&quot;Monday&quot;, &quot;Tuesday&quot;, &quot;Wednesday&quot;, &quot;Thursday&quot;) -&gt; &quot;Work hard&quot;
    in 2..4 -&gt; &quot;Work hard&quot;
    &quot;Friday&quot; -&gt; &quot;Party&quot;
    is String -&gt; &quot;What?&quot;
    else -&gt; &quot;No Clue&quot;
}
println(whatToDo(&quot;Sunday&quot;)) // Relax
println(whatToDo(&quot;Wednesday&quot;)) // Work hard
println(whatToDo(3)) // Work hard
println(whatToDo(&quot;Friday&quot;)) // Party
println(whatToDo(&quot;Munday&quot;)) // What?
println(whatToDo(8)) // No Clue
</code></pre>
<hr>
<h3 id="⭐-명령문-when-">⭐ *<em>명령문 when *</em></h3>
<ul>
<li>하나 이상의 값에 기반해서 다른 동작을 원하는 경우 표현식이 아니라 명령문으로 사용하면 된다.</li>
<li>koltin에서 when이 명령문으로 사용 될 때는 else가 없어도 상관없다.</li>
</ul>
<pre><code class="language-kotlin">fun printWhatToDo(dayOfWeek: Any) {
    when (dayOfWeek) {
        &quot;Saturday&quot;, &quot;Sunday&quot; -&gt; println(&quot;Relax&quot;)
        in listOf(&quot;Monday&quot;, &quot;Tuesday&quot;, &quot;Wednesday&quot;, &quot;Thursday&quot;) -&gt; println(&quot;Work hard&quot;)
        in 2..4 -&gt; println(&quot;Work hard&quot;)
        &quot;Friday&quot; -&gt; println(&quot;Party&quot;)
        is String -&gt; println(&quot;What?&quot;)
    }
}
printWhatToDo(&quot;Sunday&quot;) // Relax
printWhatToDo(&quot;Wednesday&quot;) // Work hard
printWhatToDo(3) // Work hard
printWhatToDo(&quot;Friday&quot;) // Party
printWhatToDo(&quot;Monday&quot;) // What?
printWhatToDo(8) //</code></pre>
<hr>
<h3 id="2-안드로이드에서-사이즈가-큰-이미지를-불러오려고-합니다-어떤-방법을-사용할-수-있을까요"><strong>2) 안드로이드에서 사이즈가 큰 이미지를 불러오려고 합니다. 어떤 방법을 사용할 수 있을까요?</strong></h3>
<ul>
<li>Bitmap 크기 제한</li>
<li>이미지 리사이징</li>
<li>이미지 로딩 라이브러리 등의 방법이 있다.</li>
</ul>
<h3 id="⭐-bitmap-크기-제한">⭐ Bitmap 크기 제한</h3>
<ul>
<li>안드로이드에서는 메모리 제한이 있기 때문에 큰 이미지를 불러올 때 메모리 부족 문제가 발생할 수 있다. 그래서 큰 이미지를 다룰 때는 Bitmap 객체의 크기를 제한하는 것이 좋다.</li>
</ul>
<hr>
<h3 id="⭐-이미지-리사이징">⭐ 이미지 리사이징</h3>
<ul>
<li>이미지를 메모리에 로드하기 전에 이미지의 크기를 조절하여 메모리 양을 줄일 수 있다.</li>
<li><strong>이미지 형식</strong> : JPEG, PNG, AVIF, SVG</li>
</ul>
<h3 id="🎨-jpeg-">*<em>🎨 JPEG *</em></h3>
<ul>
<li><p>픽셀 기반의 래스터 이미지로 구성되어있으며 비트맵 이미지를 손실압축방식으로 압축할 때 일반적으로 사용되는 방식이다.</p>
</li>
<li><p><strong>래스터 이미지</strong> : 픽셀로 구성된 비트맵으로 이미지를 표현하는 것이다. 화소의 위치와 색상, 크기 등의 정보를 모두 저장한다.</p>
</li>
<li><p><strong>손실 압축</strong> : 데이터를 압축하는 과정에서 원본 데이터의 일부를 제거하는 방식이다. 파일의 크기를 줄일 수 있지만, 압축을 풀었을 때 원본 데이터를 완벽하게 복원 할 수없다.</p>
</li>
<li><p>JPEG는 파일 크기와 상관없이 복잡한 컬러와 세밀한 이미지 표현이 필요한 경우 최소한의 손실 압축률을 통해 사용하기에 적합하다.</p>
</li>
</ul>
<hr>
<h3 id="🎨-png-">*<em>🎨 PNG *</em></h3>
<ul>
<li><p>픽셀 기반의 래스터 이미지로 구성되어있지만, 비트맵 이미지를 손실없이 압축하는 방식을 사용하는 파일 형식이다.</p>
</li>
<li><p>JPEG와 마찬가지로 인터넷에서 가볍게 전송되는 것을 목표로 디자인되어서 비슷한 부분들이 있다.</p>
</li>
<li><p><strong>손실없는 압축</strong> : 원본 이미지의 모든 정보를 보존하면서 파일 크기를 줄일 수 있다.</p>
</li>
<li><p>투명도 제어, 간단한 이미지에 합리적인 압축률로 로고, 아이콘, 오버레이와 같은 단순한 이미지에 적합하다.</p>
</li>
<li><p>텍스트 기반의 그래픽을 지원하기는 하지만, SVG 보다는 저수준의 텍스트 기반 그래픽을 지원한다.</p>
</li>
</ul>
<hr>
<h3 id="🎨-avif-">*<em>🎨 AVIF *</em></h3>
<ul>
<li><p>사용자가 페이지 이미지를 보고 시각적으로 문제가 되는 요소가 없는 수준의 이미지 압축을 허용하는데 기존의 JPEG, PNG 등보다 낮은 용량으로 비슷한 이미지 품질을 보여준다.</p>
</li>
<li><p>AV1에 기반한 이미지 파일 포맷으로 AOM에 의해 개발되었으며, 아직은 잘 알려지지 않은 이미지 포맷 형식이다.</p>
</li>
</ul>
<p>** &lt; 특징 &gt; **</p>
<ul>
<li><p>효율적인 압축률과 뛰어난 이미지 품질을 제공한다.</p>
</li>
<li><p>10비트의 색상 깊이를 지원하여 10억가지 이상의 광범위한 색상 표현이 가능하다.</p>
</li>
<li><p>PNG 형식의 알파 채널을 통한 투명도 지원 뿐만 아니라 HDR 기능의 지원으로 밝은 부분과 어두운 부분 사이의 대비를 더욱 선명하게 표현할 수있다.</p>
</li>
<li><p>멀티미디어 기능, 여러 이미지나 애니메이션을 저장하는 것이 가능하다.</p>
</li>
</ul>
<hr>
<h3 id="🎨-svg-">*<em>🎨 SVG *</em></h3>
<ul>
<li>확장 가능한 벡터 그래픽을 나타내기 위한 xml 기반의 이미지 파일 형식으로 웹 페이지, 앱, 프린트 등 다양한 매체에서 사용된다.</li>
</ul>
<p><strong>&lt; 특징 &gt;</strong></p>
<ul>
<li><p>이미지를 선, 곡선, 다각형 등으로 구성하여 표현한다. </p>
</li>
<li><p>android app 개발에서는 SVG를 vector drawable로 변환하여 해상도에 따라 자동으로 스케일링 될 수 있도록하며, 이미지를 확대/축소해도 깨지지 않고 부드럽게 표현되는 장점을 가지고 있어서 다양한 크기와 해상도 디스플레이에서 사용하기 적합하다.</p>
</li>
<li><p>SVG는 xml 기반의 형식으로 정의되어 이미지에 대한 정보를 코드로 확인이 가능하며, 이미지를 텍스트로 편집하고 생성할 수 있으며 다른 요소와 결합하여 동적인 컨텐츠를 생성할 수 있는 유연성을 가지고 있다.</p>
</li>
<li><p>앱 개발은 다양한 해상도에서 이미지 품질을 유지하는 것이 중요한데 SVG를 통해 보완할 수있다.</p>
</li>
</ul>
<hr>
<h3 id="⭐-이미지-로딩-라이브러리-사용">⭐ 이미지 로딩 라이브러리 사용</h3>
<ul>
<li>Glide</li>
<li>Coil (요즘 Kotiln 개발에서 주로 사용되는 이미지 로딩 라이브러리)</li>
<li>Picasso</li>
<li>Fresco</li>
</ul>
<h3 id="✨-glide"><strong>✨ Glide</strong></h3>
<ul>
<li><p>많은 기능을 제공하며, 이미지 로딩 이외에도 GIF, 비디오 스틸 프레임 등 다양한 미디어 유형을 처리할 수있다.</p>
</li>
<li><p>메모리 관리 측면에서도 효과적으로 동작하며, 메모리 캐시, 디스크 캐시를 지원한다.</p>
</li>
<li><p>많은 커스터마이제이션 옵션을 제공하여 사용자가 이미지 로딩 동작을 세부적으로 제어할 수있다.</p>
</li>
<li><p>Activity나 Fragment의 lifecycle과 통합되어 자동으로 로딩 작업을 관리한다.</p>
</li>
</ul>
<hr>
<h3 id="✨-coil-">*<em>✨ Coil *</em></h3>
<ul>
<li><p>라이브러리 자체가 가벼워서 추가적인 의존성이 적다.</p>
</li>
<li><p>kotlin 환경에 높은 호환성을 제공하며, kotlin의 기능을 활용한 DSL을 간결한 코드로 작성이 가능하다.</p>
</li>
<li><p>간단하고 직관적인 API를 제공하여 초보자도 쉽게 사용할 수있다.</p>
</li>
<li><p>성능 면에서도 효율적으로 동작하며, 캐싱과 로딩 속도가 뛰어나다.</p>
</li>
<li><p>최신 이미지 로딩 라이브러리로 최신 안드로이드 플랫폼에 대한 최적화가 이루어져있다.</p>
</li>
<li><p>Kotlin의 코루틴을 지원하므로 비동기 작업을 편하게 처리할 수있다.</p>
</li>
</ul>
<hr>
<h3 id="✨-glide와-coil의-공통점-">*<em>✨ Glide와 Coil의 공통점 *</em></h3>
<ul>
<li><p>둘 다 이미지 로딩 및 캐싱을 효율적으로 처리한다.</p>
</li>
<li><p>둘 다 자체적으로 메모리 캐시 및 디스크 캐시를 관리한다.</p>
</li>
</ul>
<hr>
<p><strong>참고한 블로그</strong>
<a href="https://readystory.tistory.com/200">https://readystory.tistory.com/200</a> (when문)
<a href="https://junes-daily.tistory.com/78">https://junes-daily.tistory.com/78</a> (이미지 포맷 형식)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종 팀프로젝트 TIL(22)]]></title>
            <link>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL22</link>
            <guid>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL22</guid>
            <pubDate>Wed, 08 Nov 2023 04:53:31 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h4 id="🐱-with-all-my-animal-🐶">🐱 With All My Animal 🐶</h4>
<p>💡 <strong>[ 22일차 11/8일 ]</strong> 💡</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jxxn_a/post/9a1575ef-a5e2-4a0a-bd64-75ce8530d751/image.png" alt=""></p>
<blockquote>
<p>📌 <strong>오늘의 기술면접 질문 Q&amp;A</strong></p>
</blockquote>
<h3 id="1-enum-은-무엇인가요"><strong>1) enum 은 무엇인가요?</strong></h3>
<h3 id="🌻-enum">🌻 Enum</h3>
<pre><code class="language-kotlin">enum class Direction {
       SOUTH, NORTH, WEST, EAST  
}</code></pre>
<ul>
<li><p>enumerated type의 줄임말로 열거형이라는 뜻을 가지고 있으며 서로 연관되거나 또는 관련이 있는 상수들의 집합을 의미한다.</p>
</li>
<li><p><strong>Enum은 언제 사용하면 좋은가요?</strong></p>
<ul>
<li>사용하는 인스턴스의 수가 정해져있고, 관련되어 처리할 수 있는 상수값이 여러 개 존재할 때 사용한다.
ex) 로또 프로그램에서 1등부터 5등까지를 의미하는 등수와 각 등수가 만들어지는 조건, 그리고 각 등수에 해당하는 상금을 묶어 낼 필요가 있을 경우</li>
</ul>
</li>
</ul>
<pre><code class="language-kotlin">enum LottoRank {
    FIRST(6, false, 2_000_000_000),
    SECOND(5, true, 30_000_000),
    THIRD(5, false, 1_500_000),
    FOURTH(4, false, 50_000),
    FIFTH(3, false, 5_000),
    NONE(0, false, 0);
}</code></pre>
<hr>
<h3 id="2-retrofit이란-무엇인가요"><strong>2) Retrofit이란 무엇인가요?</strong></h3>
<h3 id="🌻-retrofit">🌻 Retrofit</h3>
<ul>
<li><p>Retrofit은 안드로이드 애플리케이션에서 통신 기능에 사용하는 코드를 사용하기 쉽게 만들어놓은 라이브러리이다.</p>
</li>
<li><p>다양한 플랫폼에서 REST 웹 서비스와 API를 손쉽게 사용하기 위한 라이브러리이다.</p>
</li>
<li><p>HTTP 요청을 효율적으로 처리하고, JSON 또는 XML과 같은 데이터 형식을 처리하는데 도움을 주는 라이브러리다.</p>
</li>
</ul>
<blockquote>
<h4 id="🌼--retrofit-특징-">🌼 ** Retrofit 특징 **</h4>
</blockquote>
<p>*<em>1) REST API 통신 *</em></p>
<ul>
<li>GET, POST, PUT, DELETE 등과 같은 다양한 HTTP 요청을 처리하는데 사용된다.</li>
<li>URL 경로 및 쿼리 매개변수를 쉽게 설정 할 수있다.</li>
</ul>
<p>*<em>2) 자동 직렬화 및 역직렬화 *</em></p>
<ul>
<li>JSON 또는 XML과 같은 데이터 형식을 자동으로 직렬화하여 요청 본문을 생성하고, 응답 데이터를 역직렬화하여 kotlin 객체로 변환 할 수있다.</li>
</ul>
<p>*<em>3) 안전한 타입 지원 *</em></p>
<ul>
<li>kotlin의 안전한 타입을 사용하여 API 응답을 파싱 할 수 있으므로 컴파일 시 타입 안정성을 보장한다.</li>
</ul>
<p>*<em>4) 커스터마이징 가능 *</em></p>
<ul>
<li>Retrofit을 사용하여 헤더, 인터셉터, 커스텀 컨버터 및 에러 핸들링과 같은 다양한 기능을 커스터 마이징을 할 수있다.</li>
</ul>
<blockquote>
<h4 id="🌼--retrofit-사용법-">🌼 ** Retrofit 사용법 **</h4>
</blockquote>
<ul>
<li><p><strong>라이브러리 추가 (gradle 파일)</strong></p>
<pre><code class="language-kotlin">implementation &#39;com.squareup.retrofit2:retrofit:2.9.0&#39;</code></pre>
</li>
<li><p>** API 인터페이스 정의 **</p>
<pre><code class="language-kotlin">interface ApiService {
  @GET(&quot;users/{user}&quot;)
  suspend fun getUser(@Path(&quot;user&quot;) username: String): User
}</code></pre>
</li>
<li><p>** Retrofit 객체 생성 **</p>
<ul>
<li>Retrofit 빌더를 사용하여 Retrofit 객체를 생성하고 API 서비스와 연결한다.<pre><code class="language-kotlin">val retrofit = Retrofit.Builder()
.baseUrl(&quot;https://api.example.com/&quot;)
.addConverterFactory(GsonConverterFactory.create())
.build()
</code></pre>
</li>
</ul>
</li>
</ul>
<p>val apiService = retrofit.create(ApiService::class.java)</p>
<pre><code>
- ** 비동기 요청 수행 **
    - Retrofit은 코루틴을 사용하여 비동기적으로 HTTP 요청을 수행한다.</code></pre><p>val user = apiService.getUser(&quot;Jxxn_a&quot;)</p>
<pre><code>---

### 🌼 ** class랑 enum class의 차이 **

- **class**
    - 일반적인 클래스를 나타낸다.
    - 객체지향 프로그래밍에서 사용되며, 데이터와 메서드를 포함하는 사용자 지정 타입을 정의할 때 주로 사용된다.
    - class는 필요에 따라 새로운 인스턴스를 생성하거나 기존 인스턴스의 속성과 메서드를 변경할 수있다.

```kotlin
class Person(val name : String, val age : Int)

val person = Person(&quot;Alice&quot;, 30)</code></pre><hr>
<ul>
<li><strong>enum class</strong><ul>
<li>열거형 클래스를 나타낸다.</li>
<li>관련된 상수 값을 그룹화하고 나타내는데 사용된다.</li>
<li>enum class의 각 요소는 해당 클래스의 유일한 인스턴스이며, 다른 객체와 비교할 때 일치 여부를 확인에 사용된다.</li>
<li>각 enum class 요소는 컴파일 타임에 이미 정의되어 있으며, 요소를 추가하거나 변경 할 수없다.</li>
<li>enum class 요소에 대해 추가 메서드나 속성을 정의할 수 있다.</li>
</ul>
</li>
</ul>
<pre><code class="language-kotlin">enum class Color {
    RED, GREEN, BLUE
}
val selectedColor = Color.RED
</code></pre>
<hr>
<ul>
<li><strong>차이점</strong><ul>
<li>class는 데이터와 메서드를 포함하는 사용자 지정 타입을 정의하는데 사용되며, enum class는 상수 값을 나타내고 제한된 인스턴스를 가지며 수정 할 수없는 열거형을 정의한다.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종 팀프로젝트 TIL(21)]]></title>
            <link>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8TIL21</link>
            <guid>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8TIL21</guid>
            <pubDate>Mon, 06 Nov 2023 15:47:43 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h4 id="🐱-with-all-my-animal-🐶">🐱 With All My Animal 🐶</h4>
<p>💡 <strong>[ 21일차 11/7일 ]</strong> 💡</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jxxn_a/post/e9544e57-9beb-45c8-a4b1-f669903faf3b/image.png" alt=""></p>
<blockquote>
<p>📌 <strong>오늘의 기술면접 질문 Q&amp;A</strong></p>
</blockquote>
<h3 id="1-kotlin의-프로퍼티와-변수의-차이-">*<em>1) Kotlin의 프로퍼티와 변수의 차이 *</em></h3>
<ul>
<li>프로퍼티는 클래스 내부에 선언된 변수를 의미하고, 변수는 값을 메모리에 저장하고 그 메모리 영역에 이름을 부여한 것이다.</li>
</ul>
<h3 id="🌻--프로퍼티란-">🌻 ** 프로퍼티란? **</h3>
<ul>
<li>프로퍼티는 변수와 함수의 조합이다.<ul>
<li>클래스 내부에서 데이터를 저장하고, 접근 방법을 제공한다.</li>
<li>class 내부에서 선언한 프로퍼티를 외부에서 다시 선언 할 필요가 없다.</li>
<li>프로퍼티는 값을 읽는 메서드인 getter와 값을 설정하는 setter를 자동으로 설정하거나 사용자가 직접 정의 할 수 있다.<pre><code class="language-kotlin">class User {
var name : String = &quot;&quot;
}
</code></pre>
</li>
</ul>
</li>
</ul>
<p>fun main() {
   val user = User()
   user.name = &quot;포비&quot;
   println(&quot;사용자 이름 : ${user.name}&quot;)
}</p>
<p>// 출력
사용자 이름 : 포비</p>
<h2 id="">```</h2>
<h3 id="2-androidmanifest에-대해-설명해주세요-">*<em>2) AndroidManifest에 대해 설명해주세요 *</em></h3>
<h3 id="🌻--androidmanifest-">🌻 ** AndroidManifest **</h3>
<ul>
<li><p>안드로이드가 앱을 실행하기 위해서는 그 앱에 어떤 컴포넌트가 있어야하는지 알아야하는데, 이러한 컴포넌트가 모두 정의되어있는 곳이 AndroidManifest이다.</p>
</li>
<li><p>그 이외에 다른 역할들</p>
<ul>
<li>앱에서 요구할 사용자 권한을 정의한다. ex) android.permissions.INTERNET</li>
<li>앱이 실행될 수 있는 최소 API 레벨을 정의한다.</li>
<li>앱에서 사용하는 하드웨어/소프트웨어 기능을 정의한다. ex) 카메라, 블루투스</li>
<li>앱에 링크되어야 하는 라이브러리를 선언한다. ex) Google Maps 라이브러리</li>
</ul>
</li>
<li><p>Android Application의 중요한 구성 파일 중 하나이며, Application의 여러 측면을 정의하고 설정하는데 사용된다.</p>
</li>
<li><p>Android Application에 대한 정보를 제공하며, Application이 실행되는 방식, 4대 컴포넌트 등의 구성요소에 대한 정보를 담고있다.</p>
</li>
<li><p>AndroidManifest는 Application의 핵심 구성을 정의하고, Android 운영 체제에게 Application의 특성과 요구사항을 전달하기 때문에 개발 및 배포할 때 관리를 잘해야한다.</p>
</li>
</ul>
<blockquote>
<p>🌼 ** AndroidManifest의 역할  **</p>
</blockquote>
<p><strong>1) 앱 구성 정보 제공하기</strong></p>
<ul>
<li>Application의 기본 정보를 제공한다.
ex) Application의 이름, 패키지 이름, 버전코드 &amp; 버전이름, 아이콘 등등</li>
</ul>
<p>*<em>2) 권한 설정 *</em></p>
<ul>
<li>AndroidManifest 파일은 Application이 사용자의 데이터 및 기기에 접근하기 위해 필요한 권한을 정의해두었다.</li>
<li>이를 통해서 사용자에게 어떤 권한이 필요한 지 알리고, 사용자의 동의를 얻을 수 있다.
ex) Application을 처음 실행 할 때 뜨는 권한 허용 다이얼로그</li>
</ul>
<p>*<em>3) Activity 및 화면 관리 *</em></p>
<ul>
<li>앱의 화면을 구성하는 Activity 및 각 Activity가 어떻게 상호작용하는지 정의한다.</li>
<li>Application 시작 시 어떤 Activity가 실행되어야 하는지 설정할 수 있다.
ex) SplashActivity or MainActivity</li>
</ul>
<p>*<em>4) 백그라운드 서비스 및 브로드캐스트 리시버 설정 *</em></p>
<ul>
<li>Application이 백그라운드에서 실행해야하는 서비스를 정의한다.</li>
<li>다른 Application이나 시스템에서 전송하는 브로드캐스트 이벤트를 수신하고 처리 할 브로드캐스트 리시버를 설정한다.</li>
</ul>
<p>*<em>5) 인텐트 필터 정의 *</em></p>
<ul>
<li>Application 구성 요소에 대한 인텐트 필터를 설정하여 다른 Application이 해당 구성요소로의 요청을 전달 할 수 있도록 한다.</li>
</ul>
<p>*<em>6) 앱 테마 &amp; 스타일 지정 *</em></p>
<ul>
<li>Application의 테마 및 스타일을 정의하여 앱의 모양과 느낌을 지정할 수있다.</li>
</ul>
<p>*<em>7) 빌드 설정 관리 *</em></p>
<ul>
<li>AndroidManifest에는 미니멈 SDK버전, 타겟 API버전, 스크린 크기 및 DPI와 같은 빌드 설정과 관련된 정보도 포함된다.</li>
</ul>
<p><strong>8) 앱의 핵심 구성 및 동작 설정</strong></p>
<ul>
<li>Application의 핵심 동작 및 구성을 정의하며, Android 운영체제에 Application의 특성과 요구사항을 알린다.</li>
</ul>
<hr>
<h3 id="🌼--프로퍼티와-변수의-차이점-">🌼 ** 프로퍼티와 변수의 차이점 **</h3>
<ul>
<li>프로퍼티는 주로 클래스 내부에서 선언된다. 변수는 주로 함수 내에서 선언되거나 클래스 외부에서 전역변수로 선언된다.</li>
<li>프로퍼티는 클래스의 상태를 나타내고, 객체의 속성을 저장하는데 사용되지만, 변수는 함수 내에서 일시적인 데이터를 저장하거나 클래스 외부에서 전역적으로 공유하는데 사용된다.</li>
</ul>
<hr>
<p><strong>[ 참고한 블로그 ]</strong>
<a href="https://thinking-face.tistory.com/entry/Android-Manifest-%ED%8C%8C%EC%9D%BC%EC%9D%B4%EB%9E%80">https://thinking-face.tistory.com/entry/Android-Manifest-%ED%8C%8C%EC%9D%BC%EC%9D%B4%EB%9E%80</a> (AndroidManifest)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종 팀프로젝트 TIL(20)]]></title>
            <link>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8TIL20</link>
            <guid>https://velog.io/@jxxn_a/%EC%B5%9C%EC%A2%85-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8TIL20</guid>
            <pubDate>Mon, 06 Nov 2023 06:40:49 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h4 id="🐱-with-all-my-animal-🐶">🐱 With All My Animal 🐶</h4>
<p>💡 <strong>[ 20일차 11/6일 ]</strong> 💡</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jxxn_a/post/803c6725-428b-4a48-b32b-729110e6e926/image.png" alt=""></p>
<blockquote>
<p>📌 <strong>오늘의 기술면접 질문 Q&amp;A</strong></p>
</blockquote>
<p><strong>1) 코틀린의 장점</strong></p>
<ul>
<li>자바와 상호 운용이 가능하며, 자바보다 구문이 간결하여 코드를 더 쉽게 읽고 쓸 수 있다. 또한, 기능적 프로그래밍을 지원하므로 더 읽기 쉽고 유지관리가 쉬운 코드를 더 쉽게 작성 할 수 있다.</li>
</ul>
<p><strong>2) Intent가 무엇인가요?</strong></p>
<ul>
<li><p>개발자가 어떤 의도를 가지고 메서드를 실행할 것인지를 인텐트 담아서 안드로이드에 전달하면 해당 인텐트를 해석하고 실행한다.</p>
</li>
<li><p>안드로이드 4대 컴포넌트 중 사용자와 상호작용을 담당하는 인터페이스인 액티비티는 이 Intent를 통해 다른 Application의 액티비티를 호출 할 수 있습니다.</p>
</li>
</ul>
<blockquote>
<p>📌 ** 에러 수정 **</p>
</blockquote>
<ul>
<li>작성된 일지를 수정할 때 일지의 내용과 사진만 수정하고 저장을 누를 시 태그가 중복되었다는 토스트 메세지가 지속적으로 뜨는 에러가 발생했다.</li>
</ul>
<pre><code class="language-kotlin">binding.btnBehaviorAdd.setOnClickListener {
    val chipName = binding.etvMypageBehaviorTag.text.toString()
    if (chipName.isNotBlank()) {
        // 태그 제한 개수 설정
        val maxChips = 3

        class MypageBehavior : AppCompatActivity() {
            return@setOnClickListener
        }

        var isDuplicate = false
        for (i in 0 until binding.chipGroup.childCount) {
            val chip = binding.chipGroup.getChildAt(i) as Chip
            if (chip.text.toString() == chipName) {
                isDuplicate = true
                break
            }
        }

        if (isDuplicate) {
            Toast.makeText(this, &quot;중복된 태그가 있습니다.&quot;, Toast.LENGTH_SHORT).show()
        } else {
            binding.chipGroup.addView(Chip(this).apply {
                text = chipName
                isCloseIconVisible = true
                setOnCloseIconClickListener {
                    binding.chipGroup.removeView(this)
                    tagListBehavior.remove(chipName)
                }
                chipBackgroundColor = ColorStateList.valueOf(Color.WHITE)
                val typeface: Typeface? =

                class MypageBehavior : AppCompatActivity() {
                }
            }
        }

                                            ...

                    private fun addChip(chipName: String) {
                        var isDuplicate = false
                        for (i in 0 until binding.chipGroup.childCount) {
                            val chip = binding.chipGroup.getChildAt(i) as Chip
                            if (chip.text.toString() == chipName) {
                                isDuplicate = true
                                break
                            }
                        }

                        if (!isDuplicate) {
                            binding.chipGroup.addView(Chip(this).apply {
                                text = chipName
                                isCloseIconVisible = true
                                setOnCloseIconClickListener {
                                    binding.chipGroup.removeView(this)
                                    tagListBehavior.remove(chipName)
                                }
                                chipBackgroundColor = ColorStateList.valueOf(Color.WHITE)
                                val typeface: Typeface? =
                                    ResourcesCompat.getFont(this@MypageBehavior, R.font.cafe24)
                                this.typeface = typeface
                            })
                            tagListBehavior.add(chipName)
                        } else {
                            Toast.makeText(this, &quot;중복된 태그가 있습니다.&quot;, Toast.LENGTH_SHORT).show()
                        }
                    }
                }</code></pre>
<ul>
<li><p><strong>오류가 생긴 이유</strong>
  -&gt; 중복된 태그가 계속 추가되었던 것
(원인: addChip 함수를 여러 번 호출하고 중복 태그를 여러 번 추가했던 것, 추가버튼 클릭 시 중복 확인이 두 번 진행되었던 것)</p>
</li>
<li><p><strong>해결 방안</strong>
  -&gt; 중복이 아닌 경우에만  addChip 함수 내에서만 호출하여 태그 추가 (중복 확인 X)</p>
</li>
<li><blockquote>
<p>추가 버튼 클릭 시 태그를 추가 전 중복 확인</p>
</blockquote>
</li>
<li><p>** 해결 된 코드 **</p>
<pre><code class="language-kotlin">binding.btnBehaviorAdd.setOnClickListener {
          val chipName = binding.etvMypageBehaviorTag.text.toString().trim()

          if (chipName.isNotBlank()) {
              val maxChips = 3
              if (binding.chipGroup.childCount &gt;= maxChips) {
                  Toast.makeText(this, &quot;최대 $maxChips 개의 태그만 추가할 수 있습니다.&quot;, Toast.LENGTH_SHORT)
                      .show()
                  return@setOnClickListener
              }

              val isDuplicate = tagListBehavior.any { it.equals(chipName, ignoreCase = true) }
              if (isDuplicate) {
                  Toast.makeText(this, &quot;중복된 태그가 있습니다.&quot;, Toast.LENGTH_SHORT).show()
              } else {
                  binding.chipGroup.addView(Chip(this).apply {
                      text = chipName
                      isCloseIconVisible = true
                      setOnCloseIconClickListener {
                          binding.chipGroup.removeView(this)
                      }
                      chipBackgroundColor = ColorStateList.valueOf(Color.WHITE)
                      val typeface: Typeface? =
                          ResourcesCompat.getFont(this@MypageBehavior, R.font.cafe24)
                      this.typeface = typeface
                      tagListBehavior.add(chipName)
                  })
                  Toast.makeText(this, &quot;태그가 추가되었습니다.&quot;, Toast.LENGTH_SHORT).show()
                  binding.etvMypageBehaviorTag.setText(&quot;&quot;)
              }
          } else {
              Toast.makeText(this, &quot;태그를 입력해주세요&quot;, Toast.LENGTH_SHORT).show()
          }
      }
  }

                                                  ...

     private fun addChip(chipName: String) {
      binding.chipGroup.addView(Chip(this).apply {
          text = chipName
          isCloseIconVisible = true
          setOnCloseIconClickListener {
              binding.chipGroup.removeView(this)
              tagListBehavior.remove(chipName)
          }
          chipBackgroundColor = ColorStateList.valueOf(Color.WHITE)
          val typeface: Typeface? =
              ResourcesCompat.getFont(this@MypageBehavior, R.font.cafe24)
          this.typeface = typeface
      })
      tagListBehavior.add(chipName)
  }
}
</code></pre>
</li>
</ul>
<p>```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[WIL(12)]]></title>
            <link>https://velog.io/@jxxn_a/WIL12</link>
            <guid>https://velog.io/@jxxn_a/WIL12</guid>
            <pubDate>Sun, 05 Nov 2023 14:48:52 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="4주차-회고-노트">4주차 회고 노트</h3>
<p>2023.10.30 ~ 2023.11.03 Android App 최종 팀프로젝트 4주차</p>
</blockquote>
<blockquote>
<p>📌 <strong>트러블 슈팅</strong></p>
</blockquote>
<p>🐶 : 문제 - 모든 걸 처리하고 담당하는 액티비티 / 해결, 시도 - MVVM으로 코드 리팩토링(아직 못함)
🐰 : 문제 - 프로필 사진 변경 시 바로 적용이 안 되는 것 / 해결, 시도 - 앱이 실행될 때 불러오는 부분의 코드를 다르게 변경해보았지만 아직 고쳐지지 못함 (해결 안됨)
🐮 : 문제 - 좋아요를 할시에 파이어베이스와 앱과의 데이터 연결이 안됨 / 해결 - 좋아요 노드를 하나 추가하여 연결</p>
<blockquote>
<p>📌 <strong>이번 주 한 일</strong></p>
</blockquote>
<ul>
<li><p><strong>팀 전체</strong></p>
<ul>
<li>중간 발표</li>
<li>추가 기능 구현 완료</li>
</ul>
</li>
<li><p><strong>팀원 개인</strong></p>
</li>
</ul>
<p>🐶</p>
<ul>
<li>중간 발표 PPT 제작, 시연 영상 편집, 발표</li>
<li>홈 피드 - 스피너 검색, 태그 검색 기능</li>
<li>마이 피드 - 일지 카테고리 태그 필터 기능</li>
<li>일지 수정 기능</li>
</ul>
<p>🐰</p>
<ul>
<li>전체적인 UI 수정 (Android 12 고려하여 수정)</li>
<li>오늘 날짜와 반려동물의 생일이 같을 때 생일 케이크 아이콘 띄우기</li>
</ul>
<p>🐮</p>
<ul>
<li>좋아요 페이지 리스트 추가 기능</li>
<li>비밀번호 변경시 안내창 UI추가</li>
<li>pricetext에 숫자가 천자리마다 콤마가 찍히게 기능추가</li>
</ul>
<p>🐑</p>
<ul>
<li>회원탈퇴 기능구현,UI만들기</li>
<li>댓글삭제 기능구현 </li>
</ul>
<blockquote>
<p> **  📌 프로젝트에 적용했던 핵심 기술 목록을 작성해 주시고, 각 기술을 도입하게된 의사결정 과정을 정리해주세요.**</p>
</blockquote>
<ul>
<li><p><strong>이외에도 기술적인 방향을 잡기 위한 질문을 정리해오시면 가장 좋습니다!</strong></p>
</li>
<li><p>Q1. 마이페이지 - 프래그먼트 안에 1개의 RV adapter가 있고, adapter 안에 2개의 뷰홀더를 연결하여 마이페이지 내 탭 레이아웃으로 왼쪽 탭은 내가 쓴 게시글 목록을, 오른쪽은 내가 좋아요한 게시글 목록을 보여주는데, 탭 레이아웃을 왔다갔다 할 때 오른 쪽 탭에서는 내가 쓴 게시글 목록이 0.5초 보였다 사라지고, 왼 쪽 탭에서는 내가 좋아요한 목록이 잠깐 보였다 사라지는데, 해결 할 방법이 있을까요?</p>
</li>
</ul>
<blockquote>
<p>**  📌 숙제 : 튜터링 받으며 다음 주까지 달성해야 할 일**</p>
</blockquote>
<ul>
<li><p>팀 전체</p>
<ul>
<li>배포 준비</li>
<li>버그 수정</li>
<li>코드 리팩토링</li>
</ul>
</li>
<li><p>팀원 개인
🐶 : 개발자 계정 생성, 버그 수정, 코드 리팩토링 시도
🐰 : 배포 과정 익히기
🐑 : 배포 준비,앱 구동 중 나올 수 있는 버그 빠르게 수정 위해 firebase 구조 다시보기
🐮 : 배포 과정 준비, 못 다한 기능 마무리하기, 앱 최적화</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Kotlin TIL(22) [객체지향 프로그래밍]]]></title>
            <link>https://velog.io/@jxxn_a/Kotlin-TIL22</link>
            <guid>https://velog.io/@jxxn_a/Kotlin-TIL22</guid>
            <pubDate>Sat, 04 Nov 2023 14:57:47 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/jxxn_a/post/0579626e-027e-42bc-85a1-0d53db6651a7/image.png" alt=""></p>
<blockquote>
<h3 id="💡객체지향-프로그래밍oop💡">💡객체지향 프로그래밍(OOP)💡</h3>
</blockquote>
<ul>
<li><p><strong>객체지향 프로그래밍이란?</strong>
프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고, 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법이다.</p>
</li>
<li><p><strong>Class &amp; Instanse</strong></p>
</li>
<li><p><em>예시 1)*</em> 붕어빵 기계(class) -&gt; 붕어빵(Instance)</p>
</li>
<li><p><em>예시 2)*</em> 차(class) -&gt; Porsche, Audi(Instance)</p>
</li>
</ul>
<blockquote>
<h4 id="💡객체지향-프로그래밍의-특징💡"><strong>💡객체지향 프로그래밍의 특징💡</strong></h4>
</blockquote>
<blockquote>
<p>** 💊 캡슐화(Encapsulation) 💊**
객체의 데이터를 외부에서 직접 접근하지 못하게 막는다. (함수를 통해서만 조작이 가능하게 하는 작업)</p>
</blockquote>
<ul>
<li><p><strong>캡슐화의 2가지 관점</strong></p>
<p><strong>1) 데이터 캡슐화</strong>
: 객체의 상태와 행동을 하나 단위로 묶는 자율적 실체</p>
<p><strong>2) 데이터 은닉화</strong>
: 외부에서 객체의 상태를 변경할 수 없게 숨기는 것</p>
</li>
<li><p>** 정보 은닉 목적**
: 필요가 없는 정보는 외부에서 접근하지 못하도록 제한하는 것으로 private 키워드를 사용한다.</p>
</li>
<li><p>** 정보 은닉이 필요한 이유 **
: 은닉하지 않으면 객체의 상태 정보에 누구나 접근이 가능해지고, 이것은 잘못된 데이터가 들어갈 수 있다는 의미이다. 이것을 방지하기 위해 필요하다.</p>
</li>
</ul>
<blockquote>
<p>** 📑 추상화(Abstraction) 📑 **
데이터나 프로세스 등을 의미가 비슷한 개념이나 표현으로 정의해나가는 과정이면서 동시에 각 개별 객체의 구현에 대한 상세함은 감추는 것이다.</p>
</blockquote>
<ul>
<li><p>객체들이 가진 공통의 특성들을 파악하고 불필요한 특성들을 제거하는 과정</p>
</li>
<li><p><strong>예시)</strong> 말티즈, 푸들, 시츄는 공통적으로 멍멍하는 소리를 내고, 꼬리가 있고, 다리가 4개가 있다. 이를 강아지라는 클래스로 추상화 할 수 있다.</p>
</li>
<li><p><strong>추상화를 사용 할 때 주의 할 점</strong>
: 속성 위주가 아닌 동작 위주로 정의하는 작업을 하는 것인데 객체의 동작에 연관되지 않은 속성들은 결국 불필요하다.</p>
</li>
<li><p>** 재사용성 **
1) OOP의 가장 큰 특성 중 하나가 바로 코드의 재사용성과 상속의 개념이다.
2) 같은 객체를 여러 개 만들어야하는 경우, 한 번 작성된 코드를 활용하여 동일한 객체를 만들 수 있다는 것이다.</p>
</li>
</ul>
<blockquote>
<p>** 💰 상속(Inheritance) 💰**</p>
</blockquote>
<ul>
<li><p>기존 상위 클래스에 근거하여 새롭게 클래스와 행위를 정의할 수 있게 도와주는 개념이다.</p>
</li>
<li><p>기존 클래스에 기능을 가져와 재사용할 수 있으면서도 동시에 새롭게 만든 클래스에 새로운 기능을 추가 할 수 있게 만들어준다.</p>
</li>
<li><p>** 필요한 이유**
: 코드의 중복을 막을 수 있어서 코드가 더 간단해지므로 유지보수가 수월해지기 때문이다.</p>
</li>
</ul>
<blockquote>
<p>** 📁 다형성(Polymorphism) 📁**</p>
</blockquote>
<ul>
<li><p>다형성은 상속을 통해 기능을 확장하거나 변경하는 것을 가능하게 해준다.</p>
</li>
<li><p>코드의 재사용, 유지보수가 용이하도록 도와준다.</p>
</li>
<li><p><em>예시)*</em> 사자는 고양이과인데 고양이 class를 사자 class에서 상속 받는다고 하면, 사자 class에도 고양이 class 안에 있는 속성들을 상속받는다. 하지만, 고양이의 특징과 사자의 특징은 다르다. 이러한 것을 다형성이라고 한다.</p>
</li>
<li><p><strong>overriding(오버라이딩)</strong>
: 부모클래스에서 상속받은 자식클래스에서 부모클래스에 있는 메소드를 다시 재 정의해서 사용하는 것을 의미한다.</p>
</li>
<li><p><strong>overloading(오버로딩)</strong>
: 같은 이름의 메소들를 사용하지만 메소드마다 다른 용도로 사용되며, 그 결과물도 다르게 구현할 수 있게 만드는 개념이다.</p>
</li>
<li><p><strong>다형성의 장점</strong>
: 같은 이름의 속성을 유지함으로서, 속성을 사용하기 위한 인터페이스를 유지하고, 메소드 이름을 낭비하지 않는다는 것이다.</p>
</li>
</ul>
<hr>
<p><strong>[ 참고한 블로그 ]</strong>
<a href="https://velog.io/@zzangzzong/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8DObject-Oriented-Programming#-%EC%83%81%EC%86%8Dinheritance">https://velog.io/@zzangzzong/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8DObject-Oriented-Programming#-%EC%83%81%EC%86%8Dinheritance</a></p>
]]></description>
        </item>
    </channel>
</rss>