<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jionee</title>
        <link>https://velog.io/</link>
        <description>👩🏻‍💻 글을 쉽고 재미있게 전달하고 싶은 모바일 앱 개발자입니다.</description>
        <lastBuildDate>Sat, 03 Jan 2026 21:14:39 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jionee</title>
            <url>https://velog.velcdn.com/images/dev_jiwon/profile/e5b46fde-0d2c-423b-b582-7d4b239b02bb/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jionee. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dev_jiwon" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[React Native] New Architecture 이해하기 - 3. Hermes]]></title>
            <link>https://velog.io/@dev_jiwon/React-Native-New-Architecture-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-3.-Hermes</link>
            <guid>https://velog.io/@dev_jiwon/React-Native-New-Architecture-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-3.-Hermes</guid>
            <pubDate>Sat, 03 Jan 2026 21:14:39 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요오<del>~</del>😆😆 오랜만에 포스팅으로 찾아뵙습니다...! 😅</p>
<p><a href="https://velog.io/@dev_jiwon/React-Native-New-Architecture-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-2.-JSI">지난 시간</a>에는 새로운 아키텍처의 구성요소 중 하나인 <code>JSI</code>를 배웠습니다. 제 개인적인 생각으로는 <code>JSI</code>가 새로운 아키텍처의 🌸(꽃)이라고 생각합니다. 그래서 내용도 다소 길었습니다. 😅</p>
<br>

<p>오늘은 새로운 아키텍처의 다른 구성요소인, JavaScript 엔진 <code>Hermes</code>에 대해 알아보도록 하겠습니다!! +_+</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/7604c89d-70c5-47eb-8246-cddcfb340d32/image.png" width="30%" /> 

<p><br><br></p>
<h2 id="hermes-도입-배경">Hermes 도입 배경</h2>
<p>기존 React Native는 <code>JSC</code>(JavaScriptCore)를 기본 JavaScript 엔진으로 사용해 왔습니다. 이 구조에서는 앱 실행 시점에 JavaScript 코드가 해석되고 네이티브 모듈이 초기화되기 때문에, 메모리 사용량이 증가하고 초기 로딩 성능에 한계가 있었습니다. React Native 0.64에서는 위 성능 개선을 목표로 한 새로운 JavaScript 엔진인 <code>Hermes</code>가 도입되었습니다. <code>Hermes</code>가 도입된 이후, React Native 개발자 커뮤니티에서 성능 향상 측면에 대해 큰 지지를 받았습니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/99cb53aa-e710-4dd9-8123-215d66b8116d/image.png" width="30%" />


<p><br><br></p>
<h2 id="hermes-작동-흐름">Hermes 작동 흐름</h2>
<h3 id="1-빌드-타임">1. 빌드 타임</h3>
<p><a href="https://velog.io/@dev_jiwon/React-Native-New-Architecture-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-0.-%EB%AF%B8%EB%A6%AC-%EB%B3%B4%EA%B8%B0#%EC%83%88%EB%A1%9C%EC%9A%B4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EC%9D%98-%EB%8F%99%EC%9E%91-%ED%9D%90%EB%A6%84-%EA%B0%84%EB%8B%A8%ED%95%9C-%EA%B0%9C%EC%9A%94">새로운 아키텍처의 흐름</a>에 의하면 <code>Hermes</code>는 앱 빌드 타임에 실행되는 주요 구성 요소 중 하나입니다.</p>
<p>기존 <code>JSC</code> 엔진은 런타임에 JavaScript 코드를 실행할 때, &quot;파싱 → 컴파일&quot;하는 과정이 필요했습니다. 이로인해 앱 시작 시 JavaScript 실행 준비 과정에서 지연이 생겨 초기 로딩 성능에 한계가 있었습니다.</p>
<p>이를 해결하기 위해 <code>Hermes</code>는 빌드 타임에 JavaScript 소스 코드를 미리 바이트 코드로 변환합니다. 바이트 코드 파일은 <code>Hermes</code>가 해석하거나 다시 컴파일할 필요 없이 직접 실행할 수 있는 더 간단하고 효율적인 코드 형식입니다. 이 바이트코드는 런타임에 훨씬 더 빠르게 로드될 수 있어, 애플리케이션의 시작 시간을 단축시킵니다.</p>
<blockquote>
<p>바이트 코드: 고급 언어로 작성된 소스 코드를 가상머신이 이해할 수 있도록 변환한 중간 코드</p>
</blockquote>
<p>빌드 타임에는... <code>Codegen</code>도 열심히 네이티브 모듈을 생성한다는 사실...! 
잊지 않으셨죠??! 😆</p>
<br>

<h3 id="2-런타임">2. 런타임</h3>
<p>앱을 실행하면 미리 생성된 바이트 코드 파일을 로드하는 것부터 시작합니다. 앞서 설명한 것처럼 <code>Hermes</code>는 빌드 타임에 이미 소스 코드를 파싱하고 컴파일해두었기 때문에, 앱 시작 속도가 훨씬 빨라집니다.</p>
<p><code>Hermes</code>는 이전 시간에 배운 <code>JSI</code>를 사용해 브릿지를 사용하지 않고 네이티브 함수와 객체에 직접 접근 할 수 있습니다. 주로 API를 통해 데이터를 가져오거나 상태를 업데이트하고, 사용자 입력에 응답하는 등 앱의 로직과 데이터, 이벤트 처리를 담당합니다. 또한, 새로운 렌더링 시스템인 <code>Fabric</code>을 사용하여 UI를 업데이트 할 수 있습니다. 
(<code>Fabric</code>에 대한 자세한 내용은 다다음 시간에 살펴보겠습니다! 🤩)</p>
<p><br><br></p>
<h2 id="hermes-장점">Hermes 장점</h2>
<p><code>Hermes</code>는 앱 시작 속도 뿐만 아니라 앱 번들 크기와 메모리 사용량도 최적화합니다. Meta에서는 <code>JSC</code>와 <code>Hermes</code>를 직접 비교했으며, <a href="https://reactnative.dev/blog/2022/07/08/hermes-as-the-default#benchmarking">이 벤치마킹 데이터</a>를 바탕으로 <code>Hermes</code>의 장점을 소개하겠습니다!</p>
<br>

<h3 id="1-tti-단축">1. TTI 단축</h3>
<p>TTI(Time to Interactive)는 앱이 실행된 시점부터 사용자가 앱과 상호 작용할 수 있는 시점까지의 시간입니다.
런타임에 JavaScript를 파싱하고 해석하는 것은 느리고 리소스를 많이 소모합니다. <code>Hermes</code>는 빌드 단계에서 JavaScript를 바이트코드로 사전 컴파일하기 때문에 TTI를 단축시켜 원활한 사용자 경험을 제공합니다.</p>
<br>

<h3 id="2-메모리-사용률-감소">2. 메모리 사용률 감소</h3>
<p>메모리 사용량은 앱을 실행할 때 사용되는 메모리 크기입니다.
<code>Hermes</code> 엔진은 모든 코드를 빌드타임에 컴파일한 뒤, 런타임에는 메모리에 저장된 코드를 실행시키기만 하면 되기 때문에, 런타임에 활발하게 컴파일러가 돌아가며, 수시로 메모리 읽고 쓰기를 반복하는 <code>JSC</code> 대비 메모리 사용량이 더 적습니다. 또한 <code>Hermes</code> 엔진에서는 새로운 가비지 컬렉터인 Hades가 적용되었는데, 앱의 원활한 구동에 실제로 필요한 메모리만을 사용하도록 하여 메모리 사용량을 최적화 되었습니다.</p>
<br>

<h3 id="3-바이너리-크기-감소">3. 바이너리 크기 감소</h3>
<p>바이너리 크기는 APK(안드로이드) 또는 IPA(iOS) 파일에 포함된 React Native 애플리케이션의 크기입니다.
압축된 javascript code보다 압축된 byte code의 사이즈가 약간 더 크긴하지만 hermes의 native code size는 기존 javascriptCore engine size보다 작아졌기 때문에 전체 앱 사이즈는 더 작아진다고 합니다.
(😎: 다만 이는 js engine을 앱 번들에 포함시키는 android 한정이고, javascriptCore를 포함할 필요 없었던 ios입장에서는 오히려 앱 사이즈가 약간 더 커진다고 합니다.)</p>
<p><br><br></p>
<h2 id="마무리">마무리</h2>
<blockquote>
<p><strong>Hermes는 결국...</strong></p>
</blockquote>
<ul>
<li>빌드 타임에 JS 코드를 바이트코드로 사전 컴파일을 하여,</li>
<li>런타임에 앱 시작 속도 단축과 바이너리 크기를 감소시켜 JSC를 보완할 수 있게 되었습니다! 👏👏!!</li>
</ul>
<br>

<img src="https://velog.velcdn.com/images/dev_jiwon/post/9c2ca70f-31cd-4ec0-93c6-a763cf8bb1b2/image.png" width="40%"/>


<p>그러니 Hermes 비싸도 뭐라 하지 않긔...!⭐️ </p>
<p><br><br></p>
<p>다음 포스팅에서는 새로운 아키텍처의 다른 구성 요소인 <code>Turbo Module</code>에 대해 알아보겠습니다!</p>
<p>그럼 다음 포스팅에서 만나요~~ 🥹👋</p>
<p><br><br><br><br></p>
<p>참고</p>
<p><a href="https://github.com/anisurrahman072/React-Native-Advanced-Guide/blob/master/New-Architecture/New-Architecture-in-depth.md#hermes-engine">https://github.com/anisurrahman072/React-Native-Advanced-Guide/blob/master/New-Architecture/New-Architecture-in-depth.md#hermes-engine</a></p>
<p><a href="https://reactnative.dev/blog/2022/07/08/hermes-as-the-default#benchmarking">https://reactnative.dev/blog/2022/07/08/hermes-as-the-default#benchmarking</a></p>
<p><a href="https://medium.com/crossplatformkorea/hermes-%EC%97%94%EC%A7%84%EC%9D%B4%EB%9E%80-cbeb953e0f10">https://medium.com/crossplatformkorea/hermes-%EC%97%94%EC%A7%84%EC%9D%B4%EB%9E%80-cbeb953e0f10</a></p>
<p><a href="https://velog.io/@2ast/React-Native-Hermes-engine">https://velog.io/@2ast/React-Native-Hermes-engine</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React Native] New Architecture 이해하기 - 2. JSI]]></title>
            <link>https://velog.io/@dev_jiwon/React-Native-New-Architecture-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-2.-JSI</link>
            <guid>https://velog.io/@dev_jiwon/React-Native-New-Architecture-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-2.-JSI</guid>
            <pubDate>Sun, 04 May 2025 14:12:32 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요<del>~</del> ☺️👋 벌써 React Native New Architecture 3번째 시간입니다.
오늘은 새로운 아키텍처의 핵심 구성 요소라고 할 수 있는 <code>JSI</code>에 대해 포스팅해보려 합니다! 
(<code>Codegen</code>은 <a href="https://velog.io/@dev_jiwon/React-Native-New-Architecture-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-1.-Codegen">이전 포스팅</a>을 참고해주세요.)</p>
<p>새로운 아키텍처를 이해할 때 가장 중요한 포인트는 <strong>JavaScript와 네이티브가 어떻게 연결되는가?</strong> 입니다.</p>
<p><code>JSI</code>는 JavaScript와 네이티브를 연결해주는 인터페이스로, 구 아키텍처의 브릿지 역할을 대체하기 위해 ☄️혜성같이☄️ 등장했습니다. <code>JSI</code>가 무엇이고, 어떻게 기존 브릿지의 역할을 대체하는지 자세히 알아봅시다! 👀</p>
<p><br><br></p>
<h2 id="jsi가-뭔데">JSI가 뭔데?</h2>
<h3 id="1-jsi-정의">1. JSI 정의</h3>
<p><code>JSI</code>(JavaScript Interface)는 기존 아키텍처의 브릿지를 대체하여 JavaScript와 네이티브를 <strong>직접 연결</strong>할 수 있도록 해주는 C++ 기반 인터페이스입니다. <code>JSI</code>는 C++ 힙 메모리에 직접 생성되며, <code>JavaScript</code> 엔진은 이 객체에 대한 포인터를 가지게 됩니다. 이로 인해 <code>JavaScript</code>와 네이티브 코드가 <strong>서로의 메모리 공간을 공유</strong>하게 되어 자바스크립트와 네이티브 간의 경계가 없어질 수 있게 됩니다.</p>
<h3 id="2-jsi를-기반으로-동작하는-핵심-구성-요소들">2. JSI를 기반으로 동작하는 핵심 구성 요소들</h3>
<p><code>JSI</code>를 통해 아래의 구성 요소들이 <code>JavaScript</code>와 직접 연결됩니다.</p>
<p><strong>1. Hermes 엔진</strong>
<code>Hermes</code>는 기기에서 <code>JavaScript</code> 코드를 실행하는 <code>JavaScript</code> 엔진이며, <code>JSI</code>를 통해 네이티브 코드와 직접 연결됩니다. <code>JSI</code>는 런타임에 접근할 수 있는 인터페이스를 제공하여, <code>JavaScript</code>에서 네이티브 함수나 객체를 직접 호출할 수 있게 합니다.</p>
<p><strong>2. Turbo Module</strong>
<code>TurboModule</code>은 <code>JSI</code>를 통해 <code>JavaScript</code>에서 브릿지 없이 네이티브 메서드를 호출할 수 있도록 구현되어 있습니다.</p>
<p><strong>3. Fabric</strong>
<code>Fabric</code>은 <code>JSI</code>를 기반으로 <code>JavaScript</code>와 네이티브 UI 렌더러를 연결하는 새로운 렌더링 엔진입니다.</p>
<p>(위 구성 요소들에 대해서는 다음 포스팅에서 자세히 살펴볼 예정 입니다! 🤩)</p>
<p><br><br></p>
<h2 id="jsi는-네이티브-메서드를-어떻게-호출할까">JSI는 네이티브 메서드를 어떻게 호출할까?</h2>
<h3 id="1-hostobject를-통한-네이티브-메서드-접근">1. HostObject를 통한 네이티브 메서드 접근</h3>
<p><code>JSI</code>를 통해 네이티브 메서드는 C++ 객체 형태로 <code>JavaScript</code>에 노출되며, JavaScript 코드에서 이를 참조하고 직접 호출할 수 있습니다. 이때 노출된 C++ 객체를 <code>HostObject</code> 라고 부릅니다. <code>HostObject</code>는 <code>JSI</code>에서 매우 중요한 개념으로, 런타임에 등록된 구현체가 <code>JavaScript</code> 코드 내에서 직접 참조될 수 있고, <code>JavaScript</code> 코드는 네이티브 메서드를 마치 자체 메서드처럼 호출할 수 있습니다.
(이는 마치 웹에서 JavaScript가 모든 DOM 요소를 참조하고, 해당 메서드를 호출하는 방식과 유사합니다. 🙂)</p>
<br>

<h3 id="2-javascript에서-네이티브-모듈을-호출하기까지">2. JavaScript에서 네이티브 모듈을 호출하기까지</h3>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/1f97beab-46e4-4e21-a911-45429c3eb0fd/image.png"/>

<p><strong>1. 앱 시작 시, Codegen은 모듈의 인터페이스를 정의</strong>
<a href="https://velog.io/@dev_jiwon/React-Native-New-Architecture-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-1.-Codegen#2-c-%EC%A4%91%EA%B0%84-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-glue-code-%EC%83%9D%EC%84%B1">이전 포스팅</a> 내용을 잠깐 복습하자면, <code>Codegen</code>은 빌드 과정에서 모듈의 C++ 기반 인터페이스를 생성합니다. <code>JSI</code>는 이 인터페이스를 기준으로 어떤 모듈을 찾아야 하는지, 어떤 메서드를 호출해야하는지 알 수 있습니다. 이 인터페이스 정의가 없다면, <code>JSI</code>는 필요한 모듈을 알 수 없습니다. 😭😭</p>
<p><strong>2. JavaScript에서 모듈 호출</strong>
새로운 아키텍처에서는 <code>Turbo Module</code>을 사용하여 네이티브 모듈을 구현합니다. <code>JavaScript</code>에서 이 모듈을 호출할 때, <code>JSI</code>는 가장 먼저 <code>Codegen</code>이 정의한 인터페이스를 참조합니다. 최초 호출인 경우 해당 모듈이 로드되어 있지 않으므로, <code>JSI</code>는 모듈을 동적으로 로드하고 초기화한 뒤 호출합니다. 이미 로드된 경우는 모듈을 바로 호출합니다.</p>
<p><br><br></p>
<h2 id="jsi의-특징">JSI의 특징</h2>
<p><code>JSI</code>에는 다음과 같은 특징이 있어, 여러가지 이점을 가져다줍니다. 대표적으로 세가지 특징을 설명드리겠습니다!🥹</p>
<ul>
<li><p><strong>동시성</strong> : <code>JavaScript</code>는 UI 스레드에서 실행되는 함수를 직접 호출할 수 있습니다.</p>
</li>
<li><p><strong>오버헤드 감소</strong> : 새로운 아키텍처는 더 이상 데이터를 직렬화하거나 역직렬화할 필요가 없으므로 직렬화로 인한 추가 비용이 발생하지 않습니다.</p>
</li>
<li><p><strong>동기 방식</strong> : <code>JSI</code>는 비동기/동기 방식을 모두 지원하지만, 비동기적으로 실행 되어서는 안 되는 함수들은 동기적으로 실행할 수 있습니다.</p>
</li>
</ul>
<p>제가 그중에서도 가장 강조하고 싶은 특징이 세번째 특징인 동기 방식 부분인데요, <code>JSI</code>의 동기 방식이 어떤 이점을 가져왔는지 자세히 알아봅시다!! 😎</p>
<h3 id="jsi는-동기적으로도-실행될-거라구우">JSI는 동기적으로도 실행될 거라구우!</h3>
<p>비동기 호출은 UI 스레드나 JavaScript 스레드를 차단하지 않기 때문에 대부분의 경우 여전히 선호됩니다. 하지만 다음과 같은 상황에서는 동기 호출이 유익할 수 있습니다.</p>
<ul>
<li><p><strong>네이티브 모듈 초기화</strong>
일부 네이티브 모듈은 사용하기 전에 초기화해야 하는데, 비동기적으로 초기화할 경우 지연이나 충돌이 발생할 수 있습니다. <code>JSI</code>를 사용하면 네이티브 모듈을 동기적으로 초기화하여 이러한 문제를 방지할 수 있습니다.</p>
</li>
<li><p><strong>상수 접근</strong>
일부 네이티브 모듈은 장치 정보나 플랫폼별 값과 같이 JavaScript 코드에서 사용되는 상수를 노출합니다. (ex. OS, 장치 이름, 앱 버전 등등..) <code>JSI</code>를 사용하면 이러한 상수에 브릿지 메시지를 기다릴 필요 없이 <code>JavaScript</code>에서 동기적으로 접근할 수 있습니다.</p>
</li>
<li><p><strong>동기식 네이티브 메서드 호출</strong>
일부 네이티브 메서드는 클립보드 접근이나 현재 위치 가져오기처럼 JavaScript 코드에 값을 즉시 반환해야 합니다. <code>JSI</code>를 사용하면 콜백이나 프로미스를 사용하지 않고도 이러한 메서드를 <code>JavaScript</code>에서 동기적으로 호출할 수 있습니다.</p>
</li>
</ul>
<p><br><br></p>
<h2 id="마무리">마무리</h2>
<p><code>Bridge</code>의 비효율적인 통신 한계를 해결하기 위해 ☄️혜성같이☄️ 등장한 우리 <code>JSI</code>...! 
<code>Bridge</code>와 <code>JSI</code>를 한 눈에 비교해보며...  <code>Bridge</code>를 이제 그만 보내주도록 하겠습니다...🥹🥹 </p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/4ccd889f-7d78-4395-83b4-615752517b59/image.png" width="30%"/>


<br>

<table>
<thead>
<tr>
<th>구분</th>
<th><strong>Bridge</strong></th>
<th><strong>JSI</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>모듈 등록 시점</strong></td>
<td>앱 구동 시, <code>ReactPackage</code> 목록을 통해 Java/ObjC 모듈을 한 번에 등록</td>
<td>앱 실행 시, C++ 객체를 JS 런타임(globalThis)에 직접 주입</td>
</tr>
<tr>
<td><strong>데이터 전달 방식</strong></td>
<td>JS ↔ Bridge 간 <strong>JSON 직렬화/역직렬화</strong></td>
<td>JS ↔ C++ 간 <strong>메모리 직접 접근 (함수 포인터 호출)</strong></td>
</tr>
<tr>
<td><strong>호출 타이밍</strong></td>
<td>비동기 (Bridge 메시지 큐 통해 전달)</td>
<td>동기/비동기 모두 가능 (C++ 런타임에서 직접 실행)</td>
</tr>
<tr>
<td><strong>핵심 특징</strong></td>
<td><strong>모듈을 미리 다 등록해두고 이름으로 호출</strong></td>
<td><strong>런타임에 직접 바인딩하고 바로 실행</strong></td>
</tr>
</tbody></table>
<br>

<p><code>Bridge</code> 방식은 이제 안녕 👋
<code>JSI</code>는 브릿지를 대체하기에 매우 적절!! +_+</p>
<p>다음 포스팅에서는 새로운 아키텍처의 다른 구성 요소인 <code>Hermes</code> 엔진에 대해 알아보겠습니다!</p>
<p>그럼 <a href="https://velog.io/@dev_jiwon/React-Native-New-Architecture-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-3.-Hermes-%EC%97%94%EC%A7%84">다음 포스팅</a>에서 만나요~~ 🥹👋 </p>
<p><br><br></p>
<p>참고</p>
<p><a href="https://github.com/anisurrahman072/React-Native-Advanced-Guide/blob/master/New-Architecture/New-Architecture-in-depth.md#jsi-javascript-interface">https://github.com/anisurrahman072/React-Native-Advanced-Guide/blob/master/New-Architecture/New-Architecture-in-depth.md#jsi-javascript-interface</a></p>
<p><a href="https://medium.com/mj-studio/react-native-new-architecture-guide-9fd045438530">https://medium.com/mj-studio/react-native-new-architecture-guide-9fd045438530</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React Native] New Architecture 이해하기 - 1. Codegen]]></title>
            <link>https://velog.io/@dev_jiwon/React-Native-New-Architecture-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-1.-Codegen</link>
            <guid>https://velog.io/@dev_jiwon/React-Native-New-Architecture-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-1.-Codegen</guid>
            <pubDate>Sat, 03 May 2025 20:54:15 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요!!!! 😆 😆 <a href="https://velog.io/@dev_jiwon/React-Native-New-Architecture-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-0.-%EB%AF%B8%EB%A6%AC-%EB%B3%B4%EA%B8%B0">지난 포스팅</a>에서 React Native New Architecture에 대한 대략적인 개요에 대해 알아보았는데요~ 제가 너무 큰 틀만 써서, 잘 이해가 되지 않았을 수도 있습니다. 이번 포스팅 부터는 새로운 아키텍처에서 등장한 모든 구성 요소를 함께 살펴볼 예정입니다. 오늘은 그 중에서도 첫번째 구성 요소인 <code>Codegen</code>에 대해 자세히 파헤쳐 볼 예정입니다! +_+</p>
<p>그럼 바로 시작해봅시다~!</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/664382bf-c06d-4614-a4d8-fc443f4936e9/image.png" width="60%" />

<p><br><br></p>
<h2 id="codegen이란">Codegen이란?</h2>
<p><img src="https://velog.velcdn.com/images/dev_jiwon/post/d20c60c8-1c88-4859-9d34-921d295303d3/image.png" alt=""></p>
<p><code>Codegen</code>은 <strong>정적 타입 검사기</strong>이자, JavaScript 코드를 Native 코드로 자동으로 생성해주는 <strong>네이티브 코드 생성기</strong>입니다. (말 그대로 Code generator! 🤩) </p>
<p>새로운 아키텍처에서는 구 아키텍처의 브릿지의 역할을 <code>JSI</code>라는 것이 대신합니다. <code>JSI</code>는 정적 타입 언어인 C++로 작성되어있어 컴파일할 때 타입이 명확해야하지만, JavaScript는 동적 타입 언어이므로 런타임 때 타입이 결정됩니다. 서로 타입을 해석하는 시점이 다르기 때문에, JavaScript와 C++ 간에는 타입 불일치, 잘못된 값 전달 등의 통신 문제가 발생할 수 있습니다.</p>
<p><code>Codegen</code>은 이러한 문제를 방지하기 위해 도입되었습니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/75912cae-de00-4bb2-845c-ba62c5fe088e/image.png" width="40%"/>

<br>

<h2 id="codegen-역할">Codegen 역할</h2>
<p><code>Codegen</code>은 앱 빌드 시에 JavaScript와 Native 모듈 통신을 위한 <strong>C++ 중간 인터페이스 코드(glue code)</strong>를 자동으로 생성합니다. C++로 생성하기 위해 타입을 빌드 타임에 미리 정적으로 검사해, 실행 중 발생할 수 있는 오류를 사전에 방지합니다.</p>
<br>

<h3 id="1-정적-타입-검사">1. 정적 타입 검사</h3>
<p>프로젝트 내부에는 모듈이 정의된 파일들이 존재하는데요, <code>Codegen</code>은 앱을 빌드할 때 이들 중에서 <code>TurboModule</code>을 확장한 파일만을 찾습니다. 이러한 파일들은 <code>Codegen</code>을 대상으로한 모듈 정의 파일입니다.</p>
<p>Codegen 대상 정의 파일 예시:</p>
<pre><code class="language-ts">// NativeCalculator.ts
import { TurboModuleRegistry }, type { TurboModule } from &#39;react-native&#39;;

// 타입 정의
export interface Spec extends TurboModule {
  add(a: number, b: number): number;
}

// Calculator의 이름을 가진 모듈 등록
export default TurboModuleRegistry.getEnforcing&lt;Spec&gt;(&#39;Calculator&#39;);</code></pre>
<p>위 정의 파일의 타입을 다음과 같은 표로 정의할 수 있습니다.</p>
<table>
<thead>
<tr>
<th>항목</th>
<th>값</th>
</tr>
</thead>
<tbody><tr>
<td>함수 이름</td>
<td><code>add</code></td>
</tr>
<tr>
<td>인자 목록</td>
<td><code>a: number</code>, <code>b: number</code></td>
</tr>
<tr>
<td>반환 타입</td>
<td><code>number</code></td>
</tr>
</tbody></table>
<br>

<blockquote>
<p>👶🏻: 만약 정의 파일이 타입이 없는 <code>.js</code> 파일이라면...?
😎: JavaScript는 타입 정보를 명시하지 않기 때문에, 단순한 <code>.js</code> 파일만 사용할 경우 <code>Codegen</code>은 정확한 타입을 추론할 수 없습니다.
그 결과, C++ 인터페이스를 제대로 생성하지 못해 빌드를 실패하거나, 해당 파일이 Codegen 대상에서 아예 무시될 수 있습니다.
=&gt; 모듈 정의 파일은 <code>Native&lt;ModuleName&gt;.ts</code> 또는 <code>.js</code> + <code>Flow</code> 타입 사용이 권장됩니다.</p>
</blockquote>
<blockquote>
<p>👶🏻: 만약 정의 파일에 문법 혹은 타입 오류가 있다면...? 
😎: <code>Codegen</code> 실행 중에 바로 에러를 발생시켜 빌드를 실패하게 됩니다.</p>
</blockquote>
<br>

<h3 id="2-c-중간-인터페이스-glue-code-생성">2. C++ 중간 인터페이스 (Glue Code) 생성</h3>
<p><code>Codegen</code>이 모듈 정의 파일에 문제가 없음을 확인하면, JavaScript와 Native 간 통신을 중계할 <strong>C++ 중간 인터페이스(Glue Code)</strong>를 생성합니다.</p>
<p>예를 들어, 위 정의 파일에 있던 add 함수는 다음과 같은 형태로 변환됩니다:</p>
<pre><code class="language-c">// NativeCalculatorSpec.h

#pragma once

#include &lt;jsi/jsi.h&gt;
#include &lt;ReactCommon/TurboModule.h&gt;

namespace facebook::react {
  class JSI_EXPORT NativeCalculatorSpec : public TurboModule {
  public:
    NativeCalculatorSpec(std::shared_ptr&lt;CallInvoker&gt; jsInvoker)
        : TurboModule(&quot;Calculator&quot;, jsInvoker) {}

    virtual double add(double a, double b) = 0;
  };
} // namespace facebook::react</code></pre>
<br>

<h3 id="3-네이티브-코드-생성">3. 네이티브 코드 생성</h3>
<p><code>Codegen</code>은 새로운 아키텍처의 두 가지 핵심 구성 요소인 <code>TurboModule</code>과 <code>Fabric</code>을 위한 Native 코드를 자동으로 생성합니다. 이 두 구성 요소는 모두 <code>Codegen</code>이 생성한 Native 코드 없이는 제대로 동작할 수 없습니다. <code>Codegen</code>은 네이티브 구현부의 로직을 대신 짜주진 않지만, 그 로직을 작성할 수 있도록 하는 <strong>틀</strong>(인터페이스, 바인딩 구조 등)을 자동으로 설계해줍니다. </p>
<p><code>Codegen</code>을 사용하는 이점은 네이티브 모듈과 구성 요소를 만들고 유지 관리하는 데 필요한 작업량을 줄여준다는 것입니다. 🤩</p>
<h4 id="android-java">Android (Java)</h4>
<pre><code class="language-java">// CalculatorModule.java

package com.yourapp;

import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import com.facebook.react.bridge.ReactApplicationContext;

public class CalculatorModule extends NativeCalculatorSpec {
  public CalculatorModule(ReactApplicationContext reactContext) {
    super(reactContext);
  }

  @Override
  public double add(double a, double b) {
    // TODO 개발자가 직접 작성
  }
}</code></pre>
<h4 id="ios-objective-c">iOS (Objective-C++)</h4>
<pre><code class="language-swift">// Calculator.mm

#import &quot;NativeCalculatorSpec.h&quot;

using namespace facebook;

@interface Calculator : NSObject &lt;NativeCalculatorSpec&gt;
@end

@implementation Calculator

- (double)add:(double)a b:(double)b {
    // TODO 개발자가 직접 작성
}

@end</code></pre>
<p>이렇게 생성된 네이티브 코드의 틀은 이제 브릿지를 거치지 않고도 JavaScript (with Flow) 혹은 TypeScript 와 직접 통신할 수 있게 됩니다. 결과적으로 <code>Codegen</code>은 브릿지를 제거함으로써, JavaScript와 네이티브 코드 간 통신을 더 빠르고 안정적으로 만들어줍니다.</p>
<br>

<h2 id="마무리">마무리</h2>
<blockquote>
<h4 id="codegen은-결국">Codegen은 결국...</h4>
</blockquote>
<ul>
<li><strong>JSI</strong>를 위해 타입 안정성을 확보하고,</li>
<li><strong>TurboModule</strong>과 <strong>Fabric</strong>을 위해 네이티브 코드를 자동으로 생성합니다.</li>
</ul>
<p>그렇다면, 왜 이 모든 작업을 빌드 시점에 미리 수행할까요? 🤔</p>
<p>기존의 구 아키텍처에서는 브릿지를 통해 런타임마다 데이터를 직렬화·역직렬화해야 했기 때문에, 요청이 많아질수록 병목 현상이 쉽게 발생하는 구조였습니다.</p>
<p>반면, <code>Codegen</code>은 빌드 시점에 모든 JS ↔ Native 연결을 정적으로 고정하고, 필요한 네이티브 코드를 미리 생성해두기 때문에, 런타임에는 <code>JSI</code>가 직접 메모리 주소를 참조해 빠르게 함수를 호출할 수 있게 됩니다.</p>
<p>이처럼 <code>Codegen</code>의 전 과정을 거치면, 성공적으로 빌드를 완료하게 되며 앱 실행 준비를 마치게 됩니다! +_+ 🎉</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/c26a7c17-5479-4800-915f-027e0c47c02b/image.png" width="60%" />

<p><br><br></p>
<p>다음에는 런타임 시 어떤 과정이 이루어지는지 알아볼텐데요,
바로 <a href="https://velog.io/@dev_jiwon/React-Native-New-Architecture-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-2.-JSI">다음 포스팅</a>에서 위에서 계속 언급되는 <code>JSI</code>에 대해 파악해보는 시간을 가져보겠습니다. </p>
<p>그럼 다음 포스팅에서 만나요~~ 🥹👋</p>
<p><br><br></p>
<p>참고
<a href="https://reactnative.dev/docs/the-new-architecture/what-is-codegen">https://reactnative.dev/docs/the-new-architecture/what-is-codegen</a></p>
<p><a href="https://github.com/anisurrahman072/React-Native-Advanced-Guide/blob/master/New-Architecture/New-Architecture-in-depth.md#new-architecture-of-react-native-quick-overview">https://github.com/anisurrahman072/React-Native-Advanced-Guide/blob/master/New-Architecture/New-Architecture-in-depth.md#new-architecture-of-react-native-quick-overview</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React Native] New Architecture 이해하기 - 0.  미리 보기]]></title>
            <link>https://velog.io/@dev_jiwon/React-Native-New-Architecture-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-0.-%EB%AF%B8%EB%A6%AC-%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@dev_jiwon/React-Native-New-Architecture-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-0.-%EB%AF%B8%EB%A6%AC-%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Thu, 01 May 2025 17:06:10 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요<del>~</del> 🥹🥹 React Native의 새로운 아키텍처에 대해 아시나요? 이번 주제는 React Native 새로운 아키텍처 입니다. 이 주제는 6챕터로 예상하고 있고, 6챕터 같이 잘 마무리 하여 React Native에 대해 조금은 심층적으로 알아가는 시간이 되었으면 좋겠습니다!! 🤩</p>
<p>제가 작년에 구 아키텍처에 대해 <a href="https://velog.io/@dev_jiwon/React-Native-%EB%B8%8C%EB%A6%BF%EC%A7%80-%EB%B0%A9%EC%8B%9D-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC">포스팅</a>을 했었는데요, 오늘은 구 아키텍쳐를 복습할 겸 간단하게 한번 더 짚어보고, 새로운 아키텍처가 나온 배경 및 간단한 흐름까지 간단하게만(?) 알아보겠습니다. (오늘은 일단 가벼운 입문 느낌...!)</p>
<br>

<h4 id="react-native-구-아키텍처-요약">React Native 구 아키텍처 요약</h4>
<p>React Native가 현재 0.79 버전까지 출시되었습니다. 0.67 버전까지는 구 아키텍처를 기반으로 동작했는데요, 먼저 구 아키텍처가 어떻게 작동했는지 간단하게 알아봅시다! 😎😎</p>
<p>기존 아키텍처에서는 React Native와 Native 간의 통신이 <strong>브릿지</strong>를 통해 이루어졌습니다. 이 브릿지는 JSON을 기반으로 데이터를 주고받는 구조입니다. React Native에서 Native 기능을 호출할 때, 해당 명령을 JSON 형식으로 직렬화하여 Native로 전송하고, Native는 이 요청을 처리한 뒤 결과를 다시 JSON으로 직렬화해 React Native에 응답합니다. JSON은 단순성과 가독성 때문에 선택되었지만, 가벼운 형식임에도 불구하고 비용이 발생합니다. </p>
<blockquote>
<p>React Native → Native: 명령을 JSON으로 직렬화해서 보냄
Native → React Native: 결과를 JSON으로 직렬화해서 보내고, React Native 쪽에서 역직렬화하여 사용</p>
</blockquote>
<p>React Native는 기본적으로 JavaScript 기반으로 동작하기 때문에, Native를 거쳐 다시 React Native로 돌아오는 구조는 피할 수 없습니다. 하지만 호출해야 할 명령이 많아질수록, 매번 수행되는 직렬화와 역직렬화 작업은 점점 더 큰 성능 비용을 초래하게 됩니다. 특히 Native 측에 요청해야 할 작업이 많아지면, 브릿지에서 병목현상이 발생해 UI가 멈추거나 지연되는 등 예기치 못한 사용자 경험 저하로 이어질 수 있습니다.</p>
<br>

<p>그렇다면...!!</p>
<p>👶🏻 : 직렬화 및 역직렬화 없이 React Native에서 바로 Native의 기능을 요청할 순 없을까?</p>
<p>바로 그 해답으로...!! 메타(Meta)에서는 React Native 0.68 버전부터 <strong>새로운 아키텍처(New Architecture)</strong> 를 공식적으로 도입하게 됩니다. +_+ (박수 짝짝 👏👏)</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/87392361-f6db-4741-9012-9508216c995c/image.png" width="50%" />

<p><br><br></p>
<p>메타(Meta)는 기존 아키텍처에서 가장 큰 성능 병목이었던 직렬화 과정을 근본적으로 해결하기로 하였습니다. 새로운 아키텍처에서는 기존의 브릿지 방식을 과감히 제거하고, 직렬화 없이도 Native 기능을 직접 호출할 수 있도록 하는 구조를 도입하였습니다. </p>
<p>👶🏻 :  그렇다면 브릿지의 역할을 어떻게 대신하려는거지?</p>
<p>이 때...! <strong>JSI(JavaScript Interface)</strong>라는 것이 등장합니다. 🤩 🤩</p>
<p>(JSI?? 아 JSA밖에 모른다고요 ㅋㅋㅋ)</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/73c8a025-2fa8-4687-bcd8-5f81164e5edb/image.png" width="40%" />

<br>

<p>JSI는 기존 브릿지를 대체하기 위해 등장한 새로운 인터페이스로, JSI를 통하면 직렬화 과정 없이 React Native와 Native 간의 통신이 가능해집니다. 하지만 이 JSI 홀로 그 통신 과정을 모두 수행할 수 있는 것은 아닙니다. JSI와 함께 도입된 여러 새로운 구성 요소들이 있는데요, 바로 알아봅시다. 🥹</p>
<br>

<h2 id="새로운-아키텍처의-모든-구성-요소">새로운 아키텍처의 모든 구성 요소</h2>
<p>새로운 아키텍처에 도입된 모든 구성 요소를 한번 쓱(SSG)- 살펴보겠습니다!! 😆😆</p>
<ul>
<li><strong>Codegen (네이티브 코드 생성기)</strong></li>
<li><strong>JSI (자바스크립트 인터페이스)</strong></li>
<li><strong>Hermes Engine (새로운 JS 엔진)</strong></li>
<li><strong>Turbo 모듈 (JSI 및 네이티브 코드를 사용한 네이티브 모듈)</strong></li>
<li><strong>Fabric (네이티브 UI 렌더러 / 새로운 렌더 엔진)</strong></li>
<li><strong>Fabric 렌더러 (새로운 렌더 파이프라인 생성기)</strong></li>
<li><strong>Yoga (크로스 플랫폼 레이아웃 엔진. 구 아키텍처에도 있었음)</strong></li>
</ul>
<p>다 너무 중요해서 별표 5개! ⭐️⭐️⭐️⭐️⭐️</p>
<br>

<h2 id="새로운-아키텍처의-동작-흐름-간단한-개요">새로운 아키텍처의 동작 흐름 (간단한 개요)</h2>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/0318b53a-fd3b-462a-a88b-1642b33dda8a/image.png" width="100%"/>

<p>React Native 0.68 버전부터는 개발자가 새로운 아키텍처 사용 여부를 직접 선택할 수 있게 되었습니다. 만약 새로운 아키텍처를 활성화한 상태에서, 프로덕션 배포를 위한 Android용 APK 또는 iOS용 IPA 빌드 명령을 실행하면, 새 아키텍처 흐름에 따라 다음 단계들이 수행됩니다.</p>
<h3 id="1단계-앱-빌드-시간">1단계: 앱 빌드 시간</h3>
<p>앱 빌드 시간에 실행되는 주요 구성 요소는 <strong>Hermes Engine</strong>과 <strong>Codegen</strong> 입니다.</p>
<ol>
<li><p><strong>Hermes Engine</strong>
먼저, 앱은 앱의 JavaScript 코드가 포함된 바이트코드 파일을 로드하는 것으로 시작합니다.
(*바이트코드: 고급 언어로 작성된 소스 코드를 가상머신이 이해할 수 있는 중간 코드로 컴파일한 것)</p>
<p>이 바이트코드 파일은 Android 기기와 iOS 기기에서 실행되는 JavaScript 엔진인 Hermes 에서 직접 실행할 수 있는 더 간단하고 효율적인 코드입니다. </p>
<p>👶🏻 : 빌드 시간에 바이트코드로 변환하면 뭐가 좋은건데?</p>
<p>원래는 앱이 실행될 때 JavaScript 코드를 JavaScript 엔진이 &quot;파싱 → 컴파일 → 실행&quot;하는 과정을 거쳐야 했습니다. 하지만 빌드 타임에 미리 바이트코드로 변환해두면, &quot;파싱 → 컴파일&quot; 과정을 건너뛰고 바로 앱을 실행할 수 있어서 앱 시작 속도가 훨씬 빨라집니다. 빌드 타임에 <code>.js</code> → <code>.hbc(Hermes Bytecode)</code>로 변환되며, 이는 APK/IPA에 포함됩니다. </p>
<p>Hermes는 앱 크기, 메모리 사용량, 그리고 앱 시작 시간을 개선합니다.</p>
</li>
</ol>
<br>

<ol start="2">
<li><strong>Codegen</strong>
Codegen은 <strong>앱 빌드 시에만</strong> 작동하는 자동 코드 생성기로, 빌드 시간 동안 네이티브 코드를 생성합니다. JavaScript와 Native 간의 안전한 연결을 위해 필요한 네이티브 코드를 이 시점에 생성하며, TurboModule이나 Fabric 컴포넌트가 제대로 동작하도록 기반을 마련합니다.</li>
</ol>
<br>

<h3 id="2단계-앱-런타임">2단계: 앱 런타임</h3>
<p>사용자가 앱을 실행하면, 그 이후의 작업은 React Native의 새로운 아키텍처 흐름에 따라 처리됩니다. 앱이 기기에서 실행되는 시점인 런타임 단계에서는 다음과 같은 주요 구성 요소들이 동작하게 됩니다.</p>
<h4 id="런타임의-핵심-구성-요소">런타임의 핵심 구성 요소</h4>
<ol>
<li><p><strong>TurboModule</strong>
Turbo Module은 JavaScript에서 액세스할 수 있는 네이티브 모듈을 생성하는 새로운 방식 입니다. <strong>Turbo Module은 브릿지를 사용하지 않고 JSI를 사용하여 JavaScript 코드와 통신합니다.</strong> 앱의 네이티브 모듈은 이제 Turbo Module을 사용하여 구현됩니다. 네이티브 모듈의 성능과 안정성을 향상시키고 개발 및 유지 관리를 간소화할 수 있습니다.</p>
</li>
<li><p><strong>Fabric</strong>
React Native의 새로운 UI 렌더링 시스템으로, React 컴포넌트를 네이티브 코드로 변환합니다. Fabric은 Yoga 라는 라이브러리를 사용하여 사용자 인터페이스 요소의 레이아웃 (위치, 크기, 정렬 등)을 계산하며, Fabric Renderer를 통해 React reconciliation 결과를 실제 네이티브 뷰에 렌더링 합니다. Fabric은 또한 브릿지 없이 JSI를 사용하여 JavaScript 및 네이티브 코드와 통신하므로, TTI(Time To Interactive)를 향상시키고 네이티브 기능과의 통합을 한층 강화합니다.</p>
</li>
</ol>
<h4 id="하위-구성-요소">하위 구성 요소</h4>
<p>이 외에도, 아래와 같은 하위 구성 요소들이 함께 작동합니다.</p>
<ol>
<li><p><strong>Hermes Engine</strong>
JSC를 대신하여 등장한 새로운 JavaScript 엔진으로, 빠른 실행과 낮은 메모리 사용이 강점입니다.</p>
</li>
<li><p><strong>JSI (JavaScript Interface)</strong>
JSI는 브릿지를 대체하여 등장한 구성요소로, JavaScript와 Native 간 직접 통신을 가능하게 해주는 핵심 인터페이스 입니다. JSI는 앱의 성능과 상호 운용성을 향상시키고 브릿지로는 불가능한 새로운 기능을 지원합니다.</p>
</li>
</ol>
<p><br><br></p>
<p>새로운 아키텍처의 전반적인 흐름에 대해 훑어보았는데요 👀, 오늘은 미리보기 시간이므로 대략적인 파악만 하시고, &#39;아 이런게 있구나<del>&#39; 하고 넘어가셔도 좋을 것 같습니다. 앞으로 구성 요소들에 대해 깊게 파헤쳐 보는 시간을 가져볼거거든요</del> 😉 (윙꾸) 그럼 다음 포스팅에서는 Codegen에 대해 알아보겠습니다. <a href="https://velog.io/@dev_jiwon/React-Native-New-Architecture-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-1.-Codegen">다음 포스팅</a>에서 만나요. 👋👋</p>
<p><br><br></p>
<p>참고
<a href="https://github.com/anisurrahman072/React-Native-Advanced-Guide/blob/master/New-Architecture/New-Architecture-in-depth.md#new-architecture-of-react-native-quick-overview">https://github.com/anisurrahman072/React-Native-Advanced-Guide/blob/master/New-Architecture/New-Architecture-in-depth.md#new-architecture-of-react-native-quick-overview</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 이벤트 루프? 그게 뭔데,,, 그거 어떻게 하는건데,,,⭐️]]></title>
            <link>https://velog.io/@dev_jiwon/JavaScript-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84-%EA%B7%B8%EA%B2%8C-%EB%AD%94%EB%8D%B0-%EA%B7%B8%EA%B1%B0-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%98%EB%8A%94%EA%B1%B4%EB%8D%B0</link>
            <guid>https://velog.io/@dev_jiwon/JavaScript-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84-%EA%B7%B8%EA%B2%8C-%EB%AD%94%EB%8D%B0-%EA%B7%B8%EA%B1%B0-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%98%EB%8A%94%EA%B1%B4%EB%8D%B0</guid>
            <pubDate>Mon, 17 Mar 2025 19:56:04 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요~ 😎👋 오늘은 자바스크립트의 동작 원리에 대해 포스팅 하려고 합니다!
자바스크립트 포스팅은 처음 써보는 것 같네요.</p>
<p>그동안 자바스크립트에 대한 깊은 이해도 없이 무작정 개발만 해왔다는게 많이 느껴지고 있는 요즘입니다. 연차가 쌓이면서 이제 웬만한 기능 구현은 할 줄 알지만, 여전히 근본적인 이해가 부족한 제 모습에 모순을 느끼고 있습니다. 이런 괴리감 있는 제 모습을 n년 전부터 느끼긴 했지만 이제야 괴리감 좁히기를 시도해보려 합니다...</p>
<p>뭐... 그래도... 원래는 공부의 필요성만 느끼고 공부하지 않았는데, 이제는 모르는 게 느껴지면 몸소 반응해 공부하는 걸 보니 마음 가짐은 확실히 성장한 것 같네요. </p>
<p>.
.
.</p>
<p>서론을 거의 뭐 일기처럼 주저리 주저리 써내려갔는데... 😅😅</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/7b58aebb-4964-4801-9a68-43f18d36ba0b/image.png" width="50%" />

<br>

<p>일기는 이쯤에서 멈추고...!</p>
<p>제가 이번에 공부한 자바스크립트의 동작 원리에 대해 포스팅하며, 저도 같이 복기해보려 합니다. 😤 ‼️</p>
<br>

<p>자 그럼 시작...! (엄근진)</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/59dbb894-1af3-4ec9-b8db-eb873ad4444b/image.png" width="50%" />

<p><br><br></p>
<h2 id="스레드">스레드</h2>
<p>자바스크립트는 싱글 스레드로 동작하는 언어입니다.
싱글 스레드 이전에 스레드가 무엇일까요? 스레드에 대해 간단하게 짚고 넘어가겠습니다!</p>
<blockquote>
<p>스레드: 프로세스 안에서 실제로 실행되는 작업의 흐름
프로세스: 하나의 앱이나 프로그램이 실행되는 단위
ex) 크롬 웹 브라우저(=프로세스)를 틀어 한 탭에선 유튜브 뮤직으로 음악 듣기(=스레드1)와 다른 탭에선 구글링 하기(=스레드2)</p>
</blockquote>
<br>

<h3 id="멀티-스레드">멀티 스레드</h3>
<p>위의 예시처럼 크롬 웹 브라우저에서는 한 탭에선 음악을 틀을 수 있고, 동시에 다른 탭에선 음악을 들으며 구글링이 가능합니다. 이는 각 탭이 별도의 스레드로 동작하기 때문입니다. 이렇게 하나의 <strong>프로세스 안에서 여러 스레드가 동시에 실행되는 환경</strong>을 <strong>멀티 스레드</strong>라고 합니다.
멀티 스레드를 적극 활용하는 언어에는 Java, C++, C#, Kotlin, Swift, Objective-C 등이 있습니다.</p>
<p><em>(오늘은 자바스크립트에 대해 알아보는 시간이니, 멀티 스레드는 이쯤에서 멈추고 싱글 스레드로 바로 넘어가봅시다!)</em></p>
<h3 id="싱글-스레드">싱글 스레드</h3>
<p><strong>싱글 스레드</strong>란 <strong>하나의 프로세스 내에서 하나의 스레드만 실행되는 환경</strong>입니다. 즉, 이 경우 프로세스는 한 번에 하나의 작업만 수행할 수 있습니다.
싱글 스레드를 적극 활용하는 언어에는 JavaScript, Python, Ruby, PHP 등이 있습니다.</p>
<blockquote>
<p>😎 : 자바스크립트는 기본적으로 싱글 스레드로 동작하지만, 여러 작업을 동시에 처리하는 것처럼 실행할 수 있습니다.</p>
</blockquote>
<p>자바스크립트에서 여러 작업을 동시에 처리하도록 하는 것이 <code>이벤트 루프</code>와 <code>비동기 프로그래밍</code> 덕분인데...</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/6c4561b0-a5a0-4724-b81c-9a7cb94de925/image.png" width="60%" />

<p>비동기 프로그래밍 방식을 이해하기 위해선 먼저 동기/비동기 프로그래밍 방식의 차이부터 알 필요가 있습니다.</p>
<p><br><br></p>
<h2 id="동기-프로그래밍">동기 프로그래밍</h2>
<p>아래의 코드가 있습니다. 실행하면 어떤 결과가 나올까요?</p>
<pre><code class="language-js">console.log(1)
console.log(2)
console.log(3)</code></pre>
<p>1 -&gt; 2 -&gt; 3 이렇게 위에서부터 아래로 순차적으로 출력됩니다.</p>
<pre><code>1
2
3</code></pre><p><code>console.log(1)</code>이 출력될 때까지 <code>console.log(2)</code>는 기다리고, <code>console.log(2)</code>가 출력될 때까지 <code>console.log(3)</code>도 기다립니다.</p>
<p>이렇게 작업이 하나씩 순차적으로 진행되며, 이전 작업이 끝난 후에 다음 작업이 시작되는 방식을 <strong>동기 프로그래밍(Synchronous Programming)</strong>이라고 합니다.</p>
<p>자바스크립트는 기본적으로 동기 프로그래밍 방식으로 동작합니다.</p>
<p><br><br></p>
<h2 id="비동기-프로그래밍">비동기 프로그래밍</h2>
<p>그렇다면, 아래 코드는 실행하면 어떤 결과가 나올까요?</p>
<pre><code class="language-js">console.log(1)
setTimeout(() =&gt; console.log(2), 0)
console.log(3)</code></pre>
<p>두둥-! 아래와 같이 출력됩니다.</p>
<pre><code>1
3
2</code></pre><p><code>setTimeout</code>이 0초인데도 <code>console.log(2)</code>보다 <code>console.log(3)</code>이 먼저 실행된 걸 볼 수 있습니다.</p>
<p>이렇게 즉시 수행할 수 있는 작업은 먼저 실행하고, 시간이 오래 걸리는 작업은 나중에 처리하는 방식을 <strong>비동기 프로그래밍(Asynchronous Programming)</strong>이라고 합니다.</p>
<p>이러한 비동기 프로그래밍을 가능하게 해주는 것이 바로 <strong>이벤트 루프(Event Loop)</strong> 입니다!
그렇다면, 이벤트 루프는 어떻게 이러한 과정을 처리할까요? 함께 알아봅시다! ✊🏻
(위 예시 풀이 대공개 예정 +_+)</p>
<p><br><br></p>
<h2 id="이벤트-루프">이벤트 루프</h2>
<blockquote>
<p>(재차 강조) 
⭐️ 자바스크립트는 싱글 스레드 기반으로 동작하기 때문에, 기본적으로 한 번에 하나의 작업만 실행할 수 있습니다. ⭐️ </p>
</blockquote>
<p>자바스크립트에서 작업이 실행되는 공간을 <strong>Call Stack</strong>이라고 하며, 이 곳에서는 한 번에 하나의 작업만 처리할 수 있습니다. <code>setTimeout</code>이나 <code>fetch</code> 같은 비동기 작업은 <strong>Call Stack</strong> 영역이 아닌 <strong>Web API</strong> 영역에서 처리됩니다. <strong>Web API</strong> 영역에서 작업을 실행한 결과는 <strong>Queue</strong>라는 대기열에 들어가게 됩니다.</p>
<p><strong>이벤트 루프</strong>는 <strong>Call Stack</strong>이 비었을 때 <strong>Queue</strong>에 있는 작업을 <strong>Call Stack</strong>으로 이동시킵니다. 쉽게 말해, 이벤트 루프는 지금 실행할 수 있는 작업이 있는지 확인하고, 실행할 작업이 없으면 <strong>Queue</strong>에 대기 중인 작업을 실행하는 일련의 처리 과정을 뜻합니다.</p>
<p>흠 조금 어려운데...🤔
위 설명을 아까의 예시 코드와 함께 차근차근 알아보겠습니다. 🤩</p>
<pre><code class="language-js">console.log(1)
setTimeout(() =&gt; console.log(2), 0)
console.log(3)</code></pre>
<ol>
<li><code>console.log(1)</code>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/48beedd3-9997-431e-973c-d9722c845e13/image.png" width="90%" /><code>console.log(1)</code>은 작업이 실행될 공간인 <strong>Call Stack</strong> 영역에 들어가게 됩니다.</li>
</ol>
<p><strong>Call Stack</strong>에 작업이 들어오면 자바스크립트 엔진에 의해 해당 작업을 실행하게 됩니다.</p>
<br>

<ol start="2">
<li><code>setTimeout(() =&gt; console.log(2), 0)</code>
<img 
src="https://velog.velcdn.com/images/dev_jiwon/post/eec3a655-2d8f-4ddb-bb09-8396b250b764/image.png" width="90%" /><strong>Call Stack</strong>에 있던 1번 작업이 수행되었습니다. 
그리고 2번 작업이 <strong>Web API</strong> 영역으로 넘어갔습니다. 이 작업의 콜백은 0초 뒤 <strong>Queue</strong>로 이동할 예정입니다.</li>
</ol>
<ol start="3">
<li><code>console.log(3)</code>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/47304a3b-9952-46c0-84e8-b6680cbda4ac/image.png" width="90%" /><strong>Call Stack</strong> 영역이 비어있기 때문에, 3번 작업이 바로 <strong>Call Stack</strong>에 들어갑니다.
이 과정에서 타이머가 끝나 2번 작업의 콜백이 <strong>Queue</strong>로 이동합니다.
<img src="https://velog.velcdn.com/images/dev_jiwon/post/84129273-e9b7-46c4-8568-bf297ec8cbfb/image.png" width="90%" /><strong>Call Stack</strong> 영역에 있던 <code>console.log(3)</code>을 수행 하면 </li>
</ol>
<p><strong>&quot;딸깍‼️&quot;</strong> 이벤트 루프에 의해 <code>console.log(2)</code>가 <strong>Call Stack</strong> 영역으로 이동하게 됩니다.
<img src="https://velog.velcdn.com/images/dev_jiwon/post/e900d3ed-e9d6-4a53-824b-02c9c1d226ef/image.png" width="90%" />마지막 작업인 <code>console.log(3)</code>까지 수행하게 되어 <strong>Call Stack</strong> 영역이 완죠니 비워졌습니다! +_+</p>
<br>

<p>이렇게 이벤트 루프의 전반적인 과정을 살펴보았습니다. (훗훗 내 자신 칭찬해 😎)</p>
<p><br><br></p>
<h2 id="task-queue--microtask-queue">Task Queue &lt; Microtask Queue</h2>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/11d54c3a-de82-4979-9668-8a86e325edd4/image.png" width="50%" />

<p><strong>Web API</strong>에서 비동기 작업이 수행된 후, 모두 <strong>Queue</strong>의 영역으로 들어가게 되는데 <strong>Queue</strong> 영역 내 작업 중에서도 우선순위가 나뉘어집니다. </p>
<p><strong>Queue</strong>는 <strong>Task Queue</strong>와 <strong>Microtask Queue</strong>로 나눌 수 있습니다.</p>
<blockquote>
<ul>
<li>Task Queue : 일반적인 비동기 작업들이 들어가는 대기열
ex) <code>setTimeout</code>, <code>setInterval</code>, 사용자 이벤트 등</li>
</ul>
</blockquote>
<ul>
<li>Microtask Queue: 더 높은 우선순위를 가진 작업들이 들어가는 대기열
ex) <code>Promise</code>의 <code>then</code>, <code>catch</code>, <code>finally</code> 핸들러, <code>MutationObserver</code> 등</li>
</ul>
<p><strong>Microtask Queue는 Task Queue보다 우선적으로 처리됩니다.</strong></p>
<h3 id="예제">예제</h3>
<p>간단한 예제를 볼까요? 아래의 코드를 실행하면 어떻게 될까요?</p>
<pre><code class="language-js">console.log(1)

setTimeout(() =&gt; console.log(2), 0)

fetch(&#39;~&#39;).then(() =&gt; console.log(3))</code></pre>
<p>두둥-! 아래와 같이 출력됩니다.</p>
<pre><code>1
3
2</code></pre><p>위 과정 또한 그림으로 같이 알아보겠습니다! ☺️</p>
<ol>
<li><code>console.log(1)</code>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/d9776a08-8b0c-4a38-9754-3acfc865123d/image.png" width="90%" /><code>console.log(1)</code>은 작업이 실행될 공간인 <strong>Call Stack</strong> 영역에 들어가게 됩니다.</li>
</ol>
<p><strong>Call Stack</strong>에 작업이 들어오면 자바스크립트 엔진에 의해 해당 작업을 실행하게 됩니다.</p>
<ol start="2">
<li><code>setTimeout(() =&gt; console.log(2), 0)</code>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/08ba23ad-45c4-4f1d-a1d7-15d315abfe4d/image.png" width="90%" /><strong>Call Stack</strong>에 있던 1번 작업이 수행되었습니다.
그리고 2번 작업이 <strong>Web API</strong> 영역으로 넘어갔습니다. 이 작업의 콜백은 0초 뒤 <strong>Task Queue</strong>로 이동할 예정입니다.</li>
</ol>
<ol start="3">
<li><code>fetch(&#39;~&#39;).then(() =&gt; console.log(3))</code>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/42c08640-5659-49fd-a6f6-42ff29bc1e01/image.png" width="90%" />3번 작업이 <strong>Web API</strong> 영역으로 넘어갔습니다.
이 과정에서 타이머가 끝나 2번 작업의 콜백이 <strong>Task Queue</strong> 영역으로 이동합니다.
<img src="https://velog.velcdn.com/images/dev_jiwon/post/edbb415b-e1b4-47a6-9728-537bacfc5b35/image.png" width="90%" />현재 <strong>Call Stack</strong> 영역이 비어있기 때문에, 실행할 작업을 <strong>Call Stack</strong> 영역에 넣어줘야 합니다. 실행할 작업들은 모두 Queue에 있고, 우선순위는 <strong>Microtask Queue</strong>가 더 높습니다. <strong>Microtask Queue</strong> 영역에 있는 <code>console.log(3)</code>이 바로 <strong>Call Stack</strong> 영역으로 이동할 예정입니다!
<img src="https://velog.velcdn.com/images/dev_jiwon/post/0ab337e1-0190-467e-ab1e-61a46621bdde/image.png" width="90%" /><strong>&quot;딸깍‼️&quot;</strong> 이벤트 루프에 의해 <code>console.log(3)</code>이 <strong>Call Stack</strong> 영역으로 이동하였습니다.
<img src="https://velog.velcdn.com/images/dev_jiwon/post/85cd9c1f-d8c4-414a-9cdf-74ae67472364/image.png" width="90%" /><strong>Call Stack</strong>에 있던 <code>console.log(3)</code>이 수행되었습니다.</li>
</ol>
<p><strong>&quot;딸깍‼️&quot;</strong> 이벤트 루프에 의해 <code>console.log(2)</code>가 <strong>Call Stack</strong> 영역으로 이동하였습니다.
<img src="https://velog.velcdn.com/images/dev_jiwon/post/64974afc-bc67-4682-a59e-e37e42b340e4/image.png" width="90%" />마지막 작업인 <code>console.log(2)</code>까지 수행하게 되어 <strong>Call Stack</strong> 영역이 완죠니 비워졌습니다! +_+</p>
<p><br><br></p>
<h3 id="심화-예제">심화 예제</h3>
<p>어떠셨는지요...🥹🥹 
삘 받았을 때 더 전진해야하기 때문에 나름의 심화 예제(?)를 한번 같이 풀어보겠습니다!</p>
<p>아래의 코드를 실행하면 어떤 결과가 나올까요?</p>
<pre><code class="language-js">console.log(1)

setTimeout(() =&gt; {
  console.log(2)
}, 0)

Promise.resolve().then(() =&gt; {
  setTimeout(() =&gt; {
    console.log(3)
  }, 0)
  console.log(4)
  setTimeout(() =&gt; {
    console.log(5)
  }, 0)
})

console.log(6)</code></pre>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/53e21d22-0a9c-4e67-9675-2b5a61c51368/image.png" width="30%" />

<p>너무나도 복잡한데요,,, but 차근차근 하면 못할 것이 없습니다! 😤</p>
<p>렛츠고도리...!</p>
<ol>
<li><code>console.log(1)</code>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/7a0a0e56-14c6-4065-ab54-e36560b141a8/image.png" width="90%" /><code>console.log(1)</code>은 작업이 실행될 공간인 <strong>Call Stack</strong> 영역에 들어가게 됩니다.</li>
</ol>
<p><strong>Call Stack</strong>에 작업이 들어오면 자바스크립트 엔진에 의해 해당 작업을 실행하게 됩니다.</p>
<ol start="2">
<li><code>setTimeout(() =&gt; {
console.log(2)
}, 0)</code>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/6a8e7df6-0328-45ef-a46e-15473912c84b/image.png" width="90%" /><strong>Call Stack</strong>에 있던 1번 작업이 수행되었습니다. 
그리고 2번 작업이 <strong>Web API</strong> 영역으로 넘어갔습니다. 이 작업의 콜백은 0초 뒤 <strong>Task Queue</strong>로 이동할 예정입니다.
<img src="https://velog.velcdn.com/images/dev_jiwon/post/ee10bed7-38c2-44b9-b921-9a79572a91a1/image.png" width="90%" />현재 <strong>Call Stack</strong> 영역이 비어있기 때문에, 실행할 작업을 <strong>Call Stack</strong> 영역에 넣어줘야 합니다. 처리하기 가장 빠른 <code>console.log(6)</code> 작업이 바로 <strong>Call Stack</strong>에 들어갑니다.
이 과정에서 타이머가 끝나 2번 작업의 콜백이 <strong>Task Queue</strong>로 이동합니다.</li>
</ol>
<ol start="3">
<li><code>Promise.resolve().then(() =&gt; {
setTimeout(() =&gt; {
 console.log(3)
}, 0)
console.log(4)
setTimeout(() =&gt; {
 console.log(5)
}, 0)
})</code>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/eb50e0ee-d726-486f-b178-01ab72fe048c/image.png" width="90%" /><strong>Call Stack</strong>에 있던 <code>console.log(6)</code> 작업이 수행되었습니다.
그리고 3번 작업이 <strong>Web API</strong> 영역으로 넘어갔습니다. 이 작업의 콜백은 <code>resolve</code> 후, <strong>Microtask Queue</strong>로 이동할 예정입니다.
<img src="https://velog.velcdn.com/images/dev_jiwon/post/8509d0c0-d90c-4b6b-8e9e-b5e78321d40e/image.png" width="90%" /><code>resolve</code> 후, <strong>Microtask Queue</strong> 영역에 있는 함수들은 각각 각자에 맞는 영역으로 찢어져야합니다...😭😭
<code>setTimeout(() =&gt; {
 console.log(3)
}, 0)</code>, <code>setTimeout(() =&gt; {
 console.log(5)
}, 0)</code>는 비동기 작업이므로 <strong>Web API</strong>로 이동하고,     <code>console.log(4)</code>는 비어있는 <strong>Call Stack</strong> 영역으로 이동할 예정입니다.
<img src="https://velog.velcdn.com/images/dev_jiwon/post/ddd93197-66e9-48cf-a2f6-827b7a44481f/image.png" width="90%" />각자에 맞는 위치로 흩어졌습니다...!
<code>console.log(4)</code>가 <strong>Call Stack</strong> 영역에 이동하였습니다.
<strong>Web API</strong>에 있는 작업들은 먼저 작업 들어온 순서대로 작업하여 <strong>Task Queue</strong>로 이동할 예정입니다.
<img src="https://velog.velcdn.com/images/dev_jiwon/post/d63e9e7d-852c-4cc2-b840-41614bb01b73/image.png" width="90%" /><strong>Call Stack</strong>에 있던 <code>console.log(4)</code> 작업이 수행되었습니다.</li>
</ol>
<p><strong>Web API</strong>에 있던 작업들도 순서대로 <strong>Task Queue</strong>에 이동하였습니다.
<img src="https://velog.velcdn.com/images/dev_jiwon/post/96d92e48-1fca-4ad1-8344-a8f94dba50e3/image.png" width="90%" /><strong>&quot;딸깍‼️&quot;</strong> 이벤트 루프에 의해 <code>console.log(2)</code>가 <strong>Call Stack</strong> 영역으로 이동하였습니다.
<img src="https://velog.velcdn.com/images/dev_jiwon/post/e9d089c1-4199-49ca-b224-a876eafdb929/image.png" width="90%" /><strong>Call Stack</strong>에 있던 <code>console.log(2)</code>가 수행되었습니다.
<strong>&quot;딸깍‼️&quot;</strong> 이벤트 루프에 의해 <code>console.log(3)</code>이 <strong>Call Stack</strong> 영역으로 이동하였습니다.
<img src="https://velog.velcdn.com/images/dev_jiwon/post/3f1b2b1e-8e68-43d8-b20b-6b35d3e65275/image.png" width="90%" /><strong>Call Stack</strong>에 있던 <code>console.log(3)</code>이 수행되었습니다.
<strong>&quot;딸깍‼️&quot;</strong> 이벤트 루프에 의해 <code>console.log(5)</code>가 <strong>Call Stack</strong> 영역으로 이동하였습니다.
<img src="https://velog.velcdn.com/images/dev_jiwon/post/e0892a26-a85e-4682-a67b-5e77362fa1b1/image.png" width="90%" />마지막 작업인 <code>console.log(5)</code>까지 수행하게 되어 <strong>Call Stack</strong> 영역이 완죠니 비워졌습니다! +_+</p>
<ol start="4">
<li><code>console.log(6)</code>
<del>(2번 과정에서 실행 완료)</del></li>
</ol>
<p><br><br></p>
<h2 id="마무리">마무리</h2>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/9660d64b-8cf4-4905-b687-b0eb16a87f57/image.png" width="50%" />
끄흐흡...! 드디어 ... 잘 수 있다...!(?)

<p>늘 블로그를 쓸 때마다 초보자에게 가르친다는 생각으로 엄청 자세히 쓰려고 노력하는데, 이번에도 제 최선을 다 한 것 같습니다... 🫠</p>
<p>다른 블로그들과 차별점을 두기 위해 글도 일부러 지루하지 않게 쓰려 하고, 그림 자료도 직접 ⭐️수제⭐️로 만들어가며 포스팅을 하느라 시간이 배로 걸리네요. 누군가 제 블로그를 통해 조금이라도 도움을 받았다면 너무 너무 만족할 것 같습니다...😭😭</p>
<p>앞으로도 저만의 특색 있는 블로그를 운영하기 위해 제 S.t.y.l.e.을 밀고 나가겠습니다.^^</p>
<p>그럼 다음 포스팅에서 만나요~👋👋</p>
<br>

<h2 id="참고">참고</h2>
<p><a href="https://www.youtube.com/watch?v=v67LloZ1ieI">https://www.youtube.com/watch?v=v67LloZ1ieI</a></p>
<p><a href="https://velog.io/@gil0127/%EC%8B%B1%EA%B8%80%EC%8A%A4%EB%A0%88%EB%93%9CSingle-thread-vs-%EB%A9%80%ED%8B%B0%EC%8A%A4%EB%A0%88%EB%93%9C-Multi-thread-t5gv4udj#%EC%8A%A4%EB%A0%88%EB%93%9C%EC%9D%B4%EB%9E%80--thread-">https://velog.io/@gil0127/%EC%8B%B1%EA%B8%80%EC%8A%A4%EB%A0%88%EB%93%9CSingle-thread-vs-%EB%A9%80%ED%8B%B0%EC%8A%A4%EB%A0%88%EB%93%9C-Multi-thread-t5gv4udj#%EC%8A%A4%EB%A0%88%EB%93%9C%EC%9D%B4%EB%9E%80--thread-</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React Native 라이브러리 이해하기 - 3. 라이브러리 모듈을 이해하자 (⭐️ 최종 ⭐️)]]></title>
            <link>https://velog.io/@dev_jiwon/React-Native-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-3.-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EB%AA%A8%EB%93%88%EC%9D%84-%EC%9D%B4%ED%95%B4%ED%95%98%EC%9E%90-%EC%B5%9C%EC%A2%85</link>
            <guid>https://velog.io/@dev_jiwon/React-Native-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-3.-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EB%AA%A8%EB%93%88%EC%9D%84-%EC%9D%B4%ED%95%B4%ED%95%98%EC%9E%90-%EC%B5%9C%EC%A2%85</guid>
            <pubDate>Sat, 01 Feb 2025 11:52:00 GMT</pubDate>
            <description><![CDATA[<p>오와... <a href="https://velog.io/@dev_jiwon/React-Native-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0-2.-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EA%B5%AC%EC%A1%B0%EB%A5%BC-%EC%9D%B4%ED%95%B4%ED%95%98%EC%9E%90">지난 포스팅</a>에서 라이브러리 구조에 대해 이해해보았는데요, 너무 어려웠습니다.
작성하다가 🥲 살짝 눈물이 고일 것 같아... 포스팅을 나눠 작성하기로 하였습니다!!</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/c64bc087-a657-4bb1-a074-bfc2cfd2d9c0/image.png" width="40%" />


<p>이번 포스팅에서는 React Native 앱 구동 이후, 모듈이 등록되는 과정 및 모듈과 앱 간 상호작용에 대해 이해해보겠습니다! +_+</p>
<p><em>(이번 포스팅은 <a href="https://velog.io/@dev_jiwon/React-Native-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0-2.-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EA%B5%AC%EC%A1%B0%EB%A5%BC-%EC%9D%B4%ED%95%B4%ED%95%98%EC%9E%90">이전 포스팅</a>의 코드를 기반으로 작성되었습니다. 코드 복습도 되고 일석이조? 😎)</em></p>
<p><br><br></p>
<h2 id="모듈-등록-과정-이해하기">모듈 등록 과정 이해하기</h2>
<p>먼저 라이브러리 모듈을 React Native 애플리케이션에 등록하는 과정에 대해 이해해봅시다.</p>
<h3 id="1-애플리케이션-구동">1. 애플리케이션 구동</h3>
<p>React Native 애플리케이션이 시작되면, JavaScript 엔진이 초기화되고, JavaScript 코드가 실행됩니다. 
(이 부분은 추후에 React Native New Architecture 포스팅에서 다루겠습니다.)</p>
<br>

<h3 id="2-네이티브-모듈-정의">2. 네이티브 모듈 정의</h3>
<p>React Native에서 필요한 모듈을 정의합니다.</p>
<h4 id="android">Android</h4>
<p>TestLibraryModule 파일에서 TestLibraryModule 클래스가 정의됩니다.</p>
<pre><code class="language-kotlin">@ReactModule(name = TestLibraryModule.NAME)
class TestLibraryModule(reactContext: ReactApplicationContext) :
  NativeTestLibrarySpec(reactContext) {

  ...

}</code></pre>
<h4 id="ios">iOS</h4>
<p>TestLibrary.h 파일에서 TestLibrary 클래스의 인터페이스가 정의됩니다. TestLibrary.mm 파일에서 TestLibrary 클래스의 구현이 정의됩니다.</p>
<pre><code class="language-swift">@interface TestLibrary : NSObject &lt;NativeTestLibrarySpec&gt;</code></pre>
<br>

<h3 id="3-모듈-등록">3. 모듈 등록</h3>
<p>아래 과정을 통해 React Native는 TestLibrary 모듈을 인식하고, JavaScript 코드에서 사용할 수 있게 됩니다.</p>
<h4 id="android-1">Android</h4>
<p>TestLibraryPackage 파일에서 TestLibraryModule이 React Native에 등록됩니다.</p>
<pre><code class="language-kotlin">class TestLibraryPackage : BaseReactPackage() {
  ...

  override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
    return ReactModuleInfoProvider {
      val moduleInfos: MutableMap&lt;String, ReactModuleInfo&gt; = HashMap()
      moduleInfos[TestLibraryModule.NAME] = ReactModuleInfo(
        TestLibraryModule.NAME,
        TestLibraryModule.NAME,
        false,  // canOverrideExistingModule
        false,  // needsEagerInit
        true,  // hasConstants
        false,  // isCxxModule
        true // isTurboModule
      )
      moduleInfos
    }
  }
}</code></pre>
<h4 id="ios-1">iOS</h4>
<p>TestLibrary.mm 파일에서 <code>RCT_EXPORT_MODULE()</code> 매크로를 사용하여 TestLibrary 모듈이 React Native에 등록됩니다.</p>
<pre><code class="language-swift">RCT_EXPORT_MODULE()</code></pre>
<br>

<h3 id="4-javascript-코드에서-호출할-메서드-구현">4. JavaScript 코드에서 호출할 메서드 구현</h3>
<p><code>JavaScript</code> 코드에서 호출할 메서드를 구현합니다.</p>
<h4 id="android-2">Android</h4>
<p>TestLibraryModule 파일에서 구현합니다.</p>
<pre><code class="language-kotlin">override fun multiply(a: Double, b: Double): Double {
    return a * b
}</code></pre>
<h4 id="ios-2">iOS</h4>
<p>TestLibrary.mm 파일에서 구현합니다.</p>
<pre><code class="language-swift">- (NSNumber *)multiply:(double)a b:(double)b {
    NSNumber *result = @(a * b);

    return result;
}</code></pre>
<br>

<h3 id="5-turbomodule-초기화-및-반환">5. TurboModule 초기화 및 반환</h3>
<p>라이브러리 프로젝트를 생성할 때 Turbo 모듈 옵션을 선택했다면, 네이티브 코드에서 <code>TurboModule</code>을 초기화 합니다. <code>TurboModule</code>은 <code>JavaScript</code>와 네이티브 코드 간의 상호 작용을 효율적으로 처리합니다.</p>
<h4 id="android-3">Android</h4>
<p>TestLibraryPackage 파일에서 <code>TurboModule</code> 정보를 제공하여 초기화하고 반환합니다.</p>
<pre><code class="language-kotlin"> override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
    return ReactModuleInfoProvider {
      val moduleInfos: MutableMap&lt;String, ReactModuleInfo&gt; = HashMap()
      moduleInfos[TestLibraryModule.NAME] = ReactModuleInfo(
        ...,
        true // isTurboModule (TurboModule 여부)
      )
      moduleInfos
    }
  }
</code></pre>
<h4 id="ios-3">iOS</h4>
<p>TestLibrary.mm 파일에서 getTurboModule 메서드가 구현되어 <code>TurboModule</code>을 초기화하고 반환합니다.</p>
<pre><code class="language-swift">- (std::shared_ptr&lt;facebook::react::TurboModule&gt;)getTurboModule:
    (const facebook::react::ObjCTurboModule::InitParams &amp;)params
{
    return std::make_shared&lt;facebook::react::NativeTestLibrarySpecJSI&gt;(params);
}</code></pre>
<p><br><br></p>
<h2 id="모듈과-앱-간-상호작용-이해하기">모듈과 앱 간 상호작용 이해하기</h2>
<p>자자... 모듈 등록 과정은 이해했으니, 
이제 React Native 애플리케이션에서 모듈을 호출했을 때 모듈과 앱이 어떻게 상호작용 하는지 알아봅시다!!! 🤩 🤩</p>
<p>(React Native 라이브러리 이해하는 시리즈 Wls 최종 단계!)</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/c9229a56-da19-4f0c-b7ce-be6dfb177b28/image.png" width="60%" />


<br>

<p>앱에서 두 수를 입력 받아 multiply 버튼을 클릭하면 두 수를 곱한 결과값이 나오는 화면이 있습니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/bcc61ecb-c406-4f89-bc40-32885cd36578/image.png" width="40%" />

<pre><code class="language-ts">import { multiply } from &#39;react-native-test-library&#39;;

export default function App() {
  const [a, setA] = useState(&#39;0&#39;);
  const [b, setB] = useState(&#39;0&#39;);
  const [result, setResult] = useState(0);

  const handleMultiply = (a: string, b: string) =&gt; {
    const result = multiply(Number(a), Number(b));
    setResult(result);
  };

  return (
    &lt;View&gt;
      &lt;TextInput value={a} onChangeText={setA} /&gt;
      &lt;TextInput value={b} onChangeText={setB} /&gt;
      &lt;TouchableOpacity onPress={() =&gt; handleMultiply(a, b)}&gt;
        &lt;Text&gt;multiply&lt;/Text&gt;
      &lt;/TouchableOpacity&gt;
      &lt;Text&gt;결과값: {result}&lt;/Text&gt;
    &lt;/View&gt;
  );
}</code></pre>
<p>위 multiply 버튼을 클릭하면 handleMultiply 메서드가 호출되어, <code>react-native-test-library</code> 라이브러리의 multiply 메서드가 호출됩니다.
multiply 메서드가 호출되면 <code>앱 &lt;-&gt; 모듈</code> 간의 상호작용이 어떻게 될까요~?</p>
<p>가장 먼저, 라이브러리 모듈의 진입점부터 타겠죠?</p>
<h3 id="index">index</h3>
<pre><code class="language-ts">import TestLibrary from &#39;./NativeTestLibrary&#39;;

export function multiply(a: number, b: number): number {
  return TestLibrary.multiply(a, b);
}</code></pre>
<p>위 코드가 진입점 코드고, NativeTestLibrary에서 multiply 메서드에서 나온 결과 값을 리턴하는 것을 볼 수 있습니다.</p>
<h3 id="nativetestlibrary">NativeTestLibrary</h3>
<pre><code class="language-ts">import type { TurboModule } from &#39;react-native&#39;;
import { TurboModuleRegistry } from &#39;react-native&#39;;

export interface Spec extends TurboModule {
  multiply(a: number, b: number): number;
}

export default TurboModuleRegistry.getEnforcing&lt;Spec&gt;(&#39;TestLibrary&#39;);</code></pre>
<p>이 곳에서는 <code>TurboModuleRegistry</code>에서 &#39;TestLibrary&#39;라는 이름의 <code>TurboModule</code>을 가져오고, 이를 Spec 타입으로 강제합니다. 이 모듈을 기본 내보내기로 설정합니다.</p>
<p>위 설명에서도 배웠지만, 이 모듈의 각 OS별 코드는 4번에 정의되어있습니다! 
하지만...! 복습할 겸 한번 더 언급해보겠습니다.</p>
<br>

<h3 id="android-4">Android</h3>
<pre><code class="language-kotlin">// TestLibraryModule
  override fun multiply(a: Double, b: Double): Double {
    return a * b
  }</code></pre>
<br>

<h3 id="ios-4">iOS</h3>
<pre><code class="language-swift">// TestLibrary.mm
- (NSNumber *)multiply:(double)a b:(double)b {
    NSNumber *result = @(a * b);

    return result;
}</code></pre>
<br>

<h3 id="결과">결과</h3>
<p>결국 위 메서드들까지 타고 나서 나온 결과값을 아까 라이브러리 진입점에서 return 했으므로, </p>
<pre><code class="language-ts">const handleMultiply = (a: string, b: string) =&gt; {
    const result = multiply(Number(a), Number(b));
    setResult(result);
};</code></pre>
<p>위 코드에서는 각 OS에서 던져준 a * b 값이 리턴 될 것입니다!</p>
<blockquote>
<p>결과 😎: <code>react-native-test-library</code>에서 준 리턴값을 setResult에 넣어 result 값이 세팅 됩니다.</p>
</blockquote>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/80cab210-3ced-4ea6-9463-db71ee1664fb/image.png" width="40%" />


<p><br><br></p>
<h3 id="마무리">마무리</h3>
<p>와...!!! 드디어 긴 대장정을 마쳤습니다아아아아... 😭 😭 (짧았나? 아무튼 길었음 😤)</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/c393ea01-0493-4e16-be6a-4edc880bb772/image.png" width="60%" />

<p>요즘 위젯 라이브러리를 만들면서 기초 없이 만드는 기분이 들었습니다. 그래서 라이브러리의 흐름에 대한 이해가 먼저 필요할 것 같아 이 시리즈를 작성하며 정리하게 되었습니다.</p>
<p>또한, 그동안 라이브러리 통신 및 네이티브 코드에 대한 이해가 적었었는데, 이번 기회에 크게 배웠습니다. <strong>역시 남에게 가르칠 때 가장 잘 배우는 것 같습니다.</strong></p>
<p>위젯 라이브러리도 얼른 되는대로 포스팅 해야겠습니다...!!!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React Native 라이브러리 이해하기 - 2. 라이브러리 구조를 이해하자]]></title>
            <link>https://velog.io/@dev_jiwon/React-Native-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-2.-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EA%B5%AC%EC%A1%B0%EB%A5%BC-%EC%9D%B4%ED%95%B4%ED%95%98%EC%9E%90</link>
            <guid>https://velog.io/@dev_jiwon/React-Native-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-2.-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EA%B5%AC%EC%A1%B0%EB%A5%BC-%EC%9D%B4%ED%95%B4%ED%95%98%EC%9E%90</guid>
            <pubDate>Sat, 01 Feb 2025 10:02:37 GMT</pubDate>
            <description><![CDATA[<p><a href="https://velog.io/@dev_jiwon/React-Native-%EC%9C%84%EC%A0%AF-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0-1.-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-%EC%83%9D%EC%84%B1%ED%95%98%EC%9E%90">이전 포스팅</a>에서는 라이브러리를 이해하기에 앞서 라이브러리 프로젝트를 생성하는 시간을 가졌습니다. 🥳</p>
<p>이번 포스팅에서는 라이브러리 프로젝트의 폴더 및 파일 구조를 살펴보며, 모듈을 정의하는 코드를 살펴보겠습니다! +_+</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/19cadbaa-669d-40af-a956-a611d489813b/image.png" width="40%" />


<p><br><br></p>
<h2 id="폴더-및-파일-구조-이해하기">폴더 및 파일 구조 이해하기</h2>
<p>먼저 프로젝트의 폴더 및 파일 구조부터 살펴보겠습니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/a41b4252-836f-4df4-b084-29fd98a36a70/image.png" width="30%" />


<p>크게 보면 android, example, ios, src 이렇게 폴더가 구성된 걸 볼 수 있습니다.</p>
<pre><code>/test-library
  ├── ...
  ├── android
  ├── example
  ├── ios
  ├── src
  └── ...</code></pre><p>하나하나 어떻게 구성되어있는지 살펴보겠습니다!! 🤩 🤩</p>
<h3 id="example">example</h3>
<p>먼저 example 폴더부터 살펴보겠습니다.
example 폴더는 라이브러리가 쓰일 프로젝트의 예시를 드러낸 폴더입니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/2d6221a3-52bb-45e8-ac1d-bd7ccbeba518/image.png" width="70%"/>


<p>App.tsx는 react native 가장 최상단인 index.js에서 선언하는 파일입니다.
위 코드는 <code>react-native-test-library</code> 라이브러리에서 <code>multipy</code>라는 메서드를 꺼내 result를 반환하는 코드임을 알 수 있습니다.</p>
<p><code>multiply</code>는 라이브러리 프로젝트에서 기본으로 제공해주는 메서드인데 어디에 정의 되어있을까요?</p>
<br>

<h3 id="src">src</h3>
<p>바로바로 여깁니다~^^</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/8c6d5457-f7c8-4809-98c1-42d3429ad4e3/image.png" width="70%"/>

<p>src 폴더 내부에는 라이브러리 모듈 인터페이스를 정의해놓는 파일이 있습니다.</p>
<pre><code>/test-library/src/
  ├── NativeTestLibrary.ts
  └── index.tsx</code></pre><p>src 안에는 NativeTestLibrary.ts, index.tsx 파일 두개가 있습니다.
각 파일에 대해 알아봅시다. 😎 😎</p>
<br>

<h3 id="index">index</h3>
<p>가장 먼저 src 폴더의 진입점인 index 파일부터 보겠습니다.</p>
<pre><code class="language-ts">import TestLibrary from &#39;./NativeTestLibrary&#39;;

export function multiply(a: number, b: number): number {
  return TestLibrary.multiply(a, b);
}
</code></pre>
<p>잘은 모르겠지만 multiply 메서드는 <code>NativeTestLibrary</code> 폴더에서 multiply라는 메서드를 리턴하는걸 볼 수 있습니다.</p>
<p><code>NativeTestLibrary</code>가 어떻게 되어있는지 바로 구경해봅시다! +_+</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/a4d8de48-f779-47bf-9bd6-6a9776cf82a5/image.png" width="60%" />


<br>

<h3 id="nativetestlibrary">NativeTestLibrary</h3>
<pre><code class="language-ts">import type { TurboModule } from &#39;react-native&#39;;
import { TurboModuleRegistry } from &#39;react-native&#39;;

export interface Spec extends TurboModule {
  multiply(a: number, b: number): number;
}

export default TurboModuleRegistry.getEnforcing&lt;Spec&gt;(&#39;TestLibrary&#39;);
</code></pre>
<p>전문은 이렇고 하나하나 살펴보겠습니다!</p>
<br>

<pre><code class="language-ts">export interface Spec extends TurboModule {
  multiply(a: number, b: number): number;
}</code></pre>
<p>저는 <a href="https://velog.io/@dev_jiwon/React-Native-%EC%9C%84%EC%A0%AF-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0-1.-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-%EC%83%9D%EC%84%B1%ED%95%98%EC%9E%90">앞에서</a> 라이브러리 프로젝트를 생성할 때, 모듈 옵션으로 Turbo 모듈 옵션을 선택하였기 때문에 <code>TurboModule</code>을 기반으로한 인터페이스가 생성되었습니다. <code>TurboModule</code>은 네이티브 모듈과 JavaScript 간의 브릿지를 제공하여 네이티브 기능을 JavaScript에서 사용할 수 있게 합니다.</p>
<br>

<pre><code class="language-ts">export default TurboModuleRegistry.getEnforcing&lt;Spec&gt;(&#39;TestLibrary&#39;);</code></pre>
<p>여기서 <code>TurboModuleRegistry</code>는 React Native에서 <code>TurboModule</code>을 등록하고 가져오는 데 사용되는 레지스트리입니다. <code>TurboModuleRegistry</code>를 통해 특정 <code>TurboModule</code>을 가져오거나 등록할 수 있습니다.</p>
<p><code>TurboModuleRegistry</code>에서 &#39;TestLibrary&#39;라는 이름의 <code>TurboModule</code>을 가져오고, 이를 Spec 타입으로 강제합니다. 이 모듈을 기본 내보내기로 설정합니다.</p>
<br>

<p>src 폴더는 그럼 메서드 인터페이스가 정의되어있다는 것은 알았는데...
그렇다면 메서드 정의는 어디에 되어있을까요~? 🤔 🤔</p>
<p>지금 하고 있는 건 크로스플랫폼 라이브러리 구현이니까, 메서드는 각 OS 별로 다르겠죠? (*OS마다 호출하는 함수가 다를 거니까!)</p>
<p>메서드가 어떻게 정의 되어있는지 네이티브 폴더로 가보겠습니다!</p>
<br>

<h3 id="android">Android</h3>
<p>먼저 android 부터 보겠습니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/54f25049-7c22-4251-abe3-4d5df6838008/image.png" width="60%" />

<p>저는 라이브러리 이름을 test-library로 만들었더니 각 파일 이름이 라이브러리 이름을 따라 파스칼 형식으로 저장된 걸 볼 수 있습니다!</p>
<pre><code>/test-library/android/src/main/java/com/testlibrary/
  ├── TestLibraryModule.kt
  └── TestLibraryPackage.kt</code></pre><p>각 파일에는 코드가 어떻게 기본으로 세팅되어있는지 확인해봅시다.</p>
<br>

<h4 id="testlibrarypackage">TestLibraryPackage</h4>
<p>먼저 <code>TestLibraryPackage</code>부터 보겠습니다!</p>
<p><code>TestLibraryPackage</code>는 네이티브 모듈을 React Native 애플리케이션에 등록하는 역할을 합니다.
React Native 애플리케이션이 시작될 때, <code>TestLibraryPackage</code>가 로드되고, 이 패키지에서 제공하는 네이티브 모듈들이 등록됩니다.</p>
<p>코드 전문을 보겠습니다. 😌 😌</p>
<pre><code class="language-kotlin">class TestLibraryPackage : BaseReactPackage() {
  override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
    return if (name == TestLibraryModule.NAME) {
      TestLibraryModule(reactContext)
    } else {
      null
    }
  }

  override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
    return ReactModuleInfoProvider {
      val moduleInfos: MutableMap&lt;String, ReactModuleInfo&gt; = HashMap()
      moduleInfos[TestLibraryModule.NAME] = ReactModuleInfo(
        TestLibraryModule.NAME,
        TestLibraryModule.NAME,
        false,  // canOverrideExistingModule
        false,  // needsEagerInit
        true,  // hasConstants
        false,  // isCxxModule
        true // isTurboModule
      )
      moduleInfos
    }
  }
}</code></pre>
<p>이제 getModule 메서드부터 살펴봅시다!</p>
<pre><code class="language-kotlin"> override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
    return if (name == TestLibraryModule.NAME) {
      TestLibraryModule(reactContext)
    } else {
      null
    }
  }
</code></pre>
<p>이 getModule 메서드는 React Native 애플리케이션에서 네이티브 모듈을 호출할 때 호출되어, 모듈의 이름을 기반으로 <code>TestLibraryModule</code> 인스턴스를 생성하고 반환합니다.</p>
<br>

<p>다음은 getReactModuleInfoProvider 메서드 입니다.</p>
<pre><code class="language-kotlin">  override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
    return ReactModuleInfoProvider {
      val moduleInfos: MutableMap&lt;String, ReactModuleInfo&gt; = HashMap()
      moduleInfos[TestLibraryModule.NAME] = ReactModuleInfo(
        TestLibraryModule.NAME,  // 모듈 이름
        TestLibraryModule.NAME, // 모듈 이름
        false,  // canOverrideExistingModule (기존 모듈 덮어쓰기 가능 여부)
        false,  // needsEagerInit (애플리케이션 시작 시 초기화 필요 여부)
        true,  // hasConstants (상수 포함 여부)
        false,  // isCxxModule (C++ 모듈 여부)
        true // isTurboModule (TurboModule 여부)
      )
      moduleInfos
    }
  }</code></pre>
<p>getReactModuleInfoProvider 메서드는 <code>ReactModuleInfoProvider</code>를 반환하여 네이티브 모듈의 정보를 React Native에 등록하는 데 사용됩니다.</p>
<p><code>ReactModuleInfoProvider</code>는 네이티브 모듈의 이름, 초기화 방식, 상수 제공 여부, <code>TurboModule</code> 여부 등의 정보를 포함하는 <code>ReactModuleInfo</code> 객체를 제공합니다.</p>
<p>_(&#39;C++ 모듈 여부&#39;는 라이브러리를 생성할 때 언어 선택 부분에서 공유 C++ 라이브러리(Android 및 iOS용 C++)를 사용할지 선택하면 기본 true로 설정되어있습니다.)
_</p>
<br>

<h4 id="testlibrarymodule">TestLibraryModule</h4>
<p><code>TestLibraryPackage</code>에서 React Native에 모듈을 등록했으니...
등록할 모듈을 만들어보겠습니다!! 😎 😎</p>
<p>먼저 전문을 살펴볼까요? 드디어 라이브러리 모듈 공개...! (두둥 +_+)</p>
<pre><code class="language-kotlin">@ReactModule(name = TestLibraryModule.NAME)
class TestLibraryModule(reactContext: ReactApplicationContext) :
  NativeTestLibrarySpec(reactContext) {

  override fun getName(): String {
    return NAME
  }

  // Example method
  // See https://reactnative.dev/docs/native-modules-android
  override fun multiply(a: Double, b: Double): Double {
    return a * b
  }

  companion object {
    const val NAME = &quot;TestLibrary&quot;
  }
}</code></pre>
<p>TestLibraryModule 클래스는 JavaScript와 네이티브 코드 간의 상호 작용을 가능하게 하는 <strong>브릿지의 중요한 부분</strong>입니다. JavaScript 코드에서 TestLibrary 모듈을 호출하면, React Native의 <code>TurboModule</code>과 <code>JSI</code>를 통해 이 클래스의 메서드가 실행됩니다. 
(저는 <a href="https://velog.io/@dev_jiwon/React-Native-%EC%9C%84%EC%A0%AF-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0-1.-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-%EC%83%9D%EC%84%B1%ED%95%98%EC%9E%90">앞에서</a> 라이브러리 프로젝트를 생성할 때, 모듈 옵션으로 Turbo 모듈 옵션을 선택하였기 때문이죵!)</p>
<p>기본으로 multiply라는 메서드가 제공되는데,</p>
<pre><code class="language-kotlin">override fun multiply(a: Double, b: Double): Double {
    return a * b
}</code></pre>
<p>매개변수로 <code>Double</code> 타입의 a, b의 수를 받아 곱하는 메서드입니다.</p>
<br>

<p>여기까지가! 안드로이드에서 네이티브 모듈을 등록하는 코드입니다. 
그래서 모듈과의 통신을 어떻게 하는지는 ios까지 코드 확인해보고 뒤에서 살펴보겠습니다. &gt;,&lt;</p>
<p><br><br></p>
<h3 id="ios">iOS</h3>
<p>android까지 훑어봤으니 iOS도 금방 볼 수 있을 겁니다!!!
(그렇다고 해주세요. 초롱초롱 +_+)</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/ec8509e0-24a4-4d22-9259-f973fb05bcbd/image.png" width="60%" />

<p>딱봐도! iOS는 android보다 덜 복잡한거 보이시죠?!! 폴더도 더 없고 파일 두개가 끝! 입니다.</p>
<p>라이브러리 이름을 test-library로 만들었더니 iOS도 android처럼 각 파일 이름이 라이브러리 이름을 따라 파스칼 형식으로 저장된 걸 볼 수 있습니다!</p>
<pre><code>/test-library/ios/
  ├── TestLibrary.h
  └── TestLibrary.mm</code></pre><p>각 파일에는 코드가 어떻게 기본으로 세팅되어있는지 확인해봅시다.</p>
<h4 id="testlibraryh">TestLibrary.h</h4>
<p><code>TestLibrary</code> 헤더 파일은 모듈이 정의 될 <code>TestLibrary</code> 클래스의 인터페이스를 정의합니다.</p>
<p>코드 전문을 보겠습니다!</p>
<pre><code class="language-swift">#import &quot;generated/RNTestLibrarySpec/RNTestLibrarySpec.h&quot;

@interface TestLibrary : NSObject &lt;NativeTestLibrarySpec&gt;

@end</code></pre>
<p>짜잔! 3줄이 다입니다. 🫢 🫢</p>
<p>이 파일은 <code>TestLibrary</code> 클래스의 인터페이스를 정의하는 코드입니다. 이 클래스는 <code>NSObject</code> (Objective-C에서 가장 기본이 되는 클래스)를 상속받고, <code>NativeTestLibrarySpec</code> 프로토콜을 준수합니다.</p>
<p>(<code>NativeTestLibrarySpec</code>은 RNTestLibrarySpec 헤더 파일에 있으며, RNTestLibrarySpec 헤더 파일은 빌드하면 자동으로 생성되는 파일입니다.)</p>
<p>인터페이스를 정의해놓는 것이 <code>test-library/src/NativeTestLibrary.ts</code>의 Spec과 동일한 역할을 합니다.</p>
<p>자~ 그렇다면 TestLibrary 모듈은 어떻게 구성되어있는지 볼까요?</p>
<br>

<h4 id="testlibarymm">TestLibary.mm</h4>
<p>android에서는 <code>TestLibraryPackage</code>에서 네이티브 모듈을 React Native 애플리케이션에 등록하는 역할을 했죠? iOS에서는 TestLibrary.mm 파일의 <code>TestLibrary</code> 클래스가 동일한 역할을 합니다. </p>
<p>코드 전문부터 보겠습니다!</p>
<pre><code class="language-swift">#import &quot;TestLibrary.h&quot;

@implementation TestLibrary
RCT_EXPORT_MODULE()

- (NSNumber *)multiply:(double)a b:(double)b {
    NSNumber *result = @(a * b);

    return result;
}

- (std::shared_ptr&lt;facebook::react::TurboModule&gt;)getTurboModule:
    (const facebook::react::ObjCTurboModule::InitParams &amp;)params
{
    return std::make_shared&lt;facebook::react::NativeTestLibrarySpecJSI&gt;(params);
}

@end</code></pre>
<p><em>(어웅 복잡해<del>~</del>😵😵 objective-c가 익숙치 않은 저같은 개발자들은 위 코드가 다소 낯설 수도 있습니다. 킹치만...! 차근차근 보면 됩니다...! )</em></p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/52d3efc3-e87d-4a92-a7f5-c49878555e7f/image.png" width="60%" />

<br>
ㅠㅠ

<p>바로 한줄한줄 해석해보겠습니다~!</p>
<pre><code class="language-swift">#import &quot;TestLibrary.h&quot;</code></pre>
<p>위에서 설명드린 TestLibrary.h 헤더 파일을 포함합니다.</p>
<br>

<pre><code class="language-swift">RCT_EXPORT_MODULE()</code></pre>
<p>이 부분이 <strong>✌️포인트✌️</strong>인데, 이 매크로는 <code>TestLibrary</code> 모듈을 React Native에 등록하는 부분입니다. 이 매크로를 사용하면 JavaScript 코드에서 이 모듈을 사용할 수 있게 됩니다. android에서 getReactModuleInfoProvider 메서드와 같은 역할입니다!!</p>
<br>

<pre><code class="language-swift">- (NSNumber *)multiply:(double)a b:(double)b {
    NSNumber *result = @(a * b);
    return result;
}</code></pre>
<p>위 코드는 android와 마찬가지로 기본으로 제공하는 multiply 메서드 입니다. 매개변수로 double 타입의 a, b의 수를 받아 곱해 NSNumber 객체로 반환하는 메서드입니다.</p>
<br>

<pre><code class="language-swift">- (std::shared_ptr&lt;facebook::react::TurboModule&gt;)getTurboModule:
    (const facebook::react::ObjCTurboModule::InitParams &amp;)params
{
    return std::make_shared&lt;facebook::react::NativeTestLibrarySpecJSI&gt;(params);
}</code></pre>
<p>getTurboModule 메서드는 <code>TurboModule</code>을 초기화하고 반환합니다. 이 메서드는 <code>TurboModule</code>을 사용하여 <code>JavaScript</code>와 네이티브 코드 간의 상호 작용을 가능하게 합니다. <code>NativeTestLibrarySpecJSI</code> 클래스는 <code>TurboModule</code>의 구현을 담당합니다.</p>
<br>

<p>어웅... 넘 복잡스럽고 어려웠습니다... 😭 😭</p>
<p>but...!!</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/a2715009-8b89-47df-b9a3-6bf9720fe95d/image.png" width="60%" />


<p>다음 포스팅에서 모듈 통신을 이해하는 과정을 위 코드와 함께 차근차근 다시 살펴볼 것입니다! +_+</p>
<p>그럼 <a href="https://velog.io/@dev_jiwon/React-Native-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-3.-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EB%AA%A8%EB%93%88%EC%9D%84-%EC%9D%B4%ED%95%B4%ED%95%98%EC%9E%90-%EC%B5%9C%EC%A2%85">다음 포스팅</a>에서 만나요!! 👋👋</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React Native 라이브러리 이해하기 - 1. 라이브러리 프로젝트를 생성하자]]></title>
            <link>https://velog.io/@dev_jiwon/React-Native-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-1.-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-%EC%83%9D%EC%84%B1%ED%95%98%EC%9E%90</link>
            <guid>https://velog.io/@dev_jiwon/React-Native-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-1.-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-%EC%83%9D%EC%84%B1%ED%95%98%EC%9E%90</guid>
            <pubDate>Fri, 17 Jan 2025 17:56:36 GMT</pubDate>
            <description><![CDATA[<p>이번 시리즈에서는 React Native 라이브러리에 대해 이해해보는 시간을 가져보겠습니다.😎 😎
라이브러리를 좀 더 잘 이해하기 위해 이번 포스팅에서는 라이브러리 프로젝트를...!! 같이 ...만들어 보는 시간을 가져보겠습니다!!!! 🤩 🤩 🤩</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/0a1d3b79-7b3f-488f-9058-457155a027c3/image.png" width="50%" />

<p>저는 처음에 라이브러리 프로젝트를 생성할 때, 일반 React Native 프로젝트를 생성하듯이 프로젝트를 생성했었는데...!</p>
<p>그렇게 하면 삐빅-</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/eb44dace-ef45-46ff-9a90-4fd5947b5b7a/image.png" width="50%"/>

<p>라이브러리용 프로젝트를 생성하는 방법이 따로 있습니다...!!! +_+</p>
<p>라이브러리 프로젝트를 생성하는 과정은 <a href="https://reactnative.dev/docs/the-new-architecture/create-module-library">공식 문서</a>에 나와있으므로 이 블로그 내용에선 생략하겠습니다.</p>
<br>

<p>...</p>
<br>

<img src="https://velog.velcdn.com/images/dev_jiwon/post/3de0b943-c501-4312-8200-4a64c9faa93e/image.png" width="50%" />

<p>라고 하면 너무 불친절 한 것 같아서 같이 프로젝트를 생성해보겠습니다. 🤣 🤣</p>
<p><br><br></p>
<h2 id="라이브러리-프로젝트-생성">라이브러리 프로젝트 생성</h2>
<p>본격 라이브러리 프로젝트 생성하긔❗️</p>
<ol>
<li><p>먼저 터미널을 열고 프로젝트를 생성할 위치로 가서 아래 커맨드를 입력합니다.</p>
<pre><code> npx create-react-native-library@latest &lt;Name of Your Library&gt;</code></pre></li>
</ol>
<ol start="2">
<li>npm에 올라갈 원하는 모듈 이름을 추가합니다.
<img src="https://velog.velcdn.com/images/dev_jiwon/post/78cc5889-7b69-4f3e-a04c-2f9d07027495/image.png" width="60%" /> 유효한 npm 이름이어야 하므로 모두 소문자여야 합니다. -를 사용하여 단어를 구분할 수 있습니다.</li>
</ol>
<ol start="3">
<li><p>패키지에 대한 설명 및 레퍼지토리 등을 추가합니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/9064db9d-ec6f-487d-8478-40aeea5a2f1d/image.png" width="60%" />
</li>
<li><p>원하는 유형의 라이브러리를 선택합니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/41417f67-7713-493a-b078-421cd1bc00b7/image.png" width="60%" />
저는 Turbo 모듈 옵션을 선택하였습니다. 이 옵션은 New Architecture와 Legacy Architecture 모두에 대한 라이브러리를 만들 수 있다는 점에 유의하세요.
</li>
<li><p>플랫폼에 접근하는 라이브러리(Kotlin 및 Objective-C)를 사용할지 아니면 공유 C++ 라이브러리(Android 및 iOS용 C++)를 사용할지 선택합니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/077d998f-424e-4f18-b72e-a991bba90d6d/image.png" width="60%" />

<p>저는 전자를 선택하겠습니다! :)</p>
</li>
</ol>
<br>

<p>휴 생성 완료!😌 위 절차를 따르면 라이브러리 프로젝트가 생성됩니다!!
자 이제 라이브러리 프로젝트를 생성했으니 다음 포스팅에서 라이브러리 구조에 대해 이해해보는 시간을 가져보겠습니다~ 😆 😆</p>
<p><br><br><br></p>
<p>참고</p>
<p><a href="https://velog.io/@euisuk95/React-native-builder-bob-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%84%9C-React-Native%EC%9A%A9-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EA%B8%B0-%EC%B6%94%EC%B6%94%EC%B6%94%EA%B0%9C%EC%B6%94%EC%B2%9C">https://velog.io/@euisuk95/React-native-builder-bob-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%84%9C-React-Native%EC%9A%A9-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EA%B8%B0-%EC%B6%94%EC%B6%94%EC%B6%94%EA%B0%9C%EC%B6%94%EC%B2%9C</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React Native 위젯 라이브러리 만들기 - 0. 위젯에 대해 알아보자]]></title>
            <link>https://velog.io/@dev_jiwon/React-Native-Widget-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0-0.-%EC%9C%84%EC%A0%AF%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@dev_jiwon/React-Native-Widget-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0-0.-%EC%9C%84%EC%A0%AF%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Fri, 17 Jan 2025 17:04:15 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요! 이번에는 React Native에서 위젯 라이브러리를 만드는 방법에 대해 포스팅을 하려고 합니다. 🤩 
위젯 라이브러리를 단순히 만들면 기억에 남지 않을 것 같아 오래 기억하기 위해 라이브러리를 만들며 만든 내용을 블로그에 작성하려고 합니다. 이 포스팅은 긴 포스팅이 될 것 같고, 저 스스로에게도 장기 프로젝트가 될 것 같습니다.</p>
<h2 id="배경">배경</h2>
<p>제가 곧 React Native 개발자 5년차에 접어드는데, 네이티브 언어를 아직 제대로 하지 못함에 스스로 아쉬움을 느끼고 있었고, 맨날 만들어진 라이브러리를 연동만 해봤지 직접 구현해본적이 없어서 직접 만들어 네이티브와 React Native간의 통신을 더 깊게 이해하고 싶었습니다.</p>
<p>저는 일단 React Native 라이브러리 중에서 활성화가 덜 됐거나 아직 존재하지 않은 라이브러리를 만들어 보고싶었고, 이왕이면 제가 실제로 앱에서 사용하는 기능을 구현해 보고 싶었습니다. </p>
<p>저는 평소에 앱 위젯 기능을 잘 사용합니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/dd87e86a-b021-4652-816f-6058b069abf1/image.PNG" width="30%" />

<p>그래서 React Native에도 위젯 라이브러리가 있는지 찾아보았습니다. 찾아봤더니 <a href="https://saleksovski.github.io/react-native-android-widget/docs">Android용 위젯 라이브러리</a>, <a href="https://www.npmjs.com/package/react-native-widgetkit?activeTab=readme">iOS용 위젯 라이브러리</a>가 각각 존재하였습니다.</p>
<p>Android용 위젯 라이브러리는 공식문서가 아주 친절하게 잘 되어있으나 다운로드 수가 적었고, iOS용 위젯 라이브러리는 Android용 위젯 라이브러리보다는 다운로드 수가 많았지만 4년 전에 올라온 커밋이 마지막 커밋이었습니다...⭐️</p>
<p>또한, 위 라이브러리가 한 라이브러리에서 관리 된다면 사용하기 더 편할 것 같기에 저는 이 둘을 한 라이브러리에서 쓸 수 있도록 구현해보려 합니다! 🤩</p>
<p>라이브러리를 처음 만들어보는 입장에서 마침 참고할 라이브러리가 있다니...!
이거슨 신이 주신 기회...?</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/003f5a43-046b-4406-9f67-cc3f9abe8fc7/image.png" width="70%" />

<p><br><br></p>
<h2 id="위젯이란">위젯이란?</h2>
<p>먼저, 라이브러리 개발을 들어감에 앞서 위젯에 대해 간단히 알아보겠습니다.</p>
<blockquote>
<p>😎: 위젯이란, 앱을 열지 않아도 콘텐츠를 표시하고 특정 기능을 사용할 수 있도록 하는 기능입니다. 사람들은 위젯을 통해 기기를 구성하고 사용자화하여 필요한 정보 및 기능에 빠르게 접근할 수 있습니다.</p>
</blockquote>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/44cab4cf-5e20-40c0-a83b-21e71fa34fc0/image.png" width="70%" />

<p><br><br></p>
<h2 id="위젯-종류">위젯 종류</h2>
<p>이제 앱에서 쓰이는 위젯의 종류에 대해 알아보겠습니다. 위젯의 유형은 일반적으로 다음 카테고리 중 하나에 속합니다.</p>
<h3 id="정보-위젯">정보 위젯</h3>
<p>정보 위젯은 일반적으로 중요한 정보 요소를 표시하고 <strong>시간에 따른 정보의 변화</strong>를 추적합니다. 정보 위젯의 예로는 날씨 위젯, 시계 위젯, 스포츠 경기 점수 추적 위젯이 있습니다. 일반적으로 정보 위젯을 탭하면 연결된 앱이 실행되고 위젯 정보의 세부정보 뷰가 열립니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/fc098cbe-b77e-4b88-9257-7102fe53915f/image.jpg" width="50%" />

<br>

<h3 id="컬렉션-위젯">컬렉션 위젯</h3>
<p>컬렉션 위젯은 갤러리 앱의 사진 모음, 뉴스 앱의 기사 모음, 커뮤니케이션 앱의 이메일 또는 메시지 모음과 같이 동일한 유형의 여러 요소를 표시하는 데 특화되어 있습니다. 컬렉션 위젯은 세로로 스크롤할 수 있습니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/769e0c98-1454-4ef9-9032-22cfcfd3c673/image.png" width="50%" />


<br>

<h3 id="관리-위젯">관리 위젯</h3>
<p>관리 위젯의 기본 목적은 사용자가 앱을 열지 않고도 홈 화면에서 트리거할 수 있도록 자주 사용되는 함수를 표시하는 것입니다. 관리 위젯과 상호작용하면 앱에서 연결된 세부정보 뷰가 열릴 수 있습니다. 이는 검색 위젯의 경우와 같이 관리 위젯의 함수가 데이터를 출력하는지에 따라 다릅니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/a6ae63c2-4f23-438c-99c7-7771e296d7e1/image.jpg" width="50%" />

<p>위의 위젯은 유튜브 앱과 지메일 앱의 위젯입니다.</p>
<p>유튜브 앱의 검색, 홈, 숏츠, 구독 화면으로 이동할 수 있는 버튼이 있고, 이동을 원하는 버튼을 누르면 앱이 열리면서 해당 화면에 도달합니다.</p>
<p>지메일 앱의 검색, 편지쓰기, 읽지 않은 메일 리스트 화면으로 이동할 수 있는 버튼이 있고, 이동을 원하는 버튼을 누르면 앱이 열리면서 해당 화면에 도달합니다.</p>
<br>

<h3 id="하이브리드-위젯-정보위젯--관리위젯">하이브리드 위젯 (정보위젯 + 관리위젯)</h3>
<p>일부 위젯은 앞의 섹션에 나온 유형(정보, 컬렉션, 관리) 중 하나를 나타내지만, 대부분의 위젯은 다양한 유형의 요소를 결합한 하이브리드 위젯입니다. 예를 들어 음악 플레이어 위젯은 기본적으로 관리 위젯이지만 정보 위젯과 마찬가지로 현재 재생 중인 트랙을 사용자에게 표시합니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/696a4835-fd40-48d5-99b8-efe1dc037c44/image.png" width="50%" />

<p>위의 위젯은 지메일 앱과 유튜브 뮤직 앱의 위젯입니다.</p>
<p>지메일 앱의 메일 리스트가 출력 되고(정보 위젯 기능), 메일을 바로 쓸 수 있는 기능(관리 위젯 기능)이 혼합되어 있습니다.</p>
<p>유튜브 뮤직 앱에서도 사용자가 들은 음악 리스트가 출력 되고(정보 위젯 기능), 음악을 바로 재생하는 기능(관리 위젯 기능)이 혼합되어 있습니다.</p>
<p><br><br></p>
<p>자...! 이제 본격적으로 위젯 라이브러리를 만들어보겠습니다...!!!</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/134756a2-fb4c-4da2-a0b5-bc1ae8f21073/image.png" width="60%" />

<p>다음 포스팅에서 만나요~ 👋👋</p>
<p><br><br><br></p>
<p>참고
<a href="https://developer.apple.com/kr/design/human-interface-guidelines/widgets">https://developer.apple.com/kr/design/human-interface-guidelines/widgets</a></p>
<p><a href="https://developer.android.com/develop/ui/views/appwidgets/overview?hl=ko#types">https://developer.android.com/develop/ui/views/appwidgets/overview?hl=ko#types</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React Native] React Native에서 쿠키 지우기]]></title>
            <link>https://velog.io/@dev_jiwon/React-Native-React-Native%EC%97%90%EC%84%9C-%EC%BF%A0%ED%82%A4-%EC%A7%80%EC%9A%B0%EA%B8%B0</link>
            <guid>https://velog.io/@dev_jiwon/React-Native-React-Native%EC%97%90%EC%84%9C-%EC%BF%A0%ED%82%A4-%EC%A7%80%EC%9A%B0%EA%B8%B0</guid>
            <pubDate>Sun, 15 Dec 2024 05:14:33 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요~! 오늘은 회사에서 겪었던 🍪쿠키🍪 관련 이슈를 다뤄보려고 합니다.</p>
<p>현재 회사 앱에서는 사용자가 로그인 시 자동 로그인 여부를 선택할 수 있습니다.
자동 로그인을 선택하지 않은 경우, 앱을 재시작하면 로그아웃 상태로 앱에 진입하게 되는 플로우인데요.</p>
<p>이 과정에서 🍪쿠키🍪 관련 문제가 발생했습니다.</p>
<br>

<h2 id="문제-상황">문제 상황</h2>
<p>앱에서 로그인을 하면 서버로부터 <code>set-cookie</code>를 통해 🍪쿠키🍪가 설정됩니다.
문제는 자동 로그인을 선택하지 않은 사용자가 앱을 재시작했을 때 발생합니다.</p>
<p>이 경우, request header에 이전에 설정된 🍪쿠키🍪가 그대로 남아있어, 비로그인 상태로 앱에 진입했음에도 불구하고 서버에서는 로그인 유저로 잘못 인식되는 상황이 생기게 됩니다.</p>
<p>특히 로그인 여부와 관계없이 공통적으로 호출되는 API에서 🍪쿠키🍪를 기반으로 유저를 로그인 상태로 인식하면서, 결과적으로 앱 화면은 로그아웃 상태인데 네트워크 요청은 로그인 상태로 처리되는 문제가 발생했습니다.</p>
<p>(🍪쿠키🍪 개념 및 흐름은 <a href="https://velog.io/@dev_jiwon/Security-%EC%BF%A0%ED%82%A4Cookie%EC%99%80-%EC%84%B8%EC%85%98Session#1-%EC%BF%A0%ED%82%A4-cookie">이전 포스팅</a>을 참고해주세요.)</p>
<br>

<p>이 문제를 해결하기 위해 3가지의 방안을 고민했고, 그중 어떤 방안을 선택했는지 공유해 보려고 합니다.</p>
<br>

<h2 id="해결-방안-후보">해결 방안 후보</h2>
<h3 id="해결방안-1">해결방안 1</h3>
<blockquote>
<p>🧐: 로그인 시 서버에서 <code>set-cookie</code>로 🍪를 설정하고, 로그아웃 시에도 서버에서 🍪를 삭제하고 있으니 앱이 종료될 때도 서버에서 🍪를 삭제하도록 하면 되지 않을까?</p>
</blockquote>
<p>일단 앱이 꺼졌다는 걸 앱에서도 감지할 수 없습니다. 그래서 소켓이 끊어진 경우를 앱이 종료되었다고 간주하려 하였습니다.</p>
<p>현재 앱에서 소켓을 활용해 다양한 이벤트를 처리하고 있는데요,</p>
<ul>
<li>앱 진입 시 소켓이 connect되고,</li>
<li>앱 종료 시 소켓이 disconnect되는 흐름입니다.</li>
</ul>
<p>따라서 소켓의 disconnect 상태를 앱 종료로 간주해, 이 시점에 서버에서 🍪쿠키🍪를 삭제하면 문제를 해결할 수 있을 것 같았습니다.
(소켓을 통해 앱 여부 및 자동 로그인 여부를 파악할 수 있어 가능해 보였습니다.)</p>
<br>

<p>하지만...! 여기서 또 다른 문제가 있었습니다.</p>
<p>앱을 사용하다가 휴대폰을 잠그는 경우에도 소켓이 disconnect 되는 상황이 발생합니다.
폰을 다시 잠금 해제하고 앱에 진입하면 소켓이 재연결(connect)되긴 하지만,
이 경우라면 잠금 시점에서 🍪쿠키🍪를 삭제해야 하고, 재연결 시 다시 <code>set-cookie</code>로 🍪쿠키🍪를 설정해야 하는 번거로움이 생깁니다.</p>
<p>이 방식은 복잡한 흐름을 초래하기 때문에 현실적으로 적합하지 않다고 판단했습니다.</p>
<p><del>해결방안 1 탈락</del></p>
<br>

<h3 id="해결방안-2">해결방안 2</h3>
<blockquote>
<p>🧐: 자동 로그인을 해제한 상태에서 로그인했던 유저가 앱에 재접속 할 때, <code>signout</code> API를 호출하여 서버에서 🍪를 삭제하게 하면 되지 않을까?</p>
</blockquote>
<p>이 방법은 비효율적인 API 호출을 유발합니다. 또한, <code>signout</code> API는 단순히 🍪쿠키🍪를 삭제하는 것 외에도 다른 기능을 포함하고 있을 수 있습니다.</p>
<p>현재 필요한 건 <strong>&quot;앱에서 🍪쿠키🍪만 삭제&quot;</strong> 하는 것이므로, 굳이 <code>signout</code> API를 호출하지 않고, 🍪쿠키🍪를 삭제하는 기능만 별도로 구현하는 것이 더 적합하다고 판단했습니다.</p>
<p><del>해결방안 2 탈락</del></p>
<br>

<h3 id="해결방안-3-🤩-채택❗️---rn-네트워크에서-쿠키-남는-원인-대공개❗️">해결방안 3 (🤩 채택❗️) - RN 네트워크에서 쿠키 남는 원인 대공개❗️</h3>
<blockquote>
<p>🧐: 자동 로그인을 해제한 상태에서 로그인했던 유저가 앱에 재접속 할 때, 앱에서 🍪를 지우면 되지 않을까?</p>
</blockquote>
<p>해결 방안 1번과 2번을 제외하고 나니, 앱을 껐다 켜도 request header에 🍪쿠키🍪가 남아 있는 원인이 궁금해졌습니다. 결국, request header에 🍪쿠키🍪가 남아 있다는 것은 앱 내부 어딘가에 🍪쿠키🍪가 저장되어 있다는 뜻이었기 때문에 어디에서 남아 있는지를 확인해 보기로 했습니다.</p>
<Image src="https://velog.velcdn.com/images/dev_jiwon/post/f6b76e9d-48e9-4422-b204-f5bf6e62e6c1/image.png" width="70%" />

<Image src="https://velog.velcdn.com/images/dev_jiwon/post/c26c46f8-a648-4789-9897-481860948404/image.png" width="70%" />

<p>바로바로...!</p>
<blockquote>
<p>😎: React Native에서는 <code>react-native/Libraries/Network/RCTNetworking</code> 내부에서 네트워크 요청을 관리합니다. 이 모듈은 🍪의 영속 시간 동안 🍪를 캐싱하고 있는데, 이 곳에서 🍪가 남아있었습니다. 
따라서 이 모듈에 접근하여, 자동 로그인을 선택하지 않은 사용자가 앱에 재접속했을 때 쿠키를 삭제하는 방법을 적용하기로 하였습니다.</p>
</blockquote>
<pre><code class="language-ts">const RCTNetworking = require(&quot;react-native/Libraries/Network/RCTNetworking&quot;).default
RCTNetworking.clearCookies()</code></pre>
<br>

<p>해결 완...❗️❗️ 🤩🤩🤩 ❗️❗️❗️❗️</p>
<p><br><br></p>
<h2 id="앱에서-쿠키를-가져와볼까">앱에서 쿠키를 가져와볼까?</h2>
<p>해결 방안3으로 결론 도출 중, 한 가지 의문이 들었습니다.</p>
<blockquote>
<p>🧐: 이전에 로그인했던 기록을 찾아 로그인한 유저인 경우에 🍪를 지우는 것보다,
앱 진입 시 비로그인 상태인데 헤더에 🍪가 남아 있는 경우에 🍪를 삭제하는 방식이 더 확실하지 않을까?</p>
</blockquote>
<p>이 생각을 바탕으로 React Native에서 🍪쿠키🍪를 가져오는 방법을 조사해 보았습니다.</p>
<h3 id="서드파티-라이브러리-통해-쿠키-가져오기">서드파티 라이브러리 통해 쿠키 가져오기</h3>
<p>찾아보니 <a href="https://github.com/react-native-cookies/cookies">서드파티 라이브러리</a>를 사용하면 쿠키를 가져올 수 있었습니다.
다만, 지금 저에게 필요한 건 단순히 쿠키를 가져오는 기능뿐이었고, 굳이 라이브러리를 설치하기엔 배보다 배꼽이 더 큰 상황처럼 느껴졌습니다.</p>
<br>

<h3 id="axios-interceptor-통해-쿠키-가져오기">axios interceptor 통해 쿠키 가져오기</h3>
<p>다음으로는 axios에서 쿠키를 가져오는 방법을 시도해 보았습니다.
하지만, axios로 interceptor를 통해 request header를 확인해 본 결과, 대부분의 헤더 정보는 출력되었지만 정작 <code>Cookie</code> 정보는 확인할 수 없었습니다.</p>
<p>(request header를 콘솔에 찍었더니 다음과 같았다.)</p>
<pre><code>{
  &quot;Authorization&quot;: `Bearer ${token}`,
  &quot;common&quot;: {
    &quot;Accept&quot;: &quot;application/json, text/plain, */*&quot;,
    &quot;Authorization&quot;: `Bearer ${token}`
  },
  &quot;delete&quot;: {},
  &quot;get&quot;: {},
  &quot;head&quot;: {},
  &quot;patch&quot;: {
    &quot;Content-Type&quot;: &quot;application/x-www-form-urlencoded&quot;
  },
  &quot;post&quot;: {
    &quot;Content-Type&quot;: &quot;application/x-www-form-urlencoded&quot;
  },
  &quot;put&quot;: {
    &quot;Content-Type&quot;: &quot;application/x-www-form-urlencoded&quot;
  }
}</code></pre><br>

<p>🧐 이거 대체 왜이런가 하고 봤더니,</p>
<Image src="https://velog.velcdn.com/images/dev_jiwon/post/ce79becb-9da7-4048-ab12-355c4f13d3f4/image.png" width="80%" />

<br>


<p>다음과 같은 이유가 있었습니다.</p>
<blockquote>
<p>😎 : React Native는 기본적으로 <code>RCTNetworking</code> 모듈을 통해 네이티브 네트워크 요청을 처리합니다. axios에서 <code>withCredentials: true</code> 설정을 활성화하면, 네이티브 계층에 저장된 🍪가 요청에 자동으로 추가됩니다. 
이처럼 🍪는 네이티브 계층에서 자동으로 관리되기 때문에, 네트워크 탭에 보이는 <code>Cookie</code> 헤더는 axios의 interceptor에서는 확인할 수 없습니다.
즉, 네이티브 계층에서 추가된 🍪는 axios 내부에서 직접 접근하거나 읽어들일 수 없는 구조입니다.</p>
</blockquote>
<p>(혹시 이 외의 방법으로도 🍪를 볼 수 있는 방법을 아시는 분이 계신다면 댓글 달아주시면 감사하겠습니다! (_ _))</p>
<br>

<blockquote>
<p>🥳: 이번 기회에 react native에서 🍪쿠키🍪를 지우는 방법에 대해 새롭게 알게 되었다. 역시 사람은 사고를 해야한다. 레벨 업+1 했다!!</p>
</blockquote>
<Image src="https://velog.velcdn.com/images/dev_jiwon/post/a6dd4d6a-5fde-469a-aee3-18fe07255ced/image.png" width="80%" />


<p><br><br><br></p>
<p>참고
<a href="https://medium.com/syntx-io/cookie-management-in-react-native-545133fdcd14">https://medium.com/syntx-io/cookie-management-in-react-native-545133fdcd14</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] 자바를 자바랏~! - (2) 객체 지향 프로그래밍
]]></title>
            <link>https://velog.io/@dev_jiwon/Java-%EC%9E%90%EB%B0%94%EB%A5%BC-%EC%9E%90%EB%B0%94%EB%9E%8F-2-%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%8D</link>
            <guid>https://velog.io/@dev_jiwon/Java-%EC%9E%90%EB%B0%94%EB%A5%BC-%EC%9E%90%EB%B0%94%EB%9E%8F-2-%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%8D</guid>
            <pubDate>Sun, 11 Aug 2024 10:20:56 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요. 지난 포스팅에 이어 자바를 자바랏의 두번째 개념 시간을 가져보겠습니다~!!</p>
<p><strong>이번 포스팅은 객체 지향 프로그래밍에 대해 알아보겠습니다.</strong></p>
<h2 id="1-절차-지향-프로그래밍-vs-객체지향-프로그래밍">1. 절차 지향 프로그래밍 vs. 객체지향 프로그래밍</h2>
<p>프로그램 방식은 크게 절차 지향 프로그래밍과 객체 지향 프로그래밍으로 나눌 수 있습니다.</p>
<h3 id="절차-지향-프로그래밍">절차 지향 프로그래밍</h3>
<ul>
<li>절차 지향 프로그래밍은 이름 그대로 <strong>절차</strong>를 지향합니다.</li>
<li>실행 순서를 중요하게 생각하기 때문에 <strong>프로그램의 흐름을 순차적으로</strong> 따르며 처리하는 방식입니다.</li>
</ul>
<h3 id="객체-지향-프로그래밍">객체 지향 프로그래밍</h3>
<ul>
<li>객체 지향 프로그래밍은 이름 그대로 <strong>객체</strong>를 지향합니다.</li>
<li>실제 세계의 사물이나 사건을 객체로 보고, 이러한 <strong>객체들 간의 상호작용</strong>을 중심으로 프로그래밍 하는 방식.</li>
</ul>
<br>

<p>두 프로그래밍 방식은 데이터 처리 방식에 있어 중요한 차이가 있습니다.
절차 지향은 <strong>데이터와 해당 데이터에 대한 처리 방식이 분리</strong>되어 있으나, 객체 지향은 <strong>데이터와 그 데이터에 대한 메서드가 하나의 객체 안에 포함 되어있다는 것</strong>입니다!!!!</p>
<p>바로 예시로 보겠습니다.</p>
<h3 id="예시">예시</h3>
<div class="row">
  <img src="https://github.com/user-attachments/assets/ded0aa4d-b922-41c4-9920-df0b6b1592a3" width="30%" />
  <img src="https://github.com/user-attachments/assets/bc5fda47-ee43-460b-8139-cbcd5bd00a89" width="70%"/>
</div>

<br>

<p>고객이 카페 가서 커피를 주문하여 받는 과정을 프로그래밍의 관점으로 보겠습니다.</p>
<p>절차 지향 방식은 <strong>상황을 중심으로</strong> 순서대로 조합하는 방식입니다.</p>
<p>반면, 객체 지향 방식은 <strong>객체를 중심으로</strong> 프로그래밍 합니다. 커피 주문 상황에서 필요한 객체들에게(고객, 직원) 역할을 지정해놓고, 역할을 가진 각 객체들을 순서대로 조합하는 방식입니다.</p>
<br>


<h2 id="2-클래스와-메서드">2. 클래스와 메서드</h2>
<p>클래스는 데이터인 멤버 변수 뿐 아니라 기능 역할을 하는 메서드도 포함할 수 있습니다. 위의 예시로 절차 지향 방식과 객체 지향 방식의 코드 차이를 알아봅시다.</p>
<p>먼저 절차 지향 방식부터 알아보겠습니다!</p>
<h3 id="1-절차-지향-방식">1. 절차 지향 방식</h3>
<pre><code class="language-java">public class CafeData {
  int coffeeCount;
}</code></pre>
<pre><code class="language-java">public class CafeDataMain {
     public static void main(String[] args) {
         CafeData cafeData = new CafeData();
         add(cafeData);
         add(cafeData);
         add(cafeData);
         System.out.println(&quot;커피 개수=&quot; + cafeData.coffeeCount);
     }

     static void add(CafeData cafeData) {
         cafeData.coffeeCount++;
         System.out.println(&quot;커피 개수 증가 coffeeCount=&quot; + cafeData.coffeeCount);
      }
}</code></pre>
<p>결과</p>
<pre><code>커피 개수 증가 coffeeCount=1
커피 개수 증가 coffeeCount=2
커피 개수 증가 coffeeCount=3
커피 개수=3</code></pre><p>절차 지향 방식은 <strong>상황</strong>을 순서대로 조합하는 방식이라고 하였죠? 코드를 하나하나 분석해봅시다. 🧐</p>
<ol>
<li><p>coffeeData에 coffeeCount 멤버 변수가 존재합니다. // 메모리 주소는 예시입니다.</p>
<img src="https://github.com/user-attachments/assets/ad9e72df-e347-43ce-862c-1909fe231817" width="50%" />
</li>
<li><p>메인에 cafeData를 파라미터로 받아서, cafeData에서 coffeeCount를 꺼내어 증가시키는 메서드 add가 있습니다.</p>
<img src="https://github.com/user-attachments/assets/3eabaaea-a72b-4b05-8dad-24352afc386a" width="50%" />
</li>
<li><p>메인에서 <strong>상황</strong>(add)을 <strong>순서대로</strong> 호출하고 있습니다.</p>
<img src="https://github.com/user-attachments/assets/7be223d1-6f77-4bd3-ade8-cfd3df2ecf15" width="50%" />

</li>
</ol>
<br>

<p>과정</p>
<img src="https://github.com/user-attachments/assets/218b1ff0-d8c7-4f94-bbd4-204898fff15d" width="40%" />

<p><br><br></p>
<p>다음으로 객체 지향 방식을 알아보겠습니다!</p>
<h3 id="2-객체-지향-방식">2. 객체 지향 방식</h3>
<pre><code class="language-java">public class CafeData {
  int coffeeCount;

  void add() {
    coffeeCount++;
    System.out.println(&quot;커피 개수 증가 coffeeCount=&quot; + cafeData.coffeeCount);
  }
}</code></pre>
<pre><code class="language-java">public class CafeDataMain {
     public static void main(String[] args) {
         CafeData cafeData = new CafeData();
         cafeData.add();
         cafeData.add();
         cafeData.add();
         System.out.println(&quot;커피 개수=&quot; + cafeData.coffeeCount);
     }
}</code></pre>
<p>결과</p>
<pre><code>커피 개수 증가 coffeeCount=1
커피 개수 증가 coffeeCount=2
커피 개수 증가 coffeeCount=3
커피 개수=3</code></pre><p>객체 지향 방식은 역할을 가진 각 <strong>객체들을 순서대로</strong> 조합하는 방식이라고 하였죠? 코드를 하나하나 분석해봅시다. 🧐</p>
<ol>
<li><p>cafeData에 coffeeCount 멤버 변수와 coffeeCount 개수를 늘리는 add 메서드가 존재합니다.</p>
<p>cafeData는 coffeeCount 개수를 늘리는 <strong>역할을 하는 객체</strong>입니다.
이 add에는 <strong>자신의 멤버 변수에 접근하여</strong> 계산하였다는 점이 절차 지향 방식과의 차이 입니다.</p>
<img src="https://github.com/user-attachments/assets/72bb63cd-750d-43fd-9684-a6e32a0627f5" width="50%" />
</li>
<li><p>메인에서 cafeData 객체에서 역할 add를 꺼내 호출합니다.</p>
<p>메인에서는 CafeData의 데이터인 coffeeCount 같은 데이터는 전혀 사용하지 않습니다. CafeData를 사용하는 입장에서는 CafeData 내부에 어떤 속성이 있는지 전혀 몰라도 CafeData가 제공하는 기능 중에 필요한 기능을 호출해서 사용합니다. </p>
<blockquote>
<p>💡 이렇게 <strong>속성과 기능을 하나로 묶어서 필요한 기능을 메서드를 통해 외부에 제공하는 것</strong>을 <strong>캡슐화</strong>라고 합니다.</p>
</blockquote>
<img src="https://github.com/user-attachments/assets/4e923e7d-3c2f-47aa-bdb6-7fb508222541" width="50%" />

</li>
</ol>
<p>과정</p>
<img src="https://github.com/user-attachments/assets/83968734-a1cd-4d8d-b747-cf99b3bb74cb" width="55%" />

<h4 id="정리">정리</h4>
<ul>
<li>클래스에는 속성(멤버 변수)과 기능(메서드)을 정의할 수 있습니다.</li>
<li>객체는 자신의 메서드를 통해 자신의 멤버변수에 접근 할 수 있습니다. (객체의 메서드 내부에서 접근하는 멤버 변수는 객체 자신의 멤버 변수입니다.)</li>
</ul>
<br>

<p>다음 시간엔 생성자에 대해 알아보도록 하겠습니다!! :)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] 자바를 자바랏~! - (1) 기본형과 참조형]]></title>
            <link>https://velog.io/@dev_jiwon/Java-%EC%9E%90%EB%B0%94%EB%A5%BC-%EC%9E%90%EB%B0%94%EB%9E%8F-1-%EA%B8%B0%EB%B3%B8%ED%98%95%EA%B3%BC-%EC%B0%B8%EC%A1%B0%ED%98%95</link>
            <guid>https://velog.io/@dev_jiwon/Java-%EC%9E%90%EB%B0%94%EB%A5%BC-%EC%9E%90%EB%B0%94%EB%9E%8F-1-%EA%B8%B0%EB%B3%B8%ED%98%95%EA%B3%BC-%EC%B0%B8%EC%A1%B0%ED%98%95</guid>
            <pubDate>Sat, 03 Aug 2024 09:46:15 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요. 이번 포스팅은 한번도 포스팅해보지 않은 주제를 갖고와봤습니다.^^
요즘 스스로 기초 지식이 약하다는 판단이 들어, 기초를 다지기 위해 Java로 객체 지향 공부를 하게 되었습니다!!</p>
<h4 id="그래서-이번-포스팅은-java의-기본형과-참조형에-대해-알아보겠습니다">그래서 이번 포스팅은 Java의 기본형과 참조형에 대해 알아보겠습니다.</h4>
<h1 id="1-기본형과-참조형">1. 기본형과 참조형</h1>
<h2 id="1-기본">1. 기본</h2>
<blockquote>
<h4 id="⭐️-자바에서-참조형을-제대로-이해하는-것은-정말-중요️-⭐">⭐️ 자바에서 참조형을 제대로 이해하는 것은 정말 중요️ ⭐</h4>
</blockquote>
<p>자바의 타입은 크게 <strong>기본형</strong>과 <strong>참조형</strong>으로 나눌 수 있습니다.</p>
<h3 id="1-기본형">1) 기본형</h3>
<ul>
<li>자바가 <strong>기본으로 제공</strong>하는 데이터 타입으로, 변수에 사용하는 값을 직접 넣을 수 있는 데이터 타입.</li>
<li>개발자가 새로 정의 불가.</li>
</ul>
<blockquote>
<p><strong>😎: 기본형은 모두 소문자로 시작한다고 이해하면 편할듯!!</strong>
ex) <code>int</code>, <code>long</code>, <code>double</code>, <code>boolean</code></p>
</blockquote>
<h3 id="2-참조형">2) 참조형</h3>
<ul>
<li>데이터에 접근하기 위한 <strong>참조(주소)를 저장</strong>하는 데이터 타입</li>
<li>개발자가 정의하는 모든 클래스는 참조형</li>
<li><code>String</code>: 자바에서 String은 클래스이므로, 참조형으로 정의됨<pre><code>      그런데 문자는 매우 자주 다루기 때문에, 자바에서 기본형처럼 문자 값을 바로 대입 가능하도록 편의 기능을 제공함.</code></pre></li>
</ul>
<blockquote>
<p><strong>😎: 참조형은 모두 대문자로 시작한다고 이해하면 편할듯!!</strong>
ex) <code>String</code>, <code>객체</code>, <code>배열</code></p>
</blockquote>
<br>

<h2 id="2-계산">2. 계산</h2>
<p>위에서 소개한 기본형과 참조형은 프로그래밍의 계산에서 어떻게 쓰이는지 알아봅시다.</p>
<h3 id="1-기본형-1">1) 기본형</h3>
<p>기본형은 들어있는 값을 그대로 계산에 사용이 가능합니다.</p>
<pre><code class="language-java">int a = 10, b = 20;
int sum = a + b;</code></pre>
<h3 id="2-참조형-1">2) 참조형</h3>
<p>참조형은 들어있는 <code>참조값</code>을 그대로 사용 불가합니다.</p>
<pre><code class="language-java">class Student {
    int grade;
}</code></pre>
<pre><code class="language-java">Student s1 = new Student(); // s1 = ref.Student@a09ee92 (s1에는 주소값이 존재)
Student s2 = new Student(); // s2 = ref.Student@30f39991 (s2에는 주소값이 존재)
System.out.println(s1 + s2); // error</code></pre>
<p>Student는 타입이 기본형일까요 참조형일까요?
대문자로 시작하고, 자바가 기본으로 제공하는 데이터 타입이 아니기 때문에<code>참조형</code>입니다!!</p>
<p>s1과 s2는 참조형 인스턴스인 Student라는 객체를 할당 받았습니다.
s1, s2에는 Student 객체의 <code>참조(주소)값</code>이 존재합니다.</p>
<p>참조(주소)값은 자바 내 메모리에서 차지하는 <code>주소지</code>를 뜻합니다. 
주소지는 주소지일 뿐, 계산 할 수 있는 값이 아니기 때문에 멋대로 s1 + s2를 하게 되면 에러가 납니다...!</p>
<p>그렇다면 <code>참조형</code> 인스턴스는 어떻게 계산할까요?
주소지를 자세히 들여다봐야🧐 계산할 값이 나옵니다. 코드로 알아봅시다.</p>
<pre><code>Student s1 = new Student();
s1.grade = 100; // 값 지정

Student s2 = new Student();
s2.grade = 90; // 값 지정

int sum = s1.grade + s2.grade; // 값을 꺼내 계산함 (190)</code></pre><p>참조형 변수에 <code>.(dot)</code>을 찍어보면 값 grade가 나옵니다. s1, s2의 grade에 각각 정수 값을 지정해줍니다.
그럼 비로소 기본형에서 계산했던대로 값 계산이 가능합니다.</p>
<br>

<h2 id="3-변수-대입">3. 변수 대입</h2>
<blockquote>
<h4 id="💡-자바는-항상-변수의-값을-복사해서-대입한다">💡 자바는 항상 변수의 값을 복사해서 대입한다.!!</h4>
</blockquote>
<p>자바에서 변수에 값을 대입하는 것은 변수에 들어있는 값을 복사해서 대입하는 것입니다. 
복사해서 대입한다는 말이 무슨 말일까요? 🤔 기본형의 대입 방법부터 알아봅시다.</p>
<h3 id="1-기본형-2">1) 기본형</h3>
<p>기본형은 변수에 들어있는 <code>실제 사용하는 값</code>을 복사하여 대입합니다.</p>
<p>바로 코드로 보겠습니다!!</p>
<pre><code class="language-java">int a = 10;
int b = a; // b에 a의 값인 10을 복사해서 대입.</code></pre>
<p>위의 코드를 아래와 같이 그릴 수 있을 것입니다.</p>
<ol>
<li><p>a, b 값 할당</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/8914c796-c169-448c-954d-933e7e680ec5/image.png" width="40%" />
</li>
<li><p>a, b가 메모리 내에서 차지하는 영역</p>
<blockquote>
<p>😎: <strong>서로 같은 값을 가지지만 다른 영역에 저장됩니다.</strong></p>
</blockquote>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/2ac19a3e-bba5-464f-b46b-9cf26f3e8779/image.png" width="50%" />

</li>
</ol>
<br>

<p>결과
<strong>기본형 변수에 값을 대입시, 서로 같은 값을 가지지만 각자 주소지가 다릅니다.</strong></p>
<h3 id="2-참조형-2">2) 참조형</h3>
<p>참조형은 객체의 위치를 가리키는<code>참조(주소)값</code>을 복사하여 대입합니다.</p>
<p>바로 코드로 보겠습니다!!</p>
<pre><code class="language-java">Student s1 = new Student(); // s1 = ref.Student@a09ee92 (s1 주소값 예시)
Student s2 = s1; // s2에 s1의 주소값인 a09ee92 복사하여 대입</code></pre>
<p>위의 코드를 아래와 같이 그릴 수 있을 것입니다.</p>
<ol>
<li><p>s1, s2 값 할당</p>
 <img src="https://velog.velcdn.com/images/dev_jiwon/post/73a5919b-70b1-4875-bc29-293d31f94ca7/image.png" width="40%" />
</li>
<li><p>s1, s2가 메모리 내에서 차지하는 영역</p>
<blockquote>
<p>😎: <strong>서로 같은 영역에 저장되므로, 당연히 실제 사용하는 값도 같습니다.</strong></p>
</blockquote>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/7f3e5306-313a-41d7-95d7-465390cd0304/image.png" width="50%" />

</li>
</ol>
<p>결과
<strong>참조형 변수에 값을 대입 시, 서로 같은 값을 가지며 같은 주소지를 바라봅니다.</strong>
참조형 변수는 말 그대로 주소를 <code>참조</code>하는 변수라는 것을 알아두세요! 😝</p>
<br>

<h2 id="4-메서드-호출">4. 메서드 호출</h2>
<blockquote>
<h4 id="💡-자바는-항상-변수의-값을-복사해서-대입한다-1">💡 자바는 항상 변수의 값을 복사해서 대입한다.!!</h4>
</blockquote>
<p>메서드를 호출할 때 사용하는 매개변수(파라미터)도 변수입니다. 따라서 메서드를 호출할 때 매개변수에 값을 전달하는 것도 값을 복사하여 전달하는 방식입니다.</p>
<h3 id="1-기본형-3">1) 기본형</h3>
<p>메서드로 기본형 데이터를 전달하면 <code>실제 값</code>이 복사되어 전달됩니다. 
이 경우, 메서드 내부에서 매개변수(파라미터)의 값을 변경해도 호출자의 변수 값에는 영향이 없습니다.</p>
<p>바로 코드로 보겠습니다!! 아래 코드를 수행하면 어떻게 될까요?</p>
<pre><code class="language-java">public class changeNumberMain {
     public static void main(String[] args) {
         int a = 10;
         System.out.println(&quot;메서드 호출 전: a = &quot; + a);
         changeNumber(a);
         System.out.println(&quot;메서드 호출 후: a = &quot; + a);
    }

    static void changeNumber(int x) {
        x = 20;
    } 
}</code></pre>
<p>한 줄 한 줄 그림으로 알아봅시다!!</p>
<ol>
<li><code>int a = 10</code><img src="https://velog.velcdn.com/images/dev_jiwon/post/286b8089-140a-4ab3-921a-a04034635205/image.png" width="50%" />


</li>
</ol>
<ol start="2">
<li><p><code>changePrimitive(a)</code>
<code>changePrimitive(int x) { x = 20 }</code></p>
<img src=" https://velog.velcdn.com/images/dev_jiwon/post/498ce5be-a177-403f-8e67-f1c6dfa9550b/image.png" width="50%" />

<p>changePrimitie의 파라미터인 x에 a를 대입하면, x = a가 될 것입니다.
x가 a의 <code>실제 값</code>을 그대로 <code>복사</code> 합니다. x가 20이 될 뿐, a가 20이 되지 않습니다.</p>
</li>
<li><p>그래서 결과는?</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/3bf6e5f4-7229-44e9-be08-608fc8c91837/image.png" width="50%" />

<pre><code class="language-java">메서드 호출 전: a = 10
메서드 호출 후: a = 10</code></pre>
<p>왜⸌◦̈⃝⸍ʷʰʸˀ̣ˀ̣? 
x는 기본형 타입이므로 a와는 <strong>값만 같을 뿐 참조값이 다르기 때문이죠!!</strong></p>
</li>
</ol>
<h3 id="2-참조형-3">2) 참조형</h3>
<p>메서드로 참조형 데이터를 전달하면 <code>참조값(주소값)</code>이 복사되어 전달됩니다. 
이 경우, 메서드 내부에서 매개변수(파라미터)로 전달된 객체의 값을 변경하면 호출자의 객체도 변경됩니다.</p>
<p>바로 코드로 보겠습니다!! 아래 코드를 수행하면 어떻게 될까요?</p>
<pre><code class="language-java">Student s1 = new Student();
s1.grade = 100;
System.out.println(&quot;메서드 호출 전: s1.grade = &quot; + s1.grade);
changeGrade(s1);
System.out.println(&quot;메서드 호출 후: s1.grade = &quot; + s1.grade);

void changeGrade(Student studentS) {
  studentS.grade = 90;
}</code></pre>
<p>한 줄 한 줄 코드로 알아봅시다!!</p>
<ol>
<li><p><code>Student s1 = new Student()</code>
<code>s1.grade = 100</code></p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/91f99ff8-bb83-4d19-9d40-8288f9e6ee8e/image.png" width="50%" />
</li>
<li><p><code>changeGrade(s1)</code>
<code>changeGrade(Student studentS) {
studentS.grade = 90
}</code></p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/87dc8b7c-3d1e-434e-8425-327139d65140/image.png" width="50%" />

<p>changeGrade의 파라미터인 studentS에 s1을 대입하면, studentS = s1이 될 것입니다. studentS는 참조형 객체죠? 그러므로 studentS와 s1는 같은 참조(주소)값을 바라보게 될 것입니다. </p>
<br>

<p>studentS의 grade 값을 90으로 바꿔도 s1의 grade도 같이 90으로 바뀝니다.</p>
</li>
<li><p>그래서 결과는?</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/81ef9314-3e56-45a2-9033-5f3cf2c0fe4c/image.png" width="50%" />

<p>a09ee92(주소값 예시)의 참조(주소)값에는 grade 90을 가지고 있으며, s1과 studentS가 둘다 동일한 참조(주소)값을 바라보고 있습니다!!!</p>
</li>
</ol>
<br>

<h2 id="5-변수와-초기화">5. 변수와 초기화</h2>
<h3 id="1-변수의-종류">1) 변수의 종류</h3>
<p>자바에서 변수는 크게 멤버 변수와 지역 변수로 나눌 수 있습니다.
각각 무엇인지 알아봅시다!!</p>
<h4 id="1-멤버-변수-필드">1. 멤버 변수 (필드)</h4>
<ul>
<li><p><code>클래스</code>에 선언된 변수</p>
<p>바로 코드로 보겠습니다!!</p>
<pre><code class="language-java">public class Student {
  String name; // 멤버 번수(필드)
  int age; // 멤버 변수(필드)
  int grade;  // 멤버 번수(필드)
}</code></pre>
</li>
</ul>
<h4 id="2-지역-변수">2. 지역 변수</h4>
<ul>
<li><p>지역 변수는 <code>메서드</code>에 선언된 변수를 말하며, 메서드가 끝나면 제거되는 변수</p>
</li>
<li><p>매개변수도 지역 변수의 한 종류</p>
<p>바로 코드로 보겠습니다!!</p>
<pre><code class="language-java">public class StudentMain {
   public static void main(String[] args) {
       int a = 1; // 지역 변수
       Student student1; // 지역 변수
       student1 = new Student();
       Student student2 = new Student(); // 지역변수
}
}</code></pre>
</li>
</ul>
<h3 id="2-변수의-값-초기화">2) 변수의 값 초기화</h3>
<p>멤버 변수(필드)와 지역 변수의 초기화가 어떻게 되는지 알아봅시다!</p>
<h4 id="1-멤버-변수-필드--자동-초기화">1. 멤버 변수 (필드) : 자동 초기화</h4>
<ul>
<li><p>인스턴스를 생성할 때 자동으로 초기화
ex) <code>int = 0</code>, <code>boolean = false</code>, <code>참조형 = null</code></p>
</li>
<li><p>개발자가 초기값 직접 지정 가능합니다!</p>
<p>바로 코드로 보겠습니다!!</p>
<pre><code class="language-java">public class Student {
  String name; // 초기화 안했으므로 null로 초기화 됨
  int age; // 초기화 안했으므로 0으로 초기화 됨
  int grade = 90;  // 90으로 직접 초기화
}</code></pre>
</li>
</ul>
<h4 id="2-지역-변수--수동-초기화">2. 지역 변수 : 수동 초기화</h4>
<ul>
<li><p>개발자가 항상 직접 초기화해야합니다!</p>
<p>바로 코드로 보겠습니다!!</p>
<pre><code class="language-java">public class StudentMain {
   public static void main(String[] args) {
       Student student = new Student();
       System.out.println(student.name); // null
       System.out.println(student.age); // 0
       System.out.println(student.grade); // 90
}
}</code></pre>
</li>
</ul>
<h3 id="3-null">3) null</h3>
<p>위에서 멤버 번수(필드)의 참조형 변수는 <code>null</code>로 초기화 한다고 하였습니다. 
<code>null</code>은 아직 가리키는 대상이 없다, 존재하지 않는, 혹은 없다는 뜻 입니다.</p>
<p>바로 코드로 보겠습니다!!</p>
<pre><code class="language-java">public class Data {
  int value;
}</code></pre>
<pre><code class="language-java">   public class DataMain {
       public static void main(String[] args) {
           Data data = null; // 1.
           data = new Data(); // 2.
           data = null; // 3.
    }
  }</code></pre>
<p>위와 같은 코드를 한 줄 한 줄 자세히 살펴보며 메모리에 어떻게 적재되는지 살펴봅시다! 🧐</p>
<ol>
<li><p><code>Data data = null</code></p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/657f2c9d-ff2d-471f-8db7-1533878a17f1/image.png" width="50%" />

<p>Data의 타입을 갖는 data의 객체를 null로 초기화합니다.</p>
<ol start="2">
<li><code>data = new Data()</code></li>
</ol>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/43d654a7-d815-4365-a527-f70032b6edf9/image.png" width="50%" />

<p>data의 타입을 가진 참조형 변수에 Data 인스턴스 지정합니다. data는 참조형 변수이므로, data에는 데이터에 접근하기 위한 Data 인스턴스의 참조(주소)값을 저장합니다. Data의 값으론 value가 있습니다. (value는 자동 초기화로 인해 0으로 초기화 됨)</p>
<ol start="3">
<li><code>data = null</code></li>
</ol>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/047c35ff-1393-4b7b-8fbf-98d8b71877cc/image.png" width="50%" />
data의 객체를 다시 `null`로 할당하였습니다. 이렇게 되면 data가 Data 인스턴스를 참조하던 것을 해제하게 됩니다!!

<p><strong>(⭐️ data는 더이상 Data 인스턴스를 참조하지 않습니다. ⭐️)</strong></p>
</li>
</ol>
<br>

<h4 id="garbage-collection--쓰레기-수집기">Garbage Collection : 쓰레기 수집기</h4>
<br>
<img
src="https://velog.velcdn.com/images/dev_jiwon/post/3ab5e01b-c890-4c67-bb94-c087746fe2bd/image.png" width="50%" />

<p>위 3번에서 data는 더이상 Data 인스턴스를 참조하지 않는다고 하였습니다.</p>
<p>이 부분을 자세히 들여다보겠습니다. data에 null을 할당하면서 data는 Data의 인스턴스의 참조를 해제하였습니다. 이렇게 아무것도 참조하지 않게 되면 Data의 인스턴스는 갈 길을 잃게 됩니다...🥲 (data: 나 누구 참조해?🥲)</p>
<p>자바에서 객체는 해당 객체를 참조하는 곳이 있으면 JVM이 종료할 때까지 계속 생존합니다. 그런데 중간에 해당 객체를 참조하는 곳이 모두 사라지면 그때 JVM은 <strong>⭐️필요 없는 객체로 판단하고 GC(Grabage Collection)를 사용해서 제거하게 됩니다.⭐️</strong></p>
<p>그래서 ref.Data@a09ee92(참조값 예시) 참조값을 가지는 Data 인스턴스는 JVM의 GC에 의해 제거되었습다. 😋</p>
<h3 id="4-nullpointerexception">4) NullPointerException</h3>
<p>참조형 변수에 . (dot)을 사용하면 해당 객체를 찾아갈 수 있습니다. 만약 참조형 변수가 <code>null</code>을 가리킨다면 값이 없다는 뜻이므로, 찾아갈 수 있는 객체(인스턴스)가 없습니다.🥲 <code>NullPointerException</code> 은 null 에 . (dot)을 찍었을 때 발생합니다. </p>
<p>바로 코드로 보겠습니다!!</p>
<pre><code class="language-java">   public class DataMain {
       public static void main(String[] args) {
           Data data = null;
           System.out.println(&quot;data.value = &quot; + data.value); // NullPointerException
    }
  }</code></pre>
<p>이 경우 <code>NullPointerException</code>이라는 예외가 발생하고, 프로그램이 종료됩니다. <code>NullPointerException</code>은 이름 그대로 null 을 가리켜서(Pointer) 예외가 발생했다는 의미입니다. <code>null</code>은 없다는 뜻이므로, 결국 주소가 없는 곳을 찾아갈 때 발생하는 예외입니다.</p>
<p>결과</p>
<pre><code>Exception in thread &quot;main&quot; java.lang.NullPointerException: Cannot read field &quot;value1&quot; because &quot;data&quot; is null
    at ref.initMain.main(initMain.java:8) // NullPointerException 발생

Process finished with exit code 1 // 프로그램 종료</code></pre><p>다음 시간엔 <a href="https://velog.io/@dev_jiwon/Java-%EC%9E%90%EB%B0%94%EB%A5%BC-%EC%9E%90%EB%B0%94%EB%9E%8F-2-%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%8D">객체 지향 프로그래밍</a>에 대해 알아보겠습니다!! :)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React Native] React Native 구동 원리 (feat. old Architecture)]]></title>
            <link>https://velog.io/@dev_jiwon/React-Native-%EB%B8%8C%EB%A6%BF%EC%A7%80-%EB%B0%A9%EC%8B%9D-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC</link>
            <guid>https://velog.io/@dev_jiwon/React-Native-%EB%B8%8C%EB%A6%BF%EC%A7%80-%EB%B0%A9%EC%8B%9D-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC</guid>
            <pubDate>Sat, 20 Apr 2024 17:37:24 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요<del>~</del> 오랜만에 React Native 포스팅으로 만나뵙습니다!! 🥹🥹</p>
<p>React Native에 새롭게 등장한 새로운 아키텍처 대해 아시나요? 오늘은 새로운 아키텍쳐에 대해 알아보기 전에<del>~</del> 구 아키텍처의 흐름에 대해 먼저 알아보려고 합니다.</p>
<br>

<h2 id="들어가며">들어가며</h2>
<p>React Native는 React 와 동일한 메커니즘을 사용할 수 있도록 하여 Android, iOS에 맞는 API를 사용하여 어플리케이션에 UI를 그리게 됩니다.</p>
<p>JavaScript로 React, JSX를 통해서 컴포넌트를 구성하지만, 실제로는 우리가 작성한 JavaScript 코드가 실행되는 영역과 UI를 그려주는 네이티브 영역은 분리되어 있습니다. </p>
<p>어떻게 React Native 에서는 우리가 작성한 JSX 표현식을 가지고 네이티브 UI를 그리고 있을까요? 🤔🤔</p>
<br>

<h2 id="브릿지">브릿지</h2>
<p>React Native 프로젝트를 실행하면 2개의 스레드가 동시에 동작합니다. </p>
<ul>
<li>Native 스레드: 네이티브 영역 담당</li>
<li>JS 스레드: JavaScript 코드가 실행되는 영역 담당</li>
</ul>
<p><em>(*스레드: 명령어를 실행하여 처리하는 주체로, 가장 작은 작업의 단위로 볼 수 있다.)</em></p>
<p>React Native는 JS 스레드와 Native 스레드가 서로 소통할 수 있도록 통로를 만들어 두었습니다. 이 통로를 Bridge라고 합니다. Bridge는 두 스레드 사이에서 서로 메세지-큐 방식으로 소통합니다.</p>
<p>React Native에서는 JSX를 통해 컴포넌트를 작성하게 되면 JSON으로 직렬화한 문자열을 Bridge를 통해 Native 스레드로 전달하게 되며, Native 스레드에서는 다시 역직렬화를 하여 네이티브 API 형식에 맞춰 UI를 그려주게 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/dev_jiwon/post/8a471d3c-815b-46f6-9086-94c02a4fe124/image.png" alt=""></p>
<blockquote>
<p>🤓: 예를들어, React Native에서 View, Text의 컴포넌트를 호출하면,
iOS에서는 UIView와 UILable을,
Android에서는 android.view.ViewGroup, android.view.TextView를 호출하게 됩니다.</p>
</blockquote>
<br>

<p>반대로 Native 스레드에서 JS 스레드로 이벤트를 전달하는 경우도 있습니다. 🤩
유저와 화면과의 interaction이 발생하면 Native 스레드에서 JSON으로 직렬화한 문자열을 Bridge를 통해 JS 스레드의 이벤트로 들어오게 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/dev_jiwon/post/2d4ca304-7fff-4850-ab23-e1425d1d5179/image.png" alt=""></p>
<blockquote>
<p>🤓: 예를들어, iOS 혹은 Android 기기에서 버튼을 클릭 시, React Native의 버튼 컴포넌트(ex. TouchableOpacity)의 onPress로 이벤트가 들어오게 됩니다. 위의 예시로 보자면 &quot;클릭!&quot;의 문자열이 로그로 찍히겠죠? 😊</p>
</blockquote>
<p>단순히 View와 Text만 작성해서 추가할 뿐만 아니라, 컴포넌트의 사이즈, 색상 그리고 위치는 어떻게 할 것인지와 같은 스타일 코드를 작성하게 됩니다. React Native 에서는 이러한 레이아웃 스타일을 Native 스레드에 보내기 위해 레이아웃 엔진인 <strong>Yoga</strong>를 사용하고 있습니다.</p>
<br>

<h3 id="1-yoga">1. Yoga</h3>
<p>Yoga는 C++로 작성된 <strong>레이이웃 엔진</strong>으로 다양한 프로그래밍 언어에서 사용할 수 있는 오픈소스 라이브러리입니다. 기본적으로 React Native 와 함께 작동하기 위해서 설계 되었다고 합니다. React Native는 각 플랫폼에 맞는 UI 구성 요소에 대한 세부사항을 알 필요없이 Yoga를 통해 다양한 화면 크기, 해상도 및 유형에 최적화 된 인터페이스를 만들 수 있게 됩니다.</p>
<p>Yoga는 일반적으로 iOS 네이티브 기본 구성요소인 Auto Layout과 UIStackView로 레이아웃을 구성하는 것보다 빠르게 렌더링 된다고 합니다. 
(* 하지만 단순하게 비교한 것이며 복잡한 구성에 따라 벤치마킹 결과도 다를 수 있습니다.)</p>
<br>

<img src="https://velog.velcdn.com/images/dev_jiwon/post/bb3fa943-1058-41f2-8638-98353d700c80/image.png" width="70%" />


<p>(* Flexlayout이 Yoga 입니다. 자세한건 <a href="https://github.com/layoutBox/LayoutFrameworkBenchmark">여기</a>를 참고해주세요.)</p>
<p>단순히 일부 네이티브 영역의 렌더링 속도만 빨라서는 크게 의미는 없습니다. React Native에서는 단순히 레이아웃을 그리는 것 뿐만 아니라 더 다양한 것들을 구성하고 브릿지라는 메커니즘을 통해 네이티브와 소통하기 때문에, Yoga를 사용한다고 해서 네이티브보다 더 빠르게 작동하는 것은 아닙니다. </p>
<p>이러한 Yoga는 JS 스레드와 Native 스레드를 연결해주는 Bridge에서 작동하고 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/dev_jiwon/post/c1e5cc43-be74-41b6-bcf3-6ca5949a8ab5/image.png" alt=""></p>
<br>

<h3 id="2-렌더-파이프라인">2. 렌더 파이프라인</h3>
<p>React 로직을 호스트 플랫폼에 렌더링하기 위한 일련의 작업을 <strong>렌더 파이프라인</strong>이라고 합니다.</p>
<p>렌더 파이프라인은 일반적으로 세 가지 단계로 나눌 수 있습니다.</p>
<ol>
<li>Render Phase</li>
<li>Commit Phase</li>
<li>Mount Phase</li>
</ol>
<br>

<p>아래의 코드는 렌더 파이프에 의해 어떻게 작동될까요?</p>
<pre><code>&lt;View
    style={{
        width: 200,
        height: 200,
        backgroundColor: &quot;blue&quot;
    }}
&gt;
    &lt;Text&gt;Hello World&lt;/Text&gt;
&lt;/View&gt;</code></pre><br>

<p><strong>1. Render Phase</strong>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/c267eb6e-09a1-4018-82e0-93d82cb3348e/image.png" alt=""></p>
<ol>
<li><p>React는 JavaScript로 React Element Tree 생성
 View, Text 컴포넌트와 1:1 관계를 가진 React Element Tree를 생성합니다.</p>
</li>
<li><p>Yoga는 이에 맞는 React Shadow Tree 생성
Yoga는 생성된 React Element Tree의 레이아웃을 가진 React Shadow Tree를 생성합니다.
React Shadow Tree는 React Shadow Node로 구성되어 있습니다.</p>
<blockquote>
<p><strong>React Shadow Node</strong>: 마운트할 Component를 나타내는 객체</p>
</blockquote>
<p>렌더러는 업데이트의 성능을 높이기 위해, React Shadow Tree를 복제하여 복제된 Tree에서 React Shadow Node를 업데이트 합니다. (자세한 내용은 다음에 포스팅 하겠습니다!!^^)</p>
</li>
</ol>
<br>

<p><strong>2. Commit Phase</strong></p>
<p><img src="https://velog.velcdn.com/images/dev_jiwon/post/bbe1c1f4-dac7-4ab2-9a8b-6f1b68d27580/image.png" alt=""></p>
<p>React Native에서는 React Element에서 시작되는 각 React Shadow Node 의 스타일이 필요합니다. Yoga는 React Shadow Node의 위치과 크기를 계산합니다.</p>
<br>

<p><strong>3. Mount Phase</strong>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/2a98993d-8fda-4cc9-b8ad-d814e03a356c/image.png" alt=""></p>
<p> 크기와 위치가 계산된 레이아웃 정보를 가진 React Shadow Node를 Host View Tree로 변환하여 UI로 렌더링합니다.</p>
<br>

<h3 id="3-브릿지-방식-프레임워크-단점">3. 브릿지 방식 프레임워크 단점</h3>
<p>이러한 Bridge 방식 프레임워크에는 단점이 있습니다.</p>
<p>Bridge를 통해 렌더링에 필요한 데이터들을 주고 받는 모든 과정은 비동기로
작동합니다. 이벤트에 대해서 응답할 수 없거나, 이미 요청해버린 렌더링이나 작업들에 대해선 중간에 취소할 수 없습니다. 또한 이 과정에서 모두 JSON 직렬화와 역직렬화가 일어나기 때문에 불필요한 오버헤드가 발생하게 됩니다.</p>
<p>그리고 Bridge는 단일 스레드이므로 우선순위가 없습니다. Bridge는 단일 스레드이고, 코드가 모두 직렬화되어 전달되므로 중요한 부분에 우선순위 없이 코드를 전달하게 됩니다.</p>
<p>예를 들어, 무거운 작업이 필요한 많은 수의 항목을 가진 리스트를 만든다고 가정해봅시다. 사용자가 엄청나게 빠르게 리스트를 스크롤 하면, 스크롤 도중 중간 중간에 빈 리스트 화면이 보이게 됩니다. </p>
<p>아래와 같은 과정을 통해서요.</p>
<blockquote>
<ol>
<li>JS 스레드 -&gt; Native 스레드: 리스트 렌더링 요청<ol start="2">
<li>사용자가 엄청 빠르게 리스트 스크롤</li>
<li>Native 스레드 -&gt; JS 스레드 : 스크롤 이벤트 전송
// 4번을 받기 전에 빈 화면을 보게 됩니다.</li>
<li>JS 스레드 -&gt; Native 스레드 : 리스트 렌더링 요청</li>
</ol>
</li>
</ol>
</blockquote>
<p>이러한 일련의 과정이 빈번하고, 무거운 요소들을 그리고, 동기적인 기능들이 중간에 배치된다면 스크롤 도중 빈 영역을 만나게 될 수 있습니다.</p>
<p>이러한 문제를 개선하기 위해서 React Native 팀에서는 몇 년전 부터 새로운 아키텍쳐에 대해서 발표했고, 꾸준히 업데이트 하고 있습니다. 새로운 아키텍쳐는 불필요하게 오버헤드를 불러오는 Bridge를 없애기로 결정하였습니다. </p>
<p>그러면 Bridge 없이 어떻게 두 영역에서 소통할 수 있을까요?
정답은 바로바로<del>~</del> 다음 게시물에서 뵙겠습니다.^^</p>
<p><br><br><br></p>
<p>참고</p>
<p><a href="https://velog.io/@heejin62/React-Native-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC-%EC%9E%91%EB%8F%99-%EC%9B%90%EB%A6%AC-%EA%B0%80%EC%83%81-DOM%EA%B3%BC-%EB%A0%8C%EB%8D%94%EB%A7%81#%EA%B0%80%EC%83%81-dom">https://velog.io/@heejin62/React-Native-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC-%EC%9E%91%EB%8F%99-%EC%9B%90%EB%A6%AC-%EA%B0%80%EC%83%81-DOM%EA%B3%BC-%EB%A0%8C%EB%8D%94%EB%A7%81#%EA%B0%80%EC%83%81-dom</a></p>
<p><a href="https://reactnative.dev/architecture/render-pipeline#react-state-updates">https://reactnative.dev/architecture/render-pipeline#react-state-updates</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Security] JWT(Json Web Token)에 대하여]]></title>
            <link>https://velog.io/@dev_jiwon/Security-JWT-Json-Web-Token</link>
            <guid>https://velog.io/@dev_jiwon/Security-JWT-Json-Web-Token</guid>
            <pubDate>Sun, 03 Mar 2024 16:58:38 GMT</pubDate>
            <description><![CDATA[<h2 id="0-들어가며">0. 들어가며</h2>
<p>안녕하세요~~😄
<a href="https://velog.io/@dev_jiwon/Security-%EC%BF%A0%ED%82%A4Cookie%EC%99%80-%EC%84%B8%EC%85%98Session">저번 시간</a>에는 세션 인증 방식에 대해 알아보았는데요, 이번엔 사용자를 인증 및 인가하는 다른 방식인 토큰 인증 방식에 대해 알아보려고 합니다.</p>
<p>토큰 인증 방식은 클라이언트에서 인증 정보를 보관하는 방식 입니다.
저번에 배운 세션 인증 방식은 매 요청마다 세션 DB를 통해 세션id를 조회했어야했는데요, 그렇게 되면 서버에 부담이 되었기 때문에 토큰 인증 방식이 생겼습니다.</p>
<p>비록 클라이언트에 저장해서 보안에 대한 걱정이 들 수도 있지만, 토큰은 유저 정보를 암호화한 상태로 담기 때문에 클라이언트에 담아도 괜찮습니다.</p>
<p>토큰에는 여러 종류가 있습니다. 그 중에서 개방형이고 웹에서 널리 쓰이는 JWT에 대해서 알아보겠습니다. 🙂</p>
<br>

<h2 id="1-jwtjson-web-token">1. JWT(Json Web Token)</h2>
<h3 id="1-jwt란">1. JWT란?</h3>
<p>JWT(Json Web Token)은 Json 객체에 인증에 필요한 정보들을 담은 후 비밀키로 서명한 토큰으로, 인터넷 표준 인증 방식 입니다.</p>
<p><a href="https://jwt.io/">여기</a>에 들어가보시면 JWT를 디코딩 할 수 있고, 디코딩된 토큰을 수정하여 다시 인코딩 할 수도 있습니다.</p>
<h3 id="2-jwt-구성-요소">2. JWT 구성 요소</h3>
<p>JWT는 각각의 구성 요소가 .으로 구분이 되어있으며, header, payload, signature로 구성되어있습니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/61e42795-db69-4e74-859a-e1bd686d3fdd/image.png" width="80%"/>

<p>이 세 부분을 하나하나씩 확인하여 JWT가 어떻게 구성되어있는지 알아봅시다.</p>
<h4 id="1-header">1. HEADER</h4>
<p>Header에는 해시 암호화 알고리즘과 토큰의 유형이 담겨있습니다.</p>
<p>해시 암호화 알고리즘은 대표적으로 <strong>RS256</strong>(공개키/개인키)와 <strong>HS256</strong>(비밀키(대칭키))가 있습니다. (*해시 암호화 알고리즘에 대해 궁금하신 분들은 <a href="https://auth0.com/docs/get-started/applications/signing-algorithms">여기</a> 참고하시면 됩니다.)</p>
<pre><code class="language-js">{
  &quot;alg&quot;: &quot;HS256&quot;, // 해시 암호화 알고리즘 (algorithm)
  &quot;typ&quot;: &quot;JWT&quot; // 토큰 유형 (type)
}</code></pre>
<blockquote>
<p>🤓: 가끔 어떤 서버에서는 alg에 &quot;none&quot;을 넣는 경우에도 인증시켜주는 경우가 있습니다. alg 검사를 주의해서 할 수 있도록 해야합니다!</p>
</blockquote>
<h4 id="2-payload">2. PAYLOAD</h4>
<p>Payload에는 토큰에서 사용할 정보의 조각들인 클레임(Claim)이 담겨 있습니다. Claim에는 어떤 값이 들어가든 개발자 재량이지만, 아래와 같은 표준 스펙으로 정의 할 수도 있습니다.</p>
<pre><code class="language-js">{
  &quot;iss&quot;: &quot;jieonist&quot;, // 토큰 발급자 (issuer)
  &quot;sub&quot;: &quot;1234567890&quot;, // 토큰 제목 - 사용자에 대한 식별값 (subject)
  &quot;aud&quot;: &quot;jiveloper&quot;, // 토큰 대상자 (audience)
  &quot;exp&quot;: 1716239022 // 토큰 만료 시간 (expired)
  &quot;nbf&quot;: 1716239022 // 토큰 활성 날짜 - 이 날짜 이전의 토큰은 활성화 되지 않음을 보장 (not before)
  &quot;iat&quot;: 1709320002, // 토큰 발급 시간 (issued at)
  &quot;jti&quot;: &quot;id1&quot; // JWT 토큰 식별자 - issuer가 여러명일 때 이를 구분하기 위한 값 (JWT id)
}</code></pre>
<p>위의 스펙은 모두 포함해야하는 것은 아니며, 해당 서버가 가져야할 인증 체계에 따라 자유롭게 사용하시면 됩니다.</p>
<blockquote>
<p>🤓: JWT는 누구나 복호화하기 쉽기 때문에, Payload에는 예민한 개인 정보를 넣으면 유출되기 쉽겠죠? 가급적 Payload에는 사용자를 식별할 수 있는 아이디 정도만 저장하는 것이 좋으며, 해당 사용자에 대한 추가 정보가 필요한 경우에는 서버에서 사용자 DB를 조회하는 것이 안전할 것입니다. 불가피한 이유로 Payload에 민감한 사용자 정보를 저장해야한다면 <strong>반드시 암호화를 하여 JWT 토큰을 디코딩한 후에도 알아볼 수 없게 해야할 것</strong>입니다.</p>
</blockquote>
<h4 id="3-signature">3. SIGNATURE</h4>
<p>Signature에는 가장 중요한 서명 값이 담겨있는데요, 
Header + Payload + Header에서 선언한 알고리즘 + key를 합쳐 암호한 값이 담겨있습니다.</p>
<pre><code class="language-js">HMACSHA256(
  base64UrlEncode(header) + &quot;.&quot; +
  base64UrlEncode(payload), 
  [your-256-bit-secret]
) secret base64 encoded</code></pre>
<p>Header와 Payload는 단순히 base64Url로 인코딩되어 있어 누구나 쉽게 복호화할 수 있지만, <strong>Signature는 key가 없으면 복호화할 수 없습니다.</strong> 개인키로 서명했다면 공개키로 유효성 검사를 할 수 있고, 비밀키로 서명했다면 비밀키를 가지고 있는 사람만이 암호화 복호화, 유효성 검사를 할 수 있습니다.</p>
<blockquote>
<p>🤓: secret key를 흔한 값으로 하게 되면 <a href="https://lee-automation-lab.tistory.com/entry/IT-%EB%B3%B4%EC%95%88-%EB%AC%B4%EC%B0%A8%EB%B3%84-%EB%8C%80%EC%9E%85-Brute-Force-%EA%B3%B5%EA%B2%A9%EC%9D%B4%EB%9E%80">brute force attack</a>을 당할 수 있습니다.</p>
</blockquote>
<br>

<h2 id="2-jwt의-토큰-인증-방식">2. JWT의 토큰 인증 방식</h2>
<h3 id="1-동작-과정">1. 동작 과정</h3>
<p>서버와 클라이언트간의 토큰을 통한 통신 과정을 조금 더 자세히 알아보겠습니다.</p>
<h4 id="1-사용자-인증하기-feat-토큰-생성-과정">1. 사용자 인증하기! (feat. 토큰 생성 과정)</h4>
<p>JWT를 통해 어떻게 인증이 되는지 그림을 통해 알아봅시다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/8734fad2-9a00-46c3-a82c-f5414c0bd918/image.png" width="80%" />

<ol>
<li>클라이언트에서 사용자는 아이디(id) 및 비밀번호(pw)를 입력합니다.</li>
<li>클라이언트는 서버로 사용자가 입력한 아이디와 비밀번호를 전달합니다.</li>
<li>서버는 전달 받은 정보를 바탕으로 유저가 유효하다면 비밀키를 사용해 json 객체를 암호화한 JWT를 발급합니다.
(*유저가 유효하지 않다면 로그인을 실패한 것이므로 토큰을 발급하지 않습니다.)</li>
</ol>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/ca44280e-4f16-4100-8002-bd07db165026/image.png" width="80%" />

<ol start="4">
<li>토큰이 발급되었다면 서버는 클라이언트로 토큰과 response를 전달합니다.</li>
</ol>
<ul>
<li>토큰을 헤더 혹은 response로 보냅니다.
(* 만약 토큰이 발급되지 않았다면 로그인에 실패했다는 에러 메세지가 담긴 response를 보낼 것입니다.)</li>
</ul>
<ol start="5">
<li>클라이언트는 JWT를 저장합니다.</li>
</ol>
<h4 id="2-데이터-송수신-방법">2. 데이터 송수신 방법</h4>
<p>이제 클라이언트는 토큰을 받아서 인증도 했겠다, 서버로부터 인가도 받아보겠습니다.</p>
<p>먼저, 클라이언트에서 서버로 데이터를 요청해보겠습니다.</p>
<ul>
<li>데이터 송신 방법<img src="https://velog.velcdn.com/images/dev_jiwon/post/910c602f-94b8-486a-8600-c070cad4e42c/image.png" width="80%"/>
  1. 클라이언트는 저장된 JWT 토큰을 Authorization 헤더에 담아 서버에 데이터를 요청합니다.
  2. 서버는 헤더를 매번 확인하여 JWT의 만료 기간 등 JWT가 신뢰할만한지 체크합니다.


</li>
</ul>
<ul>
<li>데이터 수신 방법<img src="https://velog.velcdn.com/images/dev_jiwon/post/1912f991-2f6b-4a23-9e70-6024d233d9fc/image.png" width="80%" />
  3. 서버는 reqeust에 대한 response를 전달합니다.
> 🙂: JWT가 유효하면 인증된 사용자이므로 사용자에게 필요한 기능을 인가하고, 유효하지 않으면 인증 처리를 해주지 않습니다. 당연히 필요한 기능에 대해 인가 받지 못 할테구요.

</li>
</ul>
<br>

<h3 id="2-refresh-token을-활용한-토큰-리프레시">2. refresh token을 활용한 토큰 리프레시</h3>
<p>만약 클라이언트에서 만료된 JWT를 가지고 서버에 api 요청을 하면 어떻게 될까요? 서버에서는 토큰을 재발급 받을 수 있도록 해주어야 할 것입니다. 토큰을 발급 받으려면 로그인을 해야하는데, 그럼 토큰이 만료될 때마다 재로그인을 해야하는 것일까요? 일반적인 서비스를 생각해보았을 때, 서비스 이용 도중에 로그인이 풀리면 매우 불편할 것입니다. 
(물론, 은행이나 정부24 같이 개인 정보가 예민한 서비스는 시간을 따로 연장하지 않는 이상 로그인이 금방 풀려 재로그인을 하는 것이 일반적입니다.)</p>
<p>일반적인 서비스에서 재로그인을 하지 않아도 만료된 토큰을 갱신 시키는 방법에 대해 알아봅시다. 🤔 </p>
<blockquote>
<p>🤓: 우리는 api를 요청할 때마다 Authorization 헤더에 토큰을 실어서 요청해야하므로, 토큰이 만료 되면 새로운 토큰을 발급 받아 새 토큰을 헤더에 넣어주어야겠습니다. Authorization 헤더에 넣는 토큰을 accessToken이라고 하며, 그 accessToken을 갱신 시키기 위한 토큰을 refreshToken이라고 합니다.</p>
</blockquote>
<h4 id="1-사용자-인증하기-feat-토큰-생성-과정-1">1. 사용자 인증하기! (feat. 토큰 생성 과정)</h4>
<p>로그인을 통해 사용자를 인증하는 방법은 위에서 본 것과 유사합니다. 다만, JWT가 accessToken으로 대체 되었고, accessToken 재발급을 위한 refreshToken이 추가되었다는 점이 다릅니다! 😄</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/f43cc469-722a-4699-8649-d37264d5606d/image.png" width="80%" />
로그인을 할 때는 JWT 대신 accessToken과 refreshToken을 발급 시켜줍니다.

<img src="https://velog.velcdn.com/images/dev_jiwon/post/ab0a1af7-c202-4da9-8c0f-1c57f3a997f1/image.png" width="80%" />
클라이언트는 accessToken과 refreshToken 모두 저장합니다.

<h4 id="2-데이터-송수신-방법-1">2. 데이터 송수신 방법</h4>
<p>데이터 송수신 방법도 위에서 본 것과 유사합니다. 다만, JWT가 accessToken으로 대체 된 점이 다릅니다! 😄</p>
<ul>
<li><p>데이터 송신 방법</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/6322adff-7ca8-4de3-a323-907c5db98bcd/image.png" width="80%" />
클라이언트는 저장된 accessToken을 Authorization 헤더에 담아 서버에 데이터를 요청합니다.
</li>
<li><p>데이터 수신 방법</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/1912f991-2f6b-4a23-9e70-6024d233d9fc/image.png" width="80%" />

</li>
</ul>
<h4 id="3-refreshtoken으로-accesstoken-갱신하기">3. refreshToken으로 accessToken 갱신하기</h4>
<p>1, 2번은 처음 위에서 소개드린 JWT 동작 과정과 매우 유사해서 크게 다를 것이 없었습니다. 이제부터 소개드릴 것이 <strong>⭐️ 뽀인뜨 ⭐️</strong> 인데요! 🤩</p>
<p>만료된 accessToken을 보낸 경우, refreshToken으로 accessToken을 갱신시키는 방법입니다!!</p>
<p>자자.. 차근차근 알아봅시다 ㅎ</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/1aa703b8-da12-47bf-8958-5b8b3022ffc1/image.png" width="80%" />

<ol>
<li>클라이언트에서 만료기간이 끝난 accessToken을 담아 api를 요청합니다.</li>
<li>서버에서는 accessToken을 검증하고, 유효하지 않음을 판단합니다.</li>
<li>서버에서 클라이언트로 401 에러 코드를 반환합니다.
(*401 status code는 권한이 없다는 응답 코드입니다. 더 궁금하시면 <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401">여기</a>를 참고하시면 됩니다.)</li>
</ol>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/ca683830-69e1-42d9-8e34-844866db5e18/image.png" width="80%" />

<ol start="4">
<li>401 에러코드를 받은 클라이언트는 refreshToken을 가지고 accessToken을 갱신시키는 api를 호출합니다.</li>
<li>해당 api에서는 새 accessToken을 발급해줍니다.</li>
<li>클라이언트는 기존 accessToken 대신 새 accessToken을 저장합니다.</li>
</ol>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/b0452021-7d1d-423b-a3cb-aead8caa09bd/image.png" width="80%" />

<ol start="7">
<li>클라이언트는 Authorization 헤더에 새 accessToken을 담아 1번에서 에러 났던 api를 재요청 합니다.</li>
<li>서버에서 accessToken 유효성 검증을 합니다.</li>
<li>서버는 reqeust에 대한 response를 전달합니다.</li>
</ol>
<blockquote>
<p>😊: 한 줄로 요약하자면!
<strong>api 요청시 401 에러를 반환 받으면 새 accessToken을 갱신 받아 api를 재요청 한다.</strong></p>
</blockquote>
<br>

<h3 id="3-장단점">3. 장단점</h3>
<h4 id="1-장점">1. 장점</h4>
<ul>
<li><a href="https://velog.io/@dev_jiwon/Security-%EC%BF%A0%ED%82%A4Cookie%EC%99%80-%EC%84%B8%EC%85%98Session#2-%EC%84%B8%EC%85%98-session">세션 인증 방식</a>과는 달리 매 요청마다 서버에서 DB를 조회하지 않고 토큰의 유효성 검사만 하면 되므로, 세션 인증 방식보다 서버의 부하가 적게 듭니다.</li>
<li>JWT를 클라이언트에 저장하기 때문에 서버 용량에 영향을 끼치지 않습니다.</li>
<li>사용자가 늘어나더라도 사용자 인증을 위해서 추가로 투자해야하는 인프라 비용을 크게 절감할 수 있습니다.</li>
</ul>
<h4 id="2-단점">2. 단점</h4>
<ul>
<li>아까 보셨듯이 <a href="https://jwt.io/">여기</a>에 들어가보시면 JWT를 디코딩하기 매우 쉽기 때문에 예민한 정보를 넣으시면 개인 정보가 유출될 가능성이 있습니다.</li>
<li>강제 로그아웃과 같은 세션이 필요한 기능은 당연히 사용할 수 없습니다.</li>
<li>토큰이 한번 탈취되면 토큰의 만료 기간이 끝날 때까지 토큰은 누군가로부터 사용될 수 있습니다...<blockquote>
<p><strong>❗️ 예방법</strong></p>
</blockquote>
</li>
</ul>
<p>1.JWT를 HttpOnly를 설정한 쿠키에 저장한다.
2.JWT 블랙리스트를 추가한다.
-&gt; 이 방법은 매번 JWT를 받아 블랙리스트에 있는지 조회하는 방법인데, 이러면 토큰 인증 방식만의 장점을 잃게 된다. (세션 토큰 인증 방식과 다를게 없어짐)
3.JWT의 만료 시간을 짧게 설정하고 매번 JWT를 다시 재발급할 수 있는 refresh Token 방식을 도입한다.</p>
<br>

<h2 id="3-느낀점">3. 느낀점</h2>
<p>회사에서 기존 앱에서 쓰이던 JWT 인증 방식을 OAuth로 적용시킨 경험이 있는데, 이 때 처음으로 토큰을 갱신 시키는 방법을 공부해보았다. JWT에 대해 깊게는 몰라 이번에 공부하면서 OAuth 서버 없이도 토큰을 갱신시킬 수 있다는 것을 알게 되었다!! 😅 포스팅을 하면서 새로 알게 된 내용도 있었고 refreshToken 갱신 하는 쪽은 다시 복습하는 기분을 느꼈다. 잊고 있던 부분도 있어서 다시 짚는 시간을 가졌다. </p>
<p>요즘 짐 같이 쌓여있던 포스팅을 하나하나 마무리 하는 중이다... 뿌듯하다...
미션을 하나하나 클리어 하는 기분이랄까?</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/a676bd3b-1990-48d4-a1b2-67efadc27f86/image.png" width="300" />

<p>밀려있는 다른 포스팅 들도 얼른 게시해야겠다!!!!</p>
<p><br><br><br></p>
<p>참고</p>
<p><a href="https://velog.io/@chuu1019/%EC%95%8C%EA%B3%A0-%EC%93%B0%EC%9E%90-JWTJson-Web-Token#%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0">https://velog.io/@chuu1019/%EC%95%8C%EA%B3%A0-%EC%93%B0%EC%9E%90-JWTJson-Web-Token#%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0</a></p>
<p><a href="https://youtu.be/XXseiON9CV0?si=scrJjWUjKPC_a8vJ">https://youtu.be/XXseiON9CV0?si=scrJjWUjKPC_a8vJ</a></p>
<p><a href="https://velog.io/@boo1996/Token#-token-%EC%9D%B4%EB%9E%80">https://velog.io/@boo1996/Token#-token-%EC%9D%B4%EB%9E%80</a></p>
<p><a href="https://www.daleseo.com/jwt/">https://www.daleseo.com/jwt/</a>
아이콘
<a href="https://icon-icons.com/ko/">https://icon-icons.com/ko/</a>
<a href="https://www.flaticon.com/kr/">https://www.flaticon.com/kr/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Security] 쿠키(Cookie)와 세션(Session)]]></title>
            <link>https://velog.io/@dev_jiwon/Security-%EC%BF%A0%ED%82%A4Cookie%EC%99%80-%EC%84%B8%EC%85%98Session</link>
            <guid>https://velog.io/@dev_jiwon/Security-%EC%BF%A0%ED%82%A4Cookie%EC%99%80-%EC%84%B8%EC%85%98Session</guid>
            <pubDate>Sun, 25 Feb 2024 15:21:56 GMT</pubDate>
            <description><![CDATA[<h2 id="0-들어가며">0. 들어가며</h2>
<p><a href="https://velog.io/@dev_jiwon/%EC%9D%B8%EC%A6%9DAuthentication%EA%B3%BC-%EC%9D%B8%EA%B0%80-Authorization">이전 시간</a> (약 1년전...)에는 인증(Authentication)과 인가(Authorization)에 대해 알아보았습니다.</p>
<p>(작년에 인증과 인가, 세션과 토큰에 대해서 공부를 하였는데, 약 1년만에 이어서 포스팅을 하네요...🥲🥲 1년만이지만 열심히 포스팅해보겠습니다...!!!!)</p>
<br>

<p>저번 시간에 배운 것을 한 번 더 복습해보겠습니다.</p>
<blockquote>
<p>HTTP는 비상태성의 특징을 가지며, 인증된 사용자에게 필요한 기능을 인가하여야한다.</p>
</blockquote>
<p>우리는 보통 웹사이트를 이용할 때, 로그인을 한 후에 서비스를 이용하곤 합니다. 로그인을 하면 회원 사용자만이 할 수 있는 기능(ex. 게시판 글 쓰기, 댓글 달기 등)을 할 수 있습니다.</p>
<blockquote>
<ul>
<li>로그인 : 클라이언트가 서버에게, &quot;사용자&quot;가 누구임을 밝히는 과정 (인증)</li>
</ul>
</blockquote>
<ul>
<li>로그인 성공 : 서버가 클라이언트에게 사용자의 &quot;역할&quot;을 제공 (글 쓰기, 댓글 등 기능 이용 가능하도록 인가)</li>
</ul>
<p>이런식으로 HTTP에서 사용자를 인증 및 인가 하는 방법은 다양합니다.
오늘은 그 중에서도 쿠키와 세션을 이용한 인증 및 인가 방식에 대해 알아보겠습니다.</p>
<p><br><br></p>
<h2 id="1-쿠키-cookie">1. 쿠키 (Cookie)</h2>
<h3 id="1-쿠키cookie란">1. 쿠키(Cookie)란?</h3>
<p>쿠키는 기본적으로 HTTP 통신을 기반으로 하며 브라우저에서 널리 사용되고 있습니다.</p>
<blockquote>
<p><strong>쿠키(Cookie)란?</strong>
서버가 어떤 데이터를 브라우저 측에 저장한 후 다시 그 데이터를 받아오는 기술, 또는 그 데이터 자체</p>
</blockquote>
<p>우리는 저번 시간에 HTTP는 비상태성이기 때문에 매요청마다 사용자를 알 수 없다고 배웠습니다. 이러한 HTTP 환경에서 매번 로그인을 하지 않고 서비스를 이용하려면, 매 요청마다 사용자가 누구인지 알려줄 필요가 있겠습니다. </p>
<p>바로 이 쿠키가 그 역할을 해주는데요, 브라우저가 서버에게 매 요청마다 사용자를 식별할 수 있는 값을 쿠키에 담아 보내줌으로써 사용자가 누구인지 알려줄 수 있게 됩니다.</p>
<p>그렇다면 이 쿠키는 언제 최초로 생성될까요? 사용자 인증을 해야 그에 따른 인가를 하기 때문에 최초에 사용자 인증을 할 수 있는 <strong>로그인</strong> 시점에 생성됩니다.</p>
<br>

<h3 id="2-쿠키의-흐름">2. 쿠키의 흐름</h3>
<h4 id="1-쿠키-최초-생성">1. 쿠키 최초 생성</h4>
<p><strong>로그인</strong>을 통해 사용자 인증을 하면, 서버는 브라우저에게 최초로 쿠키 값을 제공합니다. 그 후, 브라우저는 서버로부터 받은 쿠키 값을 저장합니다. 😋 🍪</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/e74a94c1-1c56-45be-a0f0-e8ff2050dcb7/image.png" width="80%"/>

<p>아래와 같은 형태로 각 쿠키를 HTTP 메세지의 Set-Cookie 헤더에 실어서 응답합니다.</p>
<p>1) 단일 쿠키🍪만 보낼 경우</p>
<pre><code>Set-Cookie: &lt;🍪 이름&gt;=&lt;🍪 값&gt;</code></pre><p>2) 여러 쿠키🍪🍪를 보낼 경우</p>
<pre><code>Set-Cookie: &lt;🍪 이름&gt;=&lt;🍪 값&gt;
Set-Cookie: &lt;🍪 이름&gt;=&lt;🍪 값&gt;</code></pre><h4 id="2-쿠키의-역할">2. 쿠키의 역할</h4>
<p>이제 브라우저는 사용자가 같은 도메인에 머무는 한, 어디를 방문하든 매번 같은 쿠키를 돌려줌으로써 사용자가 누구인지 알려주게 됩니다. 브라우저는 일정 시간동안 계속해서 서버로 쿠키를 돌려 보내줍니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/ccc76019-2f83-4f8b-ad77-ce0288979e09/image.png" width="80%"/>

<pre><code class="language-js">GET /index
Host: www.jiveloper.com
Cookie: a=1; b=2</code></pre>
<pre><code class="language-js">GET /about
Host: www.jiveloper.com
Cookie: a=1; b=2</code></pre>
<br>

<h3 id="3-쿠키의-정보">3. 쿠키의 정보</h3>
<p>쿠키가 담긴 HTTP 메세지의 Set-Cookie 헤더에 대해 자세히 알아봅시다.</p>
<h4 id="1-유효기간">1. 유효기간</h4>
<p>위에서 브라우저는 일정 시간동안 계속해서 서버로 쿠키를 돌려 보낸다고 설명드렸는데요, 브라우저가 쿠키를 얼마나 오래동안 돌려 보내야하는지는 서버가 맨 처음 쿠키를 보낼 때 결정을 하며, Set-Cookie 응답 헤더를 통해 명시되어야 합니다. </p>
<ul>
<li>유효 기간이 명시되어 있는 <strong>영속 쿠키(permanent cookie)</strong></li>
</ul>
<p> 쿠키를 특정 기간이나 특정 시점까지 유효하게 지정하려면 Set-Cookie 응답 헤더에 Expires 속성이나 Max-Age를 사용할 수 있습니다. expires 속성과 max-age 속성이 둘 다 있을 경우 max-age 속성이 우선합니다.</p>
<p> 참고로 브라우저에 저장해두었던 쿠키를 즉시 만료하고 싶을 때는 max-age 속성을 0으로 설정해주면 됩니다.</p>
<pre><code>  Set-Cookie: &lt;🍪 이름&gt;=&lt;🍪 값&gt;; expires=2024-02-27T13:09:09.191Z
  Set-Cookie: &lt;🍪 이름&gt;=&lt;🍪 값&gt;; max-age=1709000923994</code></pre><ul>
<li>유효 기간이 별도로 명시되지 않는 <strong>세션 쿠키(session cookie)</strong>
쿠키가 브라우저의 세션이 종료될 때 함께 만료됩니다. 즉, 브라우저의 탭이나 윈도우를 닫으면 서버가 보냈던 쿠키는 모두 만료되어 브라우저는 더 이상 해당 쿠키를 서버에 돌려 보내지 않습니다.</li>
</ul>
<h4 id="2-적용-범위">2. 적용 범위</h4>
<p>브라우저가 기본적으로 쿠키를 보낸 서버가 속한 도메인으로만 쿠키를 되돌려 보내지만 특정 URL을 방문할 때 해당 쿠키를 보낼 수도 있습니다.</p>
<ul>
<li><p>쿠키 확장
Set-Cookie 응답 헤더에 Domain 속성을 명시하면, 해당 도메인까지 포함되도록 쿠키의 범위가 확장됩니다.</p>
<pre><code>Set-Cookie: &lt;🍪 이름&gt;=&lt;🍪 값&gt;; domain=&#39;.jieonist.com&#39;</code></pre><blockquote>
<p>🤓: 예를 들어, <a href="http://www.jiveloper.com%EC%9C%BC%EB%A1%9C">www.jiveloper.com으로</a> 부터 받은 쿠키를, <a href="http://www.jieonist.com%EC%9C%BC%EB%A1%9C">www.jieonist.com으로</a> 보낼 수 있습니다. 이렇게 되면 <a href="http://www.jiveloper.com%EA%B3%BC">www.jiveloper.com과</a> <a href="http://www.jieonist.com%EC%9D%B4">www.jieonist.com이</a> 쿠키를 공유할 수 있게 됩니다.</p>
</blockquote>
</li>
<li><p>쿠키 축소
Set-Cookie 응답 헤더에 path 속성을 명시하면 쿠키의 범위를 해당 도메인의 특정 경로로 쿠키의 범위를 축소시킬 수 있습니다.</p>
<pre><code>Set-Cookie: &lt;🍪 이름&gt;=&lt;🍪 값&gt;; path=/user</code></pre><blockquote>
<p>🤓: 예를 들어, path 속성이 /user라고 설정되어 있는 쿠키는, 브라우저가 /users를 포함한 하위 경로로 요청을 할 때만 서버로 돌려 보냅니다.</p>
</blockquote>
</li>
</ul>
<h4 id="3-보안-속성">3. 보안 속성</h4>
<p>반드시 쿠키를 사용해야 하는 상황이라면 가급적 아래와 같은 보안 속성을 사용하시기를 권장드립니다.</p>
<ul>
<li><p>Secure
Set-Cookie 응답 헤더에 이 속성이 명시된 쿠키는 브라우저가 https 프로토콜 상에서만 서버로 돌려 보냅니다. 네트워크 상에서 탈취되었을 때 문제가 될 수 있는 쿠키를 상대로 쓰면 유용할 것입니다.</p>
<pre><code>Set-Cookie: &lt;🍪 이름&gt;=&lt;🍪 값&gt;; secure</code></pre></li>
<li><p>HttpOnly
Set-Cookie 응답 헤더에 이 속성이 명시된 쿠키는 서드 파티(third party) 자바스크립트 코드가 쿠키에 접근하는 것을 제한할 수 있습니다.</p>
<pre><code>Set-Cookie: &lt;🍪 이름&gt;=&lt;🍪 값&gt;; HttpOnly</code></pre></li>
</ul>
<br>

<h3 id="4-쿠키의-한계">4. 쿠키의 한계</h3>
<p>쿠키는 브라우저에 저장을 하는 것이기 때문에, 사용자가 쉽게 쿠키를 확인할 수 있다고 말씀드렸습니다. 그렇기 때문에, 사용자의 노출이 쉬워 갖가지 이슈를 가집니다.</p>
<p>따라서 쿠키를 사용할 때는 아래와 같은 쿠키의 한계점들을 잘 인지하고 사용하는 것이 중요합니다. 🤓</p>
<h4 id="1-쿠키는-유실되기-쉽습니다">1. 쿠키는 유실되기 쉽습니다.</h4>
<p>당장 크롬만 봤을 때, 인터넷 사용 삭제 기록 란에 쿠키 데이터가 있는 것을 확인하실 수 있습니다. 쿠키를 어렵지 않게 삭제할 수 있기 때문에, 중요한 데이터는 쿠키를 사용해서 브라우저에 저장하시면 안 됩니다!</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/6d4fc1f4-659a-4bd0-84af-75cd34c7b8f2/image.png" width="50%"/>

<h4 id="2-쿠키는-변조되기-쉽습니다">2. 쿠키는 변조되기 쉽습니다.</h4>
<p>브라우저의 개발자 도구를 사용하면 각 웹사이트 별로 현재 어떤 쿠키가 저장되어 있는지 한 눈에 파악할 수 있으며 쿠키를 손쉽게 변경할 수 있습니다. 이를 통해 서버가 브라우저로 보낸 쿠키와 전혀 다른 쿠키를 서버에 돌려 보낼 수도 있으며, 심지어 서버가 저장한 적이 없는 새로운 쿠키를 만들어서 서버에 보낼 수도 있습니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/3d57210a-9ee3-4aa3-ab48-efd17eaa4d2e/image.png" width="50%"/>

<br>

<h2 id="2-세션-session">2. 세션 (Session)</h2>
<p>세션이란 단어는 개발자가 아니어도 충분히 자주 접해보았을 단어라고 생각합니다. <strong>세션</strong>이라는 단어가 무슨 뜻인지 알아봅시다.</p>
<blockquote>
<p><strong>세션(Session)이란?</strong>
사용자가 인증에 성공하여 서버와 클라이언트 간의 상호작용을 위해 일시적인 시간동안 유지되는 값.</p>
</blockquote>
<p>비상태성인 HTTP 환경에서 이 세션 값이 있는 쿠키를 저장하고, 매 요청마다 세션 값을 쿠키에 담아 데이터를 요청함으로써 사용자가 <strong>누구인지</strong> 인증 할 수 있게 됩니다.</p>
<p>그렇다면 인증된 사용자의 정보를 어디에 어떻게 저장할까요?</p>
<h3 id="1-동작-과정">1. 동작 과정</h3>
<p>서버와 클라이언트간의 세션을 통한 통신 과정을 조금 더 자세히 알아보겠습니다.</p>
<h4 id="1-사용자-인증하기-feat-세션-생성-과정">1. 사용자 인증하기! (feat. 세션 생성 과정)</h4>
<p>저번 시간에는 인증에 대한 정의와 인증은 로그인을 통해 이루어진다는 것을 배웠습니다. 어떻게 인증이 되는지 그림을 통해 알아봅시다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/ba91b6c6-6af1-4569-b9b7-3910fe7438e5/image.png" width="80%"/>

<ol>
<li>브라우저에서 사용자는 아이디(id) 및 비밀번호(pw)를 입력합니다.</li>
<li>브라우저는 서버로 사용자가 입력한 아이디와 비밀번호를 전달합니다.</li>
<li>서버는 전달 받은 아이디와 비밀번호가 일치하는 유저를 조회합니다.</li>
<li>(유저 데이터가 유효하다면) 유저 데이터를 세션 데이터베이스에 전달합니다.
(* 만약 유저 데이터가 유효하지 않다면 바로 8번으로 넘어가서 로그인에 실패했다는 에러 메세지를 보낼 것입니다. (쿠키 없이!!))</li>
<li>세션 데이터베이스는 세션 아이디를 생성합니다.</li>
</ol>
<br>

<img src="https://velog.velcdn.com/images/dev_jiwon/post/b0319700-a593-42b1-a0f4-11b5d3a60d9b/image.png" width="80%"/>

<ol start="6">
<li><p>세션 데이터베이스는 서버로 생성된 세션 아이디를 전달합니다.</p>
</li>
<li><p>서버는 세션 데이터를 서버 메모리에 저장합니다.</p>
</li>
<li><p>서버는 브라우저로 response와, 세션 아이디를 담은 쿠키를 전달합니다.</p>
<blockquote>
<p>❗️ 서버가 브라우저로 보내는 응답의 헤더 중 Set-Cookie 헤더에 <strong>세션 아이디 값을 함께 실어 보낸다.</strong> 
 (서버: 옜다, 너 인증 성공! 🍪 줄게!)</p>
</blockquote>
</li>
<li><p>브라우저는 쿠키를 저장합니다.</p>
<blockquote>
<p>❗️ 그 응답을 받은 브라우저는 해당 쿠키를 저장하고, 그 다음 매 요청마다 세션 아이디를 Cookie 헤더에 실어 전송한다.
 ⭐️ 이제 브라우저는 이 쿠키를 통해 서버에게 인증된 사용자임을 알릴 수 있다. ⭐️</p>
</blockquote>
</li>
</ol>
<h4 id="2-데이터-송수신-방법">2. 데이터 송수신 방법</h4>
<p>이제 브라우저는 🍪쿠키🍪를 가지고 인증도 했겠다, 서버로부터 인가도 받아보겠습니다. </p>
<p>먼저, 브라우저에서 서버로 데이터를 요청해보겠습니다.</p>
<ul>
<li>데이터 송신 방법<img src="https://velog.velcdn.com/images/dev_jiwon/post/be93fe6e-be1a-4118-9ea6-7c6ce08f6749/image.png" width="80%" />
  1. 저장된 쿠키를 Set-Cookie 헤더에 담아 서버에 데이터를 요청합니다.
  2. 서버는 쿠키에 담긴 session db에 session id를 전달합니다.
  3. Session DB는 전달 받은 session id를 조회합니다.

</li>
</ul>
<br>

<ul>
<li>데이터 수신 방법<img src="https://velog.velcdn.com/images/dev_jiwon/post/018c266f-bbbb-4008-8b7b-fe0dd1b408e6/image.png" width="80%"/>
  4. Session DB는 서버로 session id에 대한 유효성을 전달합니다.
  5. 서버는 reqeust에 대한 response를 전달합니다.
> 🙂: session id가 유효하면 인증된 사용자이므로 사용자에게 필요한 기능을 인가하고, 유효하지 않으면 인증 처리를 해주지 않습니다. 당연히 필요한 기능에 대해 인가 받지 못 할테구요.

</li>
</ul>
<br>

<h3 id="2-세션이-쓰이는-기능">2. 세션이 쓰이는 기능</h3>
<p>세션 인증 방식을 사용하면 서버는 세션DB를 이용해 로그인된 모든 유저 정보를 저장합니다. 이러한 특징을 통해 다음과 같은 기능들이 가능합니다.</p>
<p><strong>1. 인xx그램: 원치 않는 디바이스 강제 로그아웃</strong>
서버에서 session id를 삭제하여 강제 로그아웃 기능을 구현할 수 있습니다.</p>
<p><strong>2. 넷xxx: 다중 로그인 된 계정이 현재 접속 중인지 확인할 수 있음</strong>
서버에서 다중 로그인된 계정을 찾아 현재 접속 중인지 확인할 수 있습니다.</p>
<br>

<h3 id="3-장단점">3. 장단점</h3>
<p>세션을 통한 인증 및 인가 방식에 대해 알아보았습니다. 이러한 방식에는 어떠한 장단점이 있는지 알아봅시다.</p>
<h4 id="1-장점">1. 장점</h4>
<ul>
<li>서버 측에서 유저의 인증 정보를 관리하기 때문에, _토큰 인증 방식(뒤 포스팅에 게시 예정)_과 달리 쉽게 탈취될 가능성이 적어 보안성이 높습니다.</li>
<li>새로고침이나 브라우저 종료 등으로 인한 세션 만료 기간 설정이 가능합니다.</li>
<li>브라우저에서 인증 정보를 노출시키는 위험을 줄일 수 있습니다.</li>
</ul>
<h4 id="2-단점">2. 단점</h4>
<ul>
<li>브라우저에서 서버로 데이터를 요청할 때마다 서버에서 세션 정보를 확인해야 하기 때문에, 서버의 부하가 증가할 수 있습니다.</li>
<li>서버에서 직접 사용자 인증 값을 저장하기 때문에 사용자가 많아지게 된다면 서버의 메모리가 부족해 질 수도 있습니다. 결국 사용자가 늘어나게 되면 원활한 접속을 위해 서버를 확장해야 할 것입니다.</li>
</ul>
<br>

<p>서버의 부담을 줄일 수 있는 인증방식은 없을까?
세션 인증 방식의 단점을 보완하기 위해 토큰 인증 방식이 등장하게 되었습니다.</p>
<p>요 부분은 <a href="https://velog.io/@dev_jiwon/Security-JWT-Json-Web-Token">다음 포스팅</a>에서 뵙겠습니다...!! 🤓🤓</p>
<p><br><br></p>
<p>참고</p>
<p><a href="https://hudi.blog/cookie-and-session/">https://hudi.blog/cookie-and-session/</a>
<a href="https://www.youtube.com/watch?v=tosLBcAX1vk">https://www.youtube.com/watch?v=tosLBcAX1vk</a>
<a href="https://kindjjee.tistory.com/139">https://kindjjee.tistory.com/139</a>
<a href="https://www.daleseo.com/http-cookies/">https://www.daleseo.com/http-cookies/</a>
<a href="https://www.daleseo.com/http-session/">https://www.daleseo.com/http-session/</a>
아이콘
<a href="https://icon-icons.com/ko/">https://icon-icons.com/ko/</a>
<a href="https://www.flaticon.com/kr/">https://www.flaticon.com/kr/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TypeScript] interface vs. type]]></title>
            <link>https://velog.io/@dev_jiwon/TypeScript-interface-vs.-type</link>
            <guid>https://velog.io/@dev_jiwon/TypeScript-interface-vs.-type</guid>
            <pubDate>Sun, 18 Feb 2024 06:57:40 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요~~ 오늘은 Typescript에서 쓰이는 interface와 type의 차이에 대해 알아보려고 합니다.😎</p>
<p>interface와 type은 둘다 타입을 지정해줄 때 쓰는데 정확히 어떤 차이가 있을까요?
크게 5가지의 차이점을 알아보겠습니다.</p>
<p>그럼 하나씩 알아볼까요~? 🤓🤓</p>
<br>

<h2 id="1-타입-지정">1. 타입 지정</h2>
<p>interface, type은 각각 지정할 수 있는 타입의 차이가 있습니다. 한번 알아봅시다. 😎</p>
<h3 id="inteface">inteface</h3>
<h4 id="객체-타입-지정">객체 타입 지정</h4>
<p>interface는 ❗️오직❗️ <strong>객체</strong>를 지정할 때만 쓰입니다.</p>
<pre><code class="language-tsx">interface Person {
  name: string
  age: number
}

const person: Person = {
  name: &#39;jiveloper&#39;,
  age: 27
};
</code></pre>
<br>

<h3 id="type">type</h3>
<p>type은 interface 처럼 객체 타입에도 선언하지만 주로 원시값, 튜플 등의 타입을 선언할 때 쓰입니다.</p>
<h4 id="객체-타입-지정-1">객체 타입 지정</h4>
<blockquote>
<p>🤔: 객체 타입을 지정하는 부분은 interface와 역할이 동일하나, 내가 알아봤을 때는 일반적으로는 객체의 타입을 지정할 때 interface를 사용하는게 코드컨벤션 식으로 자리 잡은듯 하다...</p>
</blockquote>
<pre><code class="language-tsx">type Person = {
  name: string
  age: number
}

const person: Person = {
  name: &#39;jiveloper&#39;,
  age: 27,
};</code></pre>
<h4 id="페이로드-지정">페이로드 지정</h4>
<blockquote>
<p>🤩: 이 부분은 이번에 처음 알게 된 사실인데, 페이로드에 대해서도 타입으로 지정할 수 있다는 것이다!!!!! 커스텀 타입으로 자주 애용해야겠습니다~!</p>
</blockquote>
<pre><code class="language-tsx">const person = {
    id: 1,
    name: &quot;jiveloper&quot;,
    job: {
        developer: true
    },
    age: 27
}

type Person = typeof person;</code></pre>
<h4 id="원시값-지정">원시값 지정</h4>
<pre><code class="language-tsx">type Name = string
type Age = number
type NumberString = string | number // union 타입</code></pre>
<h4 id="튜플-지정">튜플 지정</h4>
<pre><code class="language-tsx">type Person = [string, number, boolean]</code></pre>
<p><br><br></p>
<h2 id="2-타입-확장">2. 타입 확장</h2>
<p>interface와 type은 모두 타입 확장이 가능하나, 확장 방법에 차이가 있습니다.</p>
<h3 id="inteface-1">inteface</h3>
<p>interface는 extends 예약어를 통해 타입을 확장할 수 있습니다.</p>
<pre><code class="language-tsx">interface Person {
  name: string
  age: number
}

interface Student extends Person {
  school: string

}</code></pre>
<br>

<h3 id="type-1">type</h3>
<p>type은 &amp; 연산자를 통해 타입을 확장할 수 있습니다.</p>
<pre><code class="language-tsx">type Person = {
  name: string
  age: number
}

type Student = Person &amp; {
  school: string
}</code></pre>
<p><br><br></p>
<h2 id="3-선언적-확장">3. 선언적 확장</h2>
<p>interface는 선언적으로 확장할 수 있고, type은 선언적으로 확장할 수 없습니다.</p>
<h3 id="interface">interface</h3>
<p>선언적으로 확장한다는 말이 무슨 말일까요? 
똑같은 이름으로 interface를 선언하면 타입을 확장한다는 뜻입니다. 예시를 통해 알아보겠습니다.</p>
<pre><code class="language-tsx">interface Person {
  name: string
}

interface Person {
  age: number
}</code></pre>
<p>두 interface의 이름이 Person으로 동일하죠?
변수명이나 함수명 같은 경우는 동일한 이름으로 선언되면 duplicate error가 나는데 interface는 에러가 나지 않고 타입을 확장하는 역할을 합니다.</p>
<blockquote>
<p>😲: 위와 같이 쓴다면 A 개발자가 Person이라는 이름으로 interface를 선언하였는데, B 개발자가 그것을 못 보고 또 Person이라는 이름으로 interface를 선언할 수 있습니다. 그러면 의도와는 다르게 중복으로 interface가 선언된 경우에 캐치하기 힘들 수 있으니 조심할 필요가 있습니다.</p>
</blockquote>
<br>

<h3 id="type-2">type</h3>
<p>선언적 확장 불가능</p>
<p><br><br></p>
<h2 id="4-computed-value-사용">4. computed value 사용</h2>
<p>interface는 computed value가 사용 불가능하고, type은 computed value가 사용 가능합니다.</p>
<h3 id="inteface-2">inteface</h3>
<p>computed value 사용 불가능</p>
<br>

<h3 id="type-3">type</h3>
<p>또 어려운 말이 나왔는데, computed value가 무엇일까요?
번역하면 <strong>&quot;계산된 값&quot;</strong>이라는 뜻인데요, 어떻게 사용되는지 예시를 통해 알아봅시다.</p>
<pre><code class="language-tsx">type names = &#39;firstName&#39; | &#39;lastName&#39;

type NameTypes = {
  [key in names]: string
}

const myName: NameTypes = { firstName: &#39;veloper&#39;, lastName: &#39;ji&#39; }</code></pre>
<p>NameTypes의 key타입에 names라는 union 타입이 합쳐졌습니다.
이렇게 계산된 NameTypes는 myName이라는 객체의 타입으로 지정할 수 있습니다.</p>
<p><br><br></p>
<h2 id="5-성능-차이">5. 성능 차이</h2>
<p><a href="https://github.com/microsoft/TypeScript/wiki/Performance#preferring-interfaces-over-intersections">TypeScript Wiki</a>에 의하면 아래와 같이 설명되어있습니다. </p>
<blockquote>
<p>Type relationships between interfaces are also cached, as opposed to intersection types as a whole.
interface 들을 합성할 경우 이는 캐시가 되지만, type의 경우에는 그렇지 못하다.</p>
</blockquote>
<blockquote>
<p>A final noteworthy difference is that when checking against a target intersection type, every constituent is checked before checking against the &quot;effective&quot;/&quot;flattened&quot; type.
type 합성의 경우, 합성에 자체에 대한 유효성을 판단하기 전에, 모든 구성요소에 대한 type을 체크하므로 컴파일 시에 상대적으로 성능이 좋지 않다.</p>
</blockquote>
<p>비교적 어려운 말인데 interface는 합성 할 때 캐싱이 되기 때문에, type 보다 비교적 성능이 좋다고 이해했습니다.</p>
<p><br><br></p>
<p>참고
<a href="https://velog.io/@wlwl99/TypeScript-type%EA%B3%BC-interface%EC%9D%98-%EC%B0%A8%EC%9D%B4#%EC%84%A0%EC%96%B8%EC%A0%81-%ED%99%95%EC%9E%A5">https://velog.io/@wlwl99/TypeScript-type%EA%B3%BC-interface%EC%9D%98-%EC%B0%A8%EC%9D%B4#%EC%84%A0%EC%96%B8%EC%A0%81-%ED%99%95%EC%9E%A5</a></p>
<p><a href="https://yceffort.kr/2021/03/typescript-interface-vs-type">https://yceffort.kr/2021/03/typescript-interface-vs-type</a></p>
<p><a href="https://youtu.be/oltlapP89cU?si=O4nmsjPSBoipkiz8">https://youtu.be/oltlapP89cU?si=O4nmsjPSBoipkiz8</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] React에서 렌더링은 어떻게 되는 걸까?]]></title>
            <link>https://velog.io/@dev_jiwon/React%EC%97%90%EC%84%9C-%EB%A0%8C%EB%8D%94%EB%A7%81%EC%9D%80-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%90%98%EB%8A%94-%EA%B1%B8%EA%B9%8C</link>
            <guid>https://velog.io/@dev_jiwon/React%EC%97%90%EC%84%9C-%EB%A0%8C%EB%8D%94%EB%A7%81%EC%9D%80-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%90%98%EB%8A%94-%EA%B1%B8%EA%B9%8C</guid>
            <pubDate>Sat, 03 Feb 2024 15:59:36 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요<del>~</del> 오랜만에 개념 모음으로 찾아뵙습니당. 🤓
오늘은 React 렌더링 원리에 대해 한번 알아보려 합니다!</p>
<p><strong>렌더링</strong>, 개발자라면 수없이 들어봤을 단어이고 굉장히 익숙한 단어일거라고 생각합니다.
React 렌더링 원리를 들어가기에 앞서, 우리는 웹의 구동 원리에 대해 먼저 알 필요가 있습니다.</p>
<blockquote>
<p>😎 : 웹의 구동원리를 알아야 React가 왜 상태값이 변한 컴포넌트만 렌더링하는 것인지 알 수 있다고 생각합니다.</p>
</blockquote>
<p><br><br></p>
<h2 id="1-웹-구동-원리">1. 웹 구동 원리</h2>
<p>웹 브라우저는 어떻게 구동될까요?</p>
<p>웹 페이지는 HTML로 작성되며, HTML은 다양한 태그들로 구성되어 있습니다. 모든 웹 브라우저는 <strong>DOM을 통해 웹 페이지를 구조화</strong>하며, 이를 사용자에게 보여줍니다.</p>
<h3 id="dom이-뭔데">DOM이 뭔데?</h3>
<p>DOM은 Document Object Model의 약자로, 웹 페이지에 대한 인터페이스입니다. DOM은 웹 페이지를 객체 트리 구조로 표현할 수 있으며, 자바스크립트 등의 프로그래밍 언어를 통해 웹 페이지를 동적으로 변경할 수 있게 도와줍니다.</p>
<br>

<div>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/0b6783c8-0e99-41df-9d94-3e1ea7ddd9f6/image.png" width="50%"/>
</div>

<br>

<p>자바스크립트에서 DOM을 조작할 때마다 브라우저의 렌더링 엔진과 자바스크립트 엔진 사이에서 상호 작용이 발생합니다. 상호 작용이 발생하면 브라우저는 전체 페이지를 다시 그리려고 하기 때문에, 비용이 많이 드는 작업이고 실행 성능에 큰 영향을 미칠 수 있습니다.</p>
<p>이러한 비용을 줄이기 위해, 실제 DOM을 최소한으로 조작하면서 성능을 향상시키는 Virtual DOM이라는 것이 등장합니다...!</p>
<h3 id="virtual-dom은-뭔데">Virtual DOM은 뭔데?!!</h3>
<p>Virtual DOM은 <strong>실제 DOM의 가벼운 복사본</strong>으로, 실제 DOM의 구조를 메모리에 저장한 것입니다. 브라우저에 실제로 보여지는 DOM이 아니라 메모리에 가상으로 존재하는 DOM 입니다. </p>
<p>Virtual DOM을 사용하면 변화가 있는 부분만 실제 DOM에 반영하므로, DOM을 직접 조작하는 것보다 <strong>속도가 훨씬 빠르고 렌더링을 최소화</strong>하기 때문에 성능을 개선할 수 있습니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/0814f33d-fedc-4a62-8b19-061d2154f40d/image.png" width='100%'/>

<p>웹 페이지의 상태가 변경될 때마다 새로운 Virtual DOM 트리가 생성됩니다. 이후에는 이전 트리와 새 트리를 비교하여 바뀐 부분만 실제 DOM에 반영합니다. </p>
<blockquote>
<p>JavaScript로 만든 웹 애플리케이션은 Virtual DOM과 실제 DOM을 함께 사용하여 렌더링을 수행합니다.</p>
</blockquote>
<p><br><br></p>
<h2 id="2-react-렌더링-원리">2. React 렌더링 원리</h2>
<p>React는 Javascript로 만든 웹 프레임워크이므로 위에서 설명드린 Virtual DOM을 사용하여 화면을 렌더링 합니다.</p>
<p><img src="https://velog.velcdn.com/images/dev_jiwon/post/9c46979a-42e4-4b09-96e1-db0b739fadd7/image.png" alt=""></p>
<p>React는 사용자의 액션 등으로 컴포넌트의 상태값이 변경되면 Virtual DOM은 상태가 변한 객체를 찾아내고, 그 객체를 실제 DOM에 반영하여 업데이트 된 객체를 컴포넌트로 렌더링합니다.</p>
<p>React의 렌더링 과정을 좀 더 자세히 들여다보겠습니다.
React 렌더링 과정은 2가지 단계를 거칩니다. 바로 준비단계와 커밋단계 입니다. 무슨 단계인지 그림을 통해 한번 파악해보겠습니다.</p>
<h3 id="1-준비-단계-render-phase">1. 준비 단계 (render phase)</h3>
<p>준비 단계는 상태값이 변했을 때, 직접적으로 화면에 변화를 주는 것이 아니라 <strong>무엇을 어떻게 그릴지 계획하는 과정</strong> 입니다. 
생명주기로 따지자면 <strong>constructor</strong>, <strong>render</strong>에 해당합니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/91582a1d-74e9-4784-8539-ff69a697bf93/image.png" width="70%"/>


<p>사용자의 액션 등으로 상태값 변경 요청 트리거가 발생했을 때, 변경된 상태값을 기반으로 새롭게 생성된 Virtual DOM 트리와 이전에 생성된 Virtual DOM 트리를 비교하여 변경사항을 파악합니다.</p>
<h3 id="2-커밋-단계-commit-phase">2. 커밋 단계 (commit phase)</h3>
<p>커밋 단계는 준비 단계에서 생성된 새로운 Virtual DOM 트리를 바탕으로 필요한 UI 업데이트를 결정하고, 이를 <strong>실제 DOM에 전달하여 UI를 업데이트하는 과정</strong>입니다.
생명주기로 따지자면 <strong>componentDidMount</strong>, <strong>componentDidUpdate</strong>에 해당합니다.</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/6debe511-4878-4467-a670-3d83dfb36629/image.png" width="70%"/>


<br>

<h3 id="3-주의">3. 주의</h3>
<p>React는 변화한 상태값을 모두 렌더링하므로 상태값을 잘 조정할 필요가 있습니다. 때때로 렌더링이 불필요하게 발생할 수 있어, 과도한 렌더링 방지를 위해 useCallback이나 useMemo, React.memo를 적절히 사용하여 렌더링을 최적화 시킬 수 있습니다. 
(이 부분은 다음 포스팅에서 만나요.^^)</p>
<p><br><br></p>
<h2 id="3-느낀점">3. 느낀점</h2>
<p>원래는 React Native의 구동 원리를 공부하고 있었는데, React Native는 React 원리와 비슷하여 React 렌더링 원리를 알아보다가 결국 웹의 구동 원리까지 공부하게 되었다.</p>
<p>누군가에게 개발을 공부할 때 &quot;왜⸌◦̈⃝⸍ʷʰʸˀ̣ˀ̣?&quot;라는 의문을 가지고 공부해야한다고 들었었는데, 작년까지도 그 말을 깊게 이해하지 못했다. 요즘 React Native를 깊게(?) 공부하면서 &quot;왜⸌◦̈⃝⸍ʷʰʸˀ̣ˀ̣?&quot;라는 의문을 가지며 꼬꼬무를하는 내 자신을 발견하였다...😲😲😲!!</p>
<p>나름 장족의 발전이라고 생각하며 앞으로도 이런식으로 무언가 정확하게 이해하기 위해선 항상 의문을 가지고 생각을 이어나가야할 필요가 있다고 생각했다.</p>
<p>React 렌더링을 이해했으니 React Native 구동 원리에 대해서도 포스팅 해야겠다.</p>
<p><br><br></p>
<p>참고
<a href="https://vaishnavineema.medium.com/react-dom-vs-virtual-dom-f3236d4a1b21">https://vaishnavineema.medium.com/react-dom-vs-virtual-dom-f3236d4a1b21</a></p>
<p><a href="https://wit.nts-corp.com/2019/02/14/5522">https://wit.nts-corp.com/2019/02/14/5522</a></p>
<p><a href="https://react.vlpt.us/basic/01-concept.html">https://react.vlpt.us/basic/01-concept.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[회고록] 2023년 회고록]]></title>
            <link>https://velog.io/@dev_jiwon/2023%EB%85%84-%ED%9A%8C%EA%B3%A0%EB%A1%9D-f9y1vyva</link>
            <guid>https://velog.io/@dev_jiwon/2023%EB%85%84-%ED%9A%8C%EA%B3%A0%EB%A1%9D-f9y1vyva</guid>
            <pubDate>Sun, 31 Dec 2023 14:02:12 GMT</pubDate>
            <description><![CDATA[<p>이번 2023년을 마무리하면서 한 해를 돌아보며 회고록을 작성하려고 한다.
이번 한 해에 많이 배우고 도전하면서 나의 지향점으로 나아가고 있기에 꼭 기록을 하고싶었다!</p>
<p>원래의 나는 자존감이 매우 낮아서 온전히 내가 나의 편이 되어주지 못 했다. 어떤 안 좋은 일이 발생하면 &#39;왜 그랬을까, 나때문이네&#39; 이러면서 항상 내 탓을 해왔다. 사람들과 대화를 할 때도 상대방이 무안해질정도로 내 탓을 하곤 했는데, 나 스스로도 이런 나의 모습이 너무 싫었고 꼭 개선을 하고싶었다. </p>
<p>그러나 자존감을 올린다는 게 너무나도 막연했고, 평소에도 나를 위해 본 적이 없어서 방법을 찾기 쉽지 않았다. 이번 해의 다짐인 &#39;하고싶은 것을 하자&#39;를 실천하다보니 자연스럽게 자존감이 올랐고, 이것만 봐도 나의 2023년은 성공적인 한 해라고 생각한다. </p>
<br>

<p>2023년을 시작하면서 나 스스로 다짐을 한 게 3가지 있다.</p>
<blockquote>
<ol>
<li>자존감 올리기 (⭐️⭐️⭐️⭐️⭐️)</li>
<li>하고싶은 것 찾기 (⭐️⭐️⭐️⭐️)</li>
<li>책 읽기 (⭐️⭐️⭐️)</li>
</ol>
</blockquote>
<p>2023년에 과연 잘 지켜졌는지, 한번 되돌아 보겠다.</p>
<p><br><br></p>
<h3 id="진로-고민-feat-번아웃">진로 고민 (feat. 번아웃?)</h3>
<p>작년에 새로운 회사로 입사하고 3개월 정도 흘렀나 나에게 (내 기준) 어려운 업무가 떨어졌다. 바로 앱 내 OAuth 적용 작업 내용이었는데, 나는 그때당시 OAuth는 커녕 JWT도 아예 몰랐던 상황이라 업무가 주어졌을 때 너무 막막했다. 한 2개월을 끙끙 앓았던 것 같은데, <del>(의지할 사람이 없어서)</del> 혼자서 OAuth 공부를 하고 작업했다. </p>
<p>그때가 시작이었던 것 같다. 나의 개발 번아웃이 터진게...</p>
<p>그때 당시 방목형으로 놓여서 알아서 해야하는 이 상황이 너무 부담감으로 다가왔다. 이러한 상황과 혼자서 계속해서 실패하는 과정이 맞물리면서 개발이 싫어졌다. 하루하루 출근하는게 마음의 짐이었다...</p>
<p>지금 생각해보면 이때 OAuth를 배우고 적용해보면서 큰 성장을 하긴 했다. 올 해 1월 쯤에 OAuth 작업을 마무리했는데, OAuth가 완성됨과 동시에 개발에 흥미를 잃어버렸다. 원래는 개발하는 것에 흥미를 느끼고 내 적성에 맞다고 생각했는데 그때 당시 너무 지쳐버렸던 것 같다.</p>
<p>그 일이 있고 한 6개월동안은 개발에 흥미를 못 느껴서 &#39;개발자 관둬야하나&#39;라는 생각까지 갔다. 원래 직업군이든 뭐든 &#39;하고싶은 일을 하자&#39;는게 내 좌우명 같은 신념이었지만 개발이 더이상 하고싶어지지 않자, 내 신념이 무너지는 느낌이었다. </p>
<p>일단 하고싶은 것을 찾아야겠다고 생각했다.</p>
<p><br><br></p>
<h3 id="나는-하고싶은-것을-하고싶다">나는 하고싶은 것을 하고싶다!</h3>
<p>그때 당시 내가 지금 하고싶은 것을 하지 않고 있다는 생각이 들자, 자존감은 계속해서 바닥을 쳤다. 올 해의 가장 중요한 다짐이 무엇인가? ⭐️ 다섯개인 <strong>&#39;자존감 올리기&#39;</strong> 이다. 계속해서 인지했다. 이 땅굴 속에서 나를 탈출 시키려면 일단 하고싶은 것을 찾아야겠더라. 그렇다고 당장 직업을 바꿀 순 없는 일이고, 하고싶은 취미라도 찾아야겠다고 생각했다.</p>
<p>무엇을 하고싶은지 곰곰히 생각해보았다. 내가 어릴 적에 피아노 학원을 다녔던 적이 있는데, 그때 당시 굉장히 흥미를 느끼고 다녔던 기억이 있다. 사정상 계속 다니진 못 했지만, 피아노 학원을 관둔 것에 대한 아쉬움이 아직도 남아있었다. 피아노 학원을 다니면서 어릴 때의 흥미를 다시금 느껴보고싶었고, 결국 성인 피아노 학원을 등록했다.</p>
<p>매주 1일 레슨과 3-4일 정도 연습을 하러 피아노 학원에 갔다. 피아노를 다니는 목적이 하고싶은 일을 하기 위함과 흥미 유발이었고, 오직 나를 위한 일이었기 때문에 마음도 편했다. 스스로 시간을 투자하며 피드백을 주는 일이 나를 보살피고 케어해주는 느낌이 들었다. </p>
<p>&quot;자발적&quot;, &quot;흥미&quot;, &quot;하고싶은 일&quot; 이 세 포인트가 나를 가슴 뛰게 하는 일이었다. 내가 하고싶은 일을 하는 거니, 잠깐 더뎌도 괜찮았고 좀처럼 나를 깎아먹는 일이 없었다. 피아노가 나의 꺼진 열정을 불타오르게 하는 계기가 되었다.</p>
<br>

<p>그게 얼마나 열정적이었냐면...</p>
<br>

<img src="https://velog.velcdn.com/images/dev_jiwon/post/f8b876fc-b908-4d59-baa1-d55c316db68d/image.jpg" width="80%" />

<p>피아노 다닌지 약 9개월만에 연주회에 나갈 정도였다!!! ㅋㅋㅋㅋㅋ</p>
<p>원래 사람들 앞에 나오는 걸 굉장히 두려워하고 무서워하는 편인데, 연주회를 하겠냐는 선생님의 물음에 고민도 안하고 나가겠다고 했었다. 나의 하고싶은 일에 대한 나름의 유종의 미를 거두고싶었달까? 그것만으로도 나에게 너무나도 의미있는 일이었기에.</p>
<p>(잠시 나의 유튜브를 잠시 홍보하겠다...ㅎ 기록용으로 배운 곡 완곡 시에 업로드를 하고있다. <a href="https://www.youtube.com/channel/UC-YXl9v5STsmvVACKMTKNrg">https://www.youtube.com/channel/UC-YXl9v5STsmvVACKMTKNrg</a>)</p>
<p>비록 초보이지만 실력을 떠나서 나의 유종의 미는 성공적이었다. 내가 잘 쳤든 못 쳤든 크게 상관이 없다.</p>
<p><br><br></p>
<h3 id="꺼진-장작에-불씨를-지피다">꺼진 장작에 불씨를 지피다!</h3>
<p>다시 개발 얘기로 돌아가겠다. 개발에 흥미를 잃었지만 당장이고 하고싶은 일을 찾겠다고 직업군을 바꿀 수도 없는 일이었다. 개발에 거부감이 들어 매주 친구와 하고있던 프로젝트도 못 하겠다는 마음이 들었고, 친구에게 미안하지만 프로젝트를 잠시 쉬어가도 되겠냐고 했다. 고맙게도 친구는 이러한 내 상황을 이해해주었고, 개발은 일 외적으로 아무것도 하지 않았다.</p>
<p>막상 개발을 아무것도 하지 않자니 또 마음 한 켠이 무거워졌다. 개발이라는 생태계에서 가만히 있으면 뒤처진다는 생각 때문인듯 하다. 이 개발 번아웃 아닌 번아웃을 극복하자니 개발하기는 싫고, 가만히 있기는 뭐해서 이론 공부라도 해야겠다는 생각이 들었다.</p>
<p>그래서 정보처리기사를 준비하기로 했다. 매주 금~일요일마다 정보처리기사를 공부했다. 어떻게 보면 매주 하는 정처기 공부도 피아노 학원 다니는 것처럼 내가 자발적으로 내 일상을 만들어서 나에게 시간을 투자하는 일이었다. 공부 또한 마찬가지로 좀처럼 나를 깎아먹는 일이 없었고, 오히려 꺼진 개발 열정을 불타오르게 하였다.</p>
<p>정처기 필기를 따고, 개발 열정에 불이 붙어 다시 프로젝트를 하게 되었다. 의욕 뿜뿜이어서 일 외적으로 개발을 다시 하는데 신기하게도 거부감이 들지 않았고 오히려 열정 넘치게 개발이 계속 하고싶어졌다.</p>
<p>정처기 유종의 미를 거두기 위해 당연히 실기까지 도전했고, 당당히 합격했다!</p>
<img src="https://velog.velcdn.com/images/dev_jiwon/post/2865f12d-b813-46e2-9f33-0fb3b2e56e19/image.jpg" width="60%" />

<p><del>(살짝 오글 거리는 표현이지만..)</del> 정처기 도전을 계기로 아직까지도 개발 열정 불꽃은 유효하다. 요즘들어 출퇴근 길에 자발적으로 부족하다고 느끼는 부분을 찾기도 한다. </p>
<p>이런 나 좀 신기하다...</p>
<p><br><br></p>
<h3 id="더-늦기-전에-건강-챙기기">더 늦기 전에 건강 챙기기!</h3>
<p>직업병인지는 모르겠으나 나는 항상 자세가 안 좋다. 스스로도 느껴진다. 걸음 걸이나, 앉는 자세가 항상 삐뚤고 비대칭이라는 것을. 운동 부족임을 느끼고 있음에도 그동안 운동 시도를 많이 해보진 않았다. 그리고 내가 허리가 안쪽으로 많이 들어가있어서 그냥 누워있는 것도 힘이 든다. 허리가 뜬 채로 누워있는 자세가 너무 불편하기 때문이다. 다리를 90도로 들어야 허리가 펴지니까 그 자세가 더 편해서 항상 90도 테이블 탑 자세를 하고 자곤 했다.</p>
<p>어느 날은 문득 이 습관을 고쳐야겠더라. 그래서 필라테스를 등록했다. 1:1이라 비록 비싼 가격이지만 건강을 돈 주고 산다고 생각하며 아깝게 생각하지 않기로 했다. 필라테스는 매주 1~2일을 다닌다. 50분 수업을 하는데 시간이 그렇게 빨리 갈 수가 없다. 매일매일 소리지름 및 고통과 함께 나의 건강을 되돌리고 있다.</p>
<p>필라테스 13회 정도 수업을 들었고, 현재는 누워있을 때 90도 테이블 탑을 하지 않아도 허리가 뜨는 기분이 덜 해서 불편하지가 않다. 그리고 서있는 자세 또한 많이 교정이 되었다. 아직 한참 부족하지만 건강한 신체가 되는 그 날까지 계속 도전하겠다...!</p>
<p><br><br></p>
<h3 id="마무리">마무리</h3>
<p>2023년 나의 한 해를 압축하자면 이렇다. 올 해 가장 중요한 다짐인 <strong>&#39;자존감 올리기&#39;</strong> 와 <strong>&#39;하고싶은 것 찾기&#39;</strong> 를 이루기 위해, 자발적으로 도전해서 무언가를 이루어낸 경험이 주를 이루었다. 취미를 찾았고, 개발 번아웃도 해결을 했으며 나의 가장 큰 고민이었던 낮은 자존감까지 올랐다.</p>
<p>나의 올 해 세번째 다짐인 <strong>&#39;책 읽기&#39;</strong> 는 좀 아쉽지만 올 해 3권밖에 읽지 못 했다. 난 원래 책 1권도 읽지 않았던 사람이긴 한데... 그래도 시간 대비 많이 읽진 않았으니 세번째 다짐은 한 30%정도 이루었다고 할 생각이다.</p>
<p>나는 이제 웬만해서는 내 탓을 하지 않으며, 실패를 해도 과거에 머무르는 시간이 줄었고, 오히려 미래를 바라보며 어떻게 개선을 할 지 고민을 하는 내가 되었다. 
<strong>실패한 과거? 미련없이 패스해야한다. 어차피 과거는 돌아오지 않는다. 다시 실패를 반복하지 않는 시간이 더 유익하다.</strong> </p>
<p>성격적인 부분도 많이 변했다. 예전에는 누군가가 나를 지적하면 엄청난 자기 비하로 나를 깎아먹고 상처 받기에 급급했는데, 이제는 지적을 받으면 어떻게 개선해야할지 고민을 하게 된다. 그리고 나의 임무처럼 마음 한 켠에 자리 잡아서는 어떻게든 개선하려고 한다. <del>(실제로 개선되었는지는 상대방에게 듣지 못 해서 알 수는 없다. ㅎㅎ)</del></p>
<p>진짜 마무으리...
올 한 해 우울로 시작했지만 기쁨으로 승화했다. 여태 살면서 한 번도 만족스러운 해가 없었는데 처음으로 만족스러운 해이다. 이렇게 글로 쓰며 되돌아보니 나는 하고싶은 일을 해야 몸이 움직이는 사람이라는 것을 깨달았고, 그래야 결과도 긍정적으로 나온다는 것을 직접 확인했다. 나를 가슴 뛰게 하는 일이 무엇인지 앞으로 또 생각하고 실천해야겠다.</p>
<br>

<p>2023년의 다짐 얼마나 이루었는가?</p>
<blockquote>
<ol>
<li>자존감 올리기 (⭐️⭐️⭐️⭐️⭐️) <em><strong>=&gt; 90%</strong></em></li>
<li>하고싶은 것 찾기 (⭐️⭐️⭐️⭐️) <em><strong>=&gt; 100%</strong></em></li>
<li>책 읽기 (⭐️⭐️⭐️) <em><strong>=&gt; 30%</strong></em></li>
</ol>
</blockquote>
<p>만족 ✌(‘ω’)✌ 
2024년 계획도 또 야무지게 세워서 지켜나가야겠다~!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Clean Code] 클린 코드(Clean Code) 6장 '객체와 자료구조' 요약]]></title>
            <link>https://velog.io/@dev_jiwon/Clean-Code-%ED%81%B4%EB%A6%B0-%EC%BD%94%EB%93%9CClean-Code-6%EC%9E%A5-%EA%B0%9D%EC%B2%B4%EC%99%80-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EC%9A%94%EC%95%BD</link>
            <guid>https://velog.io/@dev_jiwon/Clean-Code-%ED%81%B4%EB%A6%B0-%EC%BD%94%EB%93%9CClean-Code-6%EC%9E%A5-%EA%B0%9D%EC%B2%B4%EC%99%80-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EC%9A%94%EC%95%BD</guid>
            <pubDate>Mon, 18 Dec 2023 15:49:52 GMT</pubDate>
            <description><![CDATA[<h1 id="6장-객체와-자료구조">6장 객체와 자료구조</h1>
<p>(자료 구조를 사용하는) 절차적인 코드는 기존 자료 구조를 변경하지 않으면서 새 함수를 추가하기 쉽다. 반면, 객체 지향 코드는 기존 함수를 변경하지 않으면서 새 클래스를 추가하기 어렵다.
<br></p>
<p>반대쪽도 참이다.
<br></p>
<p>절차적인 코드는 새로운 자료 구조를 추가하기 어렵다. 그러려면 모든 함수를 고쳐야한다. 객체 지향 코드는 새로운 함수를 추가하기 어렵다. 그러려면 모든 클래스를 고쳐야한다.</p>
<br>

<p>다시 말해, 객체 지향 코드에서 어려운 변경은 절차적인 코드에서 쉬우며, 절차적인 코드에서 어려운 변경은 객체 지향 코드에서 쉽다!</p>
<br>

<blockquote>
<p>👩🏻‍💻 💡 
이번 6장에서는 내용도 적었고 나에게 크게 와닿는 내용이 없었기 때문에, 6장에 나온 디미터 법칙에 대해 요약하고, 추가로 공부한 내용을 정리하였다.</p>
</blockquote>
<h2 id="디미터-법칙">디미터 법칙</h2>
<p>디미터 법칙은 잘 알려진 휴리스틱으로, <strong>모듈은 자신이 조작하는 객체의 속사정을 몰라야한다</strong>는 법칙이다. 
간단히 말하면 아래의 메소드만 호출하는 규칙들을 지키며 결합도를 낮추는 법칙이다.</p>
<ul>
<li>객체 자신의 메소드들</li>
<li>파라미터로 넘어온 객체들의 메소드들</li>
<li>메소드 안에서 생성되거나 초기화된 메소드들</li>
<li>자신이 직접 소유하는 객체의 메소드들</li>
<li>파라미터로 접근이 가능한 전역 변수의 메소드들</li>
</ul>
<h3 id="기차-충돌">기차 충돌</h3>
<pre><code>const obj = object.getChild()
  .getContent()
  .getItem()
  .getTitle();</code></pre><p>흔히 위와 같은 코드를 기차 충돌이라 부른다. 여러 객차가 한 줄로 이어진 기차처럼 보이기 때문이다. 일반적으로 조잡하다 여겨지는 방식이므로 피하는 편이 좋다. 이런식으로 호출하면 obj는 getChild, getContent, getItem, getTitle 함수에 모두 의존적이게 된다.</p>
<br>
의존하면서 결합도가 높아지기 때문에, 함수형 프로그래밍의 지향점(함수는 결합도↓, 응집도↑일수록 이상적이다.)을 위반한다. 최대한 노출 범위를 제한해서 유지보수가 쉽게 해야한다.



<p><br><br></p>
<h3 id="결론">결론</h3>
<h4 id="⭐️⭐️⭐️-디미터-법칙을-지킬수록-결합도는-느슨해진다-디미터-법칙을-지키자">⭐️⭐️⭐️ 디미터 법칙을 지킬수록 결합도는 느슨해진다. 디미터 법칙을 지키자!</h4>
<p><br><br></p>
<h4 id="참고">참고</h4>
<p><a href="https://hongjinhyeon.tistory.com/138">https://hongjinhyeon.tistory.com/138</a></p>
<p><a href="https://hungryjayy.github.io/posts/%EB%94%94%EB%AF%B8%ED%84%B0_%EB%B2%95%EC%B9%99/#%EB%94%94%EB%AF%B8%ED%84%B0-%EB%B2%95%EC%B9%99%EC%9D%B4-%ED%95%98%EB%82%98%EC%9D%98-%EC%9D%84-%EA%B0%95%EC%A0%9C%ED%95%98%EB%8A%94-%EA%B7%9C%EC%B9%99%EC%9D%80-%EC%95%84%EB%8B%88%EB%8B%A4">https://hungryjayy.github.io/posts/%EB%94%94%EB%AF%B8%ED%84%B0_%EB%B2%95%EC%B9%99/#%EB%94%94%EB%AF%B8%ED%84%B0-%EB%B2%95%EC%B9%99%EC%9D%B4-%ED%95%98%EB%82%98%EC%9D%98-%EC%9D%84-%EA%B0%95%EC%A0%9C%ED%95%98%EB%8A%94-%EA%B7%9C%EC%B9%99%EC%9D%80-%EC%95%84%EB%8B%88%EB%8B%A4</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Clean Code] 클린 코드(Clean Code) 5장 '형식 맞추기' 요약]]></title>
            <link>https://velog.io/@dev_jiwon/Clean-Code-%ED%81%B4%EB%A6%B0-%EC%BD%94%EB%93%9CClean-Code-5%EC%9E%A5-%ED%98%95%EC%8B%9D-%EB%A7%9E%EC%B6%94%EA%B8%B0-%EC%9A%94%EC%95%BD</link>
            <guid>https://velog.io/@dev_jiwon/Clean-Code-%ED%81%B4%EB%A6%B0-%EC%BD%94%EB%93%9CClean-Code-5%EC%9E%A5-%ED%98%95%EC%8B%9D-%EB%A7%9E%EC%B6%94%EA%B8%B0-%EC%9A%94%EC%95%BD</guid>
            <pubDate>Sun, 19 Nov 2023 05:14:40 GMT</pubDate>
            <description><![CDATA[<h1 id="5장-형식-맞추기">5장 형식 맞추기</h1>
<p>뚜껑을 열었을 때 독자들이 코드가 깔끔하고, 일관적이며, 꼼꼼하다고 감탄하면 좋겠다. 프로그래머라면 형식을 깔끔하게 맞춰 코드를 짜야 한다. 코드 형식을 맞추기 위한 간단한 규칙을 정하고 그 규칙을 착실히 따라야 한다.</p>
<br>

<h2 id="형식을-맞추는-목적">형식을 맞추는 목적</h2>
<p>무엇보다 먼저, 한 가지를 분명히 짚고 넘어가자. 코드 형식은 중요하다! 너무 중요해서 무시하기 어렵다. 코드 형식은 의사소통의 일환이다.</p>
<blockquote>
<p><strong>오늘 구현한 코드의 가독성은 앞으로 바뀔 코드의 품질에 지대한 영향을 미친다.</strong></p>
</blockquote>
<p>맨 처음 잡아놓은 구현 스타일과 가독성 수준은 유지보수 용이성과 확장성에 계속 영향을 미친다.</p>
<blockquote>
<p>👩🏻‍💻 💡 끼어들기
너무너무 공감한다. 나도 코드를 작성할 때, 유지보수를 고려하여 누군가가 내 코드를 보았을 때 해석이 가능하고 수정이 가능할 수 있도록 작성하려고 노력한다. 
코드 품질을 생각하는 것은 나중이 될 수 없다. 무조건 코드를 작성할 때 고려해야한다!</p>
</blockquote>
<p>그렇다면 원활한 소통을 장려하는 코드 형식은 무엇일까?</p>
<p><br><br></p>
<h2 id="적절한-행-길이를-유지하라">적절한 행 길이를 유지하라</h2>
<p>세로 길이부터 살펴보자. 소스 코드는 얼마나 길어야 적당할까? 일반적으로 큰 파일보다 작은 파일이 이해하기 쉽다.</p>
<h3 id="신문-기사처럼-작성하라">신문 기사처럼 작성하라</h3>
<p>아주 좋은 신문 기사를 떠올려보라. 독자는 위에서 아래로 기사를 읽는다. 최상단에 기사를 몇 마디로 요약하는 표제가 나온다. </p>
<p>소스 파일도 신문 기사와 비슷하게 작성한다. <strong>이름은 간단하면서도 설명이 가능하게 짓는다.</strong> 이름만 보고도 올바른 모듈을 살펴보고 있는지 아닌지를 판단할 정도로 신경 써서 짓는다. 
소스 파일 첫 부분은 고차원 개념과 알고리즘을 설명한다. 아래로 내려갈수록 의도를 세세하게 묘사한다.</p>
<blockquote>
<p>👩🏻‍💻 💡 끼어들기
신문기사로 아주 좋은 예시를 들어주었다. 코드는 위에서부터 아래로 책 읽듯이 술술 읽힌다면 그 코드는 정말 잘 작성된 코드라고 생각한다.</p>
</blockquote>
<h3 id="개념은-빈-행으로-분리하라">개념은 빈 행으로 분리하라</h3>
<p>거의 모든 코드는 왼쪽에서 오른쪽으로 그리고 위에서 아래로 읽힌다. 각 행은 수식이나 절을 나타내고, 일련의 행 묶음은 완결된 생각 하나를 표현한다. </p>
<p>생각 사이는 빈 행을 넣어 분리해야 마땅하다. 빈 행은 새로운 개념을 시작한다는 시각적 단서다.</p>
<h3 id="수직-거리">수직 거리</h3>
<p>서로 밀접한 개념은 세로로 가까이 둬야 한다.</p>
<h4 id="변수-선언">변수 선언</h4>
<p>우리가 만든 함수는 매우 짧으므로 지역 변수는 각 함수 맨 처음에 선언한다.</p>
<h4 id="개념의-유사성">개념의 유사성</h4>
<p>어떤 코드는 서로 끌어당긴다. 개념적인 친화도가 높기 때문이다. 친화도가 높을수록 코드를 가까이 배치한다.</p>
<blockquote>
<p>친화도가 높은 요인</p>
</blockquote>
<ol>
<li>한 함수가 다른 함수를 호출해 생기는 직접적인 종속성</li>
<li>변수와 그 변수를 사용하는 함수</li>
<li>비슷한 동작을 수행하는 일군의 함수</li>
</ol>
<p><br><br></p>
<h2 id="가로-형식-맞추기">가로 형식 맞추기</h2>
<p>프로그래머는 명백하게 짧은 행을 선호한다.</p>
<h3 id="들여쓰기">들여쓰기</h3>
<p>소스 파일은 윤곽도와 계층이 비슷하다. 계층에서 각 수준은 이름을 선언하는 범위이자 선언문과 실행문을 해석하는 범위다. </p>
<p>클래스 내 메서드는 클래스보다 한 수준 들여쓴다. 메서드 코드는 메서드 선언보다 한 수준 들여쓴다. 블록 코드는 블록을 포함하는 코드보다 한 수준 들여쓴다.</p>
<p>프로그래머는 이런 들여쓰기 체계에 크게 의존한다. 왼쪽으로 코드를 맞춰 코드가 속하는 범위를 시각적으로 표현한다. 들여쓰기한 파일은 구조가 한눈에 들어온다.</p>
<p><br><br></p>
<h2 id="팀-규칙">팀 규칙</h2>
<p>좋은 소프트웨어 시스템은 읽기 쉬운 문서로 이뤄진다는 사실을 기억하기 바란다. 스타일은 일관적이고 매끄러워야 한다. 한 소스 파일에서 봤던 형식이 다른 소스 파일에도 쓰이리라는 신뢰감을 독자에게 줘야 한다.</p>
<p><br><br>
-알라딘 eBook &lt;클린 코드 Clean Code&gt; (로버트 C. 마틴 지음, 이해영.박재호 옮김) 중에서</p>
]]></description>
        </item>
    </channel>
</rss>