<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>One IT's Devlog</title>
    <link>https://one-it.tistory.com/</link>
    <description>JavaScript와 React, React Native를 다루는 프론트엔드 개발 블로그. 이외에도 회사, IT 이야기, 일상 등을 다룹니다.
본 블로그는 사람이 직접 작성합니다. AI 자동화를 통한 양산 콘텐츠를 단호히 반대합니다.</description>
    <language>ko</language>
    <pubDate>Thu, 12 Mar 2026 13:31:02 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>아이톤</managingEditor>
    <item>
      <title>안드로이드 네이티브 개발 공부: 1. 처음 만드는 안드로이드 어플리케이션</title>
      <link>https://one-it.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C-%EA%B0%9C%EB%B0%9C-%EA%B3%B5%EB%B6%80-1-%EC%B2%98%EC%9D%8C-%EB%A7%8C%EB%93%9C%EB%8A%94-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Chapter 1. 처음 만드는 안드로이드 애플리케이션&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;UI 레이아웃 디자인하기&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 프로젝트 생성하기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Empty Activity 보단 Empty View Activity를 선택하는 것이 좋다.&lt;/li&gt;
&lt;li&gt;참고 글&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1745064880456&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;안드로이드 스튜디오 프로젝트에 왜 Layout폴더, activity_main.xml이 없을까?&quot; data-og-description=&quot;깡샘의 안드로이드 앱 프로그래밍을 공부하면서도, 지금 Joyce의 안드로이드 앱 프로그래밍을 공부하면서도 프로젝트를 새로 생성할 때 Empty Activity를 선택하라고 해왔기 때문에 당연히 그대로 &quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@jejun_/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90-%EC%99%9C-Layout%ED%8F%B4%EB%8D%94-activitymain.xml%EC%9D%B4-%EC%97%86%EC%9D%84%EA%B9%8C&quot; data-og-url=&quot;https://velog.io/@jejun_/안드로이드-스튜디오-프로젝트에-왜-Layout폴더-activitymain.xml이-없을까&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/JS5Lv/hyYG1sOhHn/M2FFGcrJ8ycfk1H0Kw9Xd1/img.png?width=1936&amp;amp;height=1494&amp;amp;face=0_0_1936_1494,https://scrap.kakaocdn.net/dn/Wiul0/hyYFz98Fbs/rpRYl9s8vRVoljzAeEsmk1/img.png?width=1936&amp;amp;height=1494&amp;amp;face=0_0_1936_1494,https://scrap.kakaocdn.net/dn/4b2ha/hyYIcTY0C9/k6R71s8lyBp6BYzCFxiHT0/img.jpg?width=2613&amp;amp;height=3505&amp;amp;face=0_0_2613_3505&quot;&gt;&lt;a href=&quot;https://velog.io/@jejun_/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90-%EC%99%9C-Layout%ED%8F%B4%EB%8D%94-activitymain.xml%EC%9D%B4-%EC%97%86%EC%9D%84%EA%B9%8C&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@jejun_/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90-%EC%99%9C-Layout%ED%8F%B4%EB%8D%94-activitymain.xml%EC%9D%B4-%EC%97%86%EC%9D%84%EA%B9%8C&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/JS5Lv/hyYG1sOhHn/M2FFGcrJ8ycfk1H0Kw9Xd1/img.png?width=1936&amp;amp;height=1494&amp;amp;face=0_0_1936_1494,https://scrap.kakaocdn.net/dn/Wiul0/hyYFz98Fbs/rpRYl9s8vRVoljzAeEsmk1/img.png?width=1936&amp;amp;height=1494&amp;amp;face=0_0_1936_1494,https://scrap.kakaocdn.net/dn/4b2ha/hyYIcTY0C9/k6R71s8lyBp6BYzCFxiHT0/img.jpg?width=2613&amp;amp;height=3505&amp;amp;face=0_0_2613_3505');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;안드로이드 스튜디오 프로젝트에 왜 Layout폴더, activity_main.xml이 없을까?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;깡샘의 안드로이드 앱 프로그래밍을 공부하면서도, 지금 Joyce의 안드로이드 앱 프로그래밍을 공부하면서도 프로젝트를 새로 생성할 때 Empty Activity를 선택하라고 해왔기 때문에 당연히 그대로&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2 ~ 3. UI 레이아웃 디자인하기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최초로 실행되는 액티비티의 기본 이름 MainActivity&lt;/li&gt;
&lt;li&gt;액티비티 레이아웃 규칙
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;code&gt;activity_{액티비티명}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;ex) SplashScreenActivity -&amp;gt; activity_splash_screen&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;루트 요소의 xml 네임스페이스는 &lt;a href=&quot;http://schemas.android.com/apk/res/android&quot;&gt;http://schemas.android.com/apk/res/android&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 위젯 설정&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;android:layout_width, android:layout_height
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;match_parent&lt;/code&gt;: 자신의 부모만큼의 크기 차지&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wrap_content&lt;/code&gt;: 자신이 갖는 콘텐츠에 필요한 크기 차지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;dp: 해상도에 독립적인 픽셀(density-independent pixel)&lt;/li&gt;
&lt;li&gt;android:text
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;@string/{키}&lt;/code&gt;: 문자열 리소스에 대한 참조(strings.xml에 정의해야 함)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>프론트엔드 개발/안드로이드</category>
      <category>Android</category>
      <category>ui 레이아웃</category>
      <author>아이톤</author>
      <guid isPermaLink="true">https://one-it.tistory.com/64</guid>
      <comments>https://one-it.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C-%EA%B0%9C%EB%B0%9C-%EA%B3%B5%EB%B6%80-1-%EC%B2%98%EC%9D%8C-%EB%A7%8C%EB%93%9C%EB%8A%94-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98#entry64comment</comments>
      <pubDate>Sat, 19 Apr 2025 21:16:55 +0900</pubDate>
    </item>
    <item>
      <title>안드로이드 네이티브 개발 공부: 0. 책 고르기</title>
      <link>https://one-it.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C-%EA%B0%9C%EB%B0%9C-%EA%B3%B5%EB%B6%80-0-%EC%B1%85-%EA%B3%A0%EB%A5%B4%EA%B8%B0</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;652&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcr4FW/btsNnVRkVIE/Fftx98krnKKCy8vCtcLrE1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcr4FW/btsNnVRkVIE/Fftx98krnKKCy8vCtcLrE1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcr4FW/btsNnVRkVIE/Fftx98krnKKCy8vCtcLrE1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbcr4FW%2FbtsNnVRkVIE%2FFftx98krnKKCy8vCtcLrE1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;652&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;652&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React Native로 앱 개발을 하고 있지만, 결국 제대로 하려면 네이티브 개발 공부를 해야 한다는 사실을 느꼈다. 그래서 기초적인 내용이나마 iOS와 함께 Android 네이티브 개발을 공부해보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강의도 좋지만 우선 기본적으로 정석같은 책이 있으면 좋을 것 같아서 하나 추천을 받은게 &quot;&lt;b&gt;실무에 바로 적용하는 안드로이드 프로그래밍&lt;/b&gt;&quot;(제4판)이었다. ChatGPT한테 추천받은 책이어서 고민 중이었는데 친구인 호주 개발자인 @chi-chi님도 이 책을 추천해줘서 결정하게 됐다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 책으로 조금씩 공부해보고 그걸 기록해보기로 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 ChatGPT가 알려준 이 책의 장점은 이렇다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;실무에 바로 적용하는 안드로이드 프로그래밍&quot;(Android Programming: The Big Nerd Ranch Guide)는 아주 좋은 책이야.&lt;br /&gt;&lt;br /&gt;이 책의 장점은:&lt;br /&gt;&lt;b&gt;✅ 기초부터 차근차근 설명&lt;/b&gt; &amp;ndash; Android 생명주기, UI 구성, 데이터 저장, 네트워크 등 기초 개념을 깊이 있게 다룸&lt;br /&gt;&lt;b&gt;✅ 실습 위주 구성&lt;/b&gt; &amp;ndash; 따라 하면서 직접 구현할 수 있는 예제가 많음&lt;br /&gt;&lt;b&gt;✅ 실무에서 필요한 내용 포함&lt;/b&gt; &amp;ndash; RecyclerView, 데이터 저장, API 통신 등 실제 앱 개발에 필요한 내용을 다룸&lt;br /&gt;&lt;br /&gt;  주의할 점&lt;br /&gt;- 최신 트렌드인 &lt;b&gt;Jetpack Compose&lt;/b&gt; 대신 &lt;b&gt;기존 XML 기반 UI&lt;/b&gt;를 중심으로 설명 Kotlin 기반 설명인지 확인 필요 (예전 버전은 Java로 설명) &lt;br /&gt;&lt;br /&gt;  추천 활용법&lt;br /&gt;1. 이 책으로 &lt;b&gt;기본 개념 &amp;amp; Android 구조&lt;/b&gt;를 먼저 익히고,&lt;br /&gt;2. 이후 &lt;b&gt;Jetpack Compose&lt;/b&gt; 강의/공식 문서로 최신 UI 개발 방식까지 배우는 걸 추천! &lt;br /&gt;&lt;br /&gt;혹시 Jetpack Compose 중심의 책을 찾고 있다면 &quot;Android Jetpack Compose Essentials&quot; 같은 책도 고려해볼 만해.  &lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시 이 책에 대해 잘 알고 있거나 흥미가 있으신 분은 댓글로 반응 주시면 감사하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프론트엔드 개발/안드로이드</category>
      <category>ChatCPT</category>
      <category>React Native</category>
      <category>네이티브 개발</category>
      <category>실무에 바로 적용하는 안드로이드 프로그래밍</category>
      <category>안드로이드</category>
      <author>아이톤</author>
      <guid isPermaLink="true">https://one-it.tistory.com/63</guid>
      <comments>https://one-it.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C-%EA%B0%9C%EB%B0%9C-%EA%B3%B5%EB%B6%80-0-%EC%B1%85-%EA%B3%A0%EB%A5%B4%EA%B8%B0#entry63comment</comments>
      <pubDate>Thu, 17 Apr 2025 23:05:24 +0900</pubDate>
    </item>
    <item>
      <title>JSX, TSX를 SVG로 변환하기</title>
      <link>https://one-it.tistory.com/entry/JSX-TSX%EB%A5%BC-SVG%EB%A1%9C-%EB%B3%80%ED%99%98%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;React Native에서 SVG를 컴포넌트화하여 사용하는 경우가 많은데 이를 위해 SVG -&amp;gt; JSX/TSX로 변환하는 컨버터는 쉽게 찾을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 그 반대의 경우인 JSX/TSX -&amp;gt; SVG로 변환하고자 할 땐 어떻게 해야 할까? 이 경우엔 컨버터나 방법을 찾기 어려웠는데 쉬운 방법이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 JSX/TSX 컴포넌트에서 return 값만을 빼내어 각 컴포넌트들을 svg 태그로 변환해주고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;svg 태그에 xmlns=&quot;&lt;a href=&quot;https://www.w3.org/2000/svg&amp;quot;&quot;&gt;https://www.w3.org/2000/svg&quot;&lt;/a&gt; 어트리뷰트를 추가해주면 된다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;xmlns를 추가해주지 않으면 보통 웹브라우저에선 svg 파일로 인식하지 않고 &amp;lsquo;This XML file does not appear to have any style information associated with it. The document tree is shown below.&amp;rsquo; 에러를 내며 깨진다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시를 통해 살펴보자.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import * as React from &quot;react&quot;
import Svg, { Path } from &quot;react-native-svg&quot;

function SvgComponent(props) {
  return (
    &amp;lt;Svg
      style={{
        flex: 1
      }}
      {...props}
    &amp;gt;
      &amp;lt;Path d=&quot;M10 10H110V110H10z&quot; stroke=&quot;red&quot; fill=&quot;#00f&quot; /&amp;gt;
    &amp;lt;/Svg&amp;gt;
  )
}

export default SvgComponent&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 컴포넌트가 있다면 아래와 같이 바꿔주면 된다.&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;svg
  style=&quot;flex: 1&quot; 
  xmlns=&quot;http://www.w3.org/2000/svg&quot;
&amp;gt;
  &amp;lt;path d=&quot;M10 10H110V110H10z&quot; stroke=&quot;red&quot; fill=&quot;#00f&quot; /&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설명을 덧붙이자면 Svg -&amp;gt; svg, Path -&amp;gt; path로, &lt;code&gt;xmlns=&quot;http://www.w3.org/2000/svg&quot;&lt;/code&gt; 추가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSX의 문법(&lt;code&gt;style={{ flex:1 }}&lt;/code&gt; 등)은 html의 문법에 맞게 수정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 수정 후 svg 파일로 저장하면 원하는 svg 이미지 파일로 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일부 복잡한 svg의 경우 호환되지 않는 경우가 있으니 이 경우엔 해당 컴포넌트에 해당하는 svg 태그를 직접 찾아서 변환해주면 된다.&lt;/p&gt;</description>
      <category>프론트엔드 개발/React &amp;amp; RN</category>
      <category>JSX</category>
      <category>React Native</category>
      <category>SVG</category>
      <category>TSX</category>
      <author>아이톤</author>
      <guid isPermaLink="true">https://one-it.tistory.com/61</guid>
      <comments>https://one-it.tistory.com/entry/JSX-TSX%EB%A5%BC-SVG%EB%A1%9C-%EB%B3%80%ED%99%98%ED%95%98%EA%B8%B0#entry61comment</comments>
      <pubDate>Mon, 4 Nov 2024 22:40:31 +0900</pubDate>
    </item>
    <item>
      <title>Codepush Standalone 버전 출시 (코드푸쉬 대안)</title>
      <link>https://one-it.tistory.com/entry/Codepush-Standalone-%EB%B2%84%EC%A0%84-%EC%B6%9C%EC%8B%9C-%EC%BD%94%EB%93%9C%ED%91%B8%EC%89%AC-%EB%8C%80%EC%95%88</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1727650998423&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - microsoft/code-push-server: Standalone CodePush server from App Center&quot; data-og-description=&quot;Standalone CodePush server from App Center. Contribute to microsoft/code-push-server development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/microsoft/code-push-server&quot; data-og-url=&quot;https://github.com/microsoft/code-push-server&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/vx7jP/hyXaJsCzNS/SqIiccOARYkWx5BEj7mR5k/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/tF8Tc/hyXaAvGcQJ/whh2pK3YJPgDuVQhJ923ZK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/microsoft/code-push-server&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/microsoft/code-push-server&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/vx7jP/hyXaJsCzNS/SqIiccOARYkWx5BEj7mR5k/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/tF8Tc/hyXaAvGcQJ/whh2pK3YJPgDuVQhJ923ZK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - microsoft/code-push-server: Standalone CodePush server from App Center&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Standalone CodePush server from App Center. Contribute to microsoft/code-push-server development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드푸쉬 standalone 버전이 출시되었습니다  &lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MS가 Appcenter 서비스를 종료함에 따라 CodePush도 자연스레 종료하게 되었는데요.   (관련내용: &lt;a href=&quot;https://learn.microsoft.com/en-us/appcenter/retirement&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://learn.microsoft.com/en-us/appcenter/retirement&lt;/a&gt; )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대신 Standalone 버전을 출시해 필요한 유저가 있다면 자신의 서버에 직접 구축해서 사용할 수 있도록 소스코드를 배포했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문의할때마다 정해진 일정은 없다며 공개하지 않던 MS에서 마침내 배포했네요. 2025년 3월 서비스 종료니까 그 전까지 이 소스를 가지고 서버를 구축하기에 시간은 충분한 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자세한 설치방법이나 사용법은 더 알아봐야 하겠지만, 어쨌든 많은 React Native 유저들에게는 희망적인 소식이네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 React Native의 Codepush 대안은 아래 두가지가 되었습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. MS Codepush Standalone 직접 설치 및 운영 (무료, 서버비 별도)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a title=&quot;Microsoft code-push-server 깃헙 레포지토리 링크&quot; href=&quot;https://github.com/microsoft/code-push-server&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/microsoft/code-push-server&lt;/a&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. Expo Update 사용 (EAS, 유료)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a title=&quot;Expo Update (EAS) 링크&quot; href=&quot;https://docs.expo.dev/versions/latest/sdk/updates/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.expo.dev/versions/latest/sdk/updates/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자세한 내용은 추후에 재업로드 하도록 하겠습니다.&lt;/p&gt;</description>
      <category>프론트엔드 개발/React &amp;amp; RN</category>
      <category>codepush</category>
      <category>codepush standalone</category>
      <category>codepush 대안</category>
      <category>codepush 중단</category>
      <category>eas</category>
      <category>Expo</category>
      <category>Ota</category>
      <category>React Native</category>
      <category>Update</category>
      <category>서비스 종료</category>
      <author>아이톤</author>
      <guid isPermaLink="true">https://one-it.tistory.com/59</guid>
      <comments>https://one-it.tistory.com/entry/Codepush-Standalone-%EB%B2%84%EC%A0%84-%EC%B6%9C%EC%8B%9C-%EC%BD%94%EB%93%9C%ED%91%B8%EC%89%AC-%EB%8C%80%EC%95%88#entry59comment</comments>
      <pubDate>Mon, 30 Sep 2024 08:12:04 +0900</pubDate>
    </item>
    <item>
      <title>React Native에서 상수 선언시 주의점</title>
      <link>https://one-it.tistory.com/entry/React-Native%EC%97%90%EC%84%9C-%EC%83%81%EC%88%98-%EC%84%A0%EC%96%B8%EC%8B%9C-%EC%A3%BC%EC%9D%98%EC%A0%90</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;개발을 하다보면 상수 선언을 할 때가 많은데 React, 특히 React Native에 상수를 선언할 때 특히 주의해야 할 점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트 외부에 상수를 선언하면 그 상수는 컴포넌트의 갱신주기 및 라이프사이클을 완전히 벗어나게 된다. 일반적인 경우 큰 문제되지 않지만, 실제로 그것이 고정된 값(상수)가 아니라 어떤 조건에 따라 변화하는 값을 다룰땐 주의해야 한다. 특히 시간과 같이 실제로는 내부적으로 변화되어야 하는 값을 상수로 처리할때 주의해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 예시를 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 moment는 현재 시간을 가져오기 위해 사용한 타임 라이브러리의 일종이다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;...
const NOW_TIME = moment() // 컴포넌트 외부에 선언된 상수

export default function ExampleComp () {
  return (
    &amp;lt;View&amp;gt;
      &amp;lt;Text&amp;gt;{NOW_TIME.format('YYYY-MM-DD HH:mm:ss')}&amp;lt;/Text&amp;gt; 
    &amp;lt;/View&amp;gt;
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 NOW_TIME은 앱을 실행시키고 값을 한번 할당한 이후엔 앱을 재실행하지 않는 이상 절대 변하지 않는다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;...

export default function ExampleComp () {
  const NOW_TIME = moment() // 컴포넌트 내부에 선언된 상수
  return (
    &amp;lt;View&amp;gt;
      &amp;lt;Text&amp;gt;{NOW_TIME.format('YYYY-MM-DD HH:mm:ss')}&amp;lt;/Text&amp;gt; 
    &amp;lt;/View&amp;gt;
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 이 NOW_TIME은 앱을 실행시키고 ExampleComp의 라이프사이클에 따르며 마운트 당시의 값을 지니게 된다. 즉, 앱 재실행 없이 해당 컴포넌트 마운트/언마운트에 따라 값이 변하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 이유로 같은 상수 선언처럼 보여도 실제 결과는 완전 달라질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조금 더 구체적인 예시를 살펴보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가령 매일 어떤 시간 리스트를 받아서 18시 이후는 잘라내는 로직을 생각해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 CUT_TIME이란걸 지정해서 18시 이후의 데이터는 컷하는 식으로 로직을 짤 수 있다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;...
const HOUR_18 = moment().set({hour: 18, minute: 0, second: 0, millisecond:0});

export default function ExampleComp ({timeList}: {timeList: ITimeObj[]}) {
  const [list, setList] = useState([])
  useEffect(() =&amp;gt; {
    const filteredList = timelist.filter((item)=&amp;gt;{
      return item.isBefore(HOUR_18);
    })
    setList(filteredList);
  }, [timeList])
	
  return (
    &amp;lt;View&amp;gt;
      {list.map((i) =&amp;gt; {
        return (
          &amp;lt;View&amp;gt;
            &amp;lt;Text&amp;gt;{i.format('YYYY-MM-DD HH:mm:ss'}&amp;lt;/Text&amp;gt;
          &amp;lt;/View&amp;gt;)
      }}
    &amp;lt;/View&amp;gt;
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 했을 경우 NOW_TIME이 앱 실행 날짜의 18시로 고정된다. 앱을 재실행하지 않는 이상 이 값은 절대 변하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 9월 11일에 앱을 실행시키고 백그라운드에 놓은채 9월 12일에 다시 그 앱을 포그라운드로 돌려놨다고 생각해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버는 9월 12일자 데이터를 내리고, 앱은 9월 12일자 18시 이전의 데이터를 그리길 원하겠지만, 실제로는 아무것도 그려지지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜냐면 18시 이전으로 필터링하기 위한 기준값이 HOUR_18이 앱 실행시점인 9월 11일자 18시로 고정되어 있기 때문에 9월 12일자 00시든, 10시든, 17시 55분이든 9월 11일 18시 이후이므로 아무것도 그리지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 의도한 UI를 보고자 한다면 앱을 재실행하는 수밖에 없다. 이걸 해결하기 위해선 코드를 아래와 같이 바꾸면 된다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;...

export default function ExampleComp ({timeList}) {
  const HOUR_18 = moment().set({hour: 18});
	
  const [list, setList] = useState([])
	
  useEffect(() =&amp;gt; {
    const filteredList = timelist.filter((item)=&amp;gt;{
      return item.isBefore(HOUR_18);
    })
    setList(filteredList);
  }, [timeList])
	
  return (
    &amp;lt;View&amp;gt;
      {list.map((i) =&amp;gt; {
        return (
          &amp;lt;View&amp;gt;
            &amp;lt;Text&amp;gt;{i.format('YYYY-MM-DD HH:mm:ss'}&amp;lt;/Text&amp;gt;
          &amp;lt;/View&amp;gt;)
      }}
    &amp;lt;/View&amp;gt;
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상수가 컴포넌트 안에 선언되어 해당 컴포넌트가 마운트 될 때 그 시간에 맞춰 재정의되니 원래 의도했던대로 작동한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹은 일반적으로 오래 켜두는 일이 드물고 거의 매 실행이 재실행과 다름없지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React Native와 같이 앱의 경우 보통 앱을 백그라운드에 놔뒀다가 필요할때 포그라운드로 호출해서 쓰는 패턴이 일반적이다. 앱을 완전히 껏다가 재실행하는 경우가 거의 없으므로 컴포넌트 외부에 위치한 상수가 의도한대로 갱신되지 않을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내부적 로직에 따라 상수를 갱신해야 할때, 그 상수 선언은 이런 케이스처럼 조심해야 한다.&lt;/p&gt;</description>
      <category>프론트엔드 개발/React &amp;amp; RN</category>
      <category>react</category>
      <category>React Native</category>
      <category>갱신주기</category>
      <category>라이프사이클</category>
      <category>상수</category>
      <category>생명주기</category>
      <author>아이톤</author>
      <guid isPermaLink="true">https://one-it.tistory.com/58</guid>
      <comments>https://one-it.tistory.com/entry/React-Native%EC%97%90%EC%84%9C-%EC%83%81%EC%88%98-%EC%84%A0%EC%96%B8%EC%8B%9C-%EC%A3%BC%EC%9D%98%EC%A0%90#entry58comment</comments>
      <pubDate>Wed, 11 Sep 2024 16:55:49 +0900</pubDate>
    </item>
    <item>
      <title>코드조각: 중복없이 아이템 랜덤뽑기 (Array에서 n개 꺼내기)</title>
      <link>https://one-it.tistory.com/entry/%EC%BD%94%EB%93%9C%EC%A1%B0%EA%B0%81-Array%EC%97%90%EC%84%9C-%EB%9E%9C%EB%8D%A4%EC%9C%BC%EB%A1%9C-%EC%A4%91%EB%B3%B5%EC%97%86%EC%9D%B4-n%EA%B0%9C-%EA%BA%BC%EB%82%B4%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;여러 아이템이 들어있는 Array에서 아이템을 랜덤으로, 그리고 중복없이 n개 뽑아내는 로직입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;array를 ['a', 'b', 'c', 'd', 'e'], cnt를 3으로 하면 ['c', 'b', 'a'] 등의 식으로 랜덤으로 뽑습니다. 단, ['c', 'b', 'c'] 와 같이 중복되는 값은 나오지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요새 TypeScript를 사용해서 TS로 짜봤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자세한 코드는 아래를 참고하세요. 혹시 JavaScript 버전을 원하시면 댓글로 알려주세요.&lt;/p&gt;
&lt;pre id=&quot;code_1702021905288&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/**
 * @param array 아이템 리스트
 * @param cnt 뽑을 아이템 개수
 * @returns 랜덤으로 추출된 아이템 리스트
 */
const getItemRandomly = (array: any[], cnt: number): any[] =&amp;gt; {
  const copyArr = [...array] // splice로 인해 원본 배열이 바뀌는 것을 방지하기 위해 복사본 생성
  if (copyArr.length &amp;lt; cnt) return copyArr;
  const result = [];
  while (result.length &amp;lt; cnt) {
    const randomIndex = Math.floor(Math.random() * copyArr.length);
    let item = copyArr.splice(randomIndex, 1)[0];
    if (item !== undefined &amp;amp;&amp;amp; !!item) {
      result.push(item);
    }
  }
  return result;
};&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이밖에 다른 방법을 알고 있거나 더 효율적인 코드를 아신다면 댓글로 달아주세요. 저는 물론 많은 분들에게 큰 도움이 됩니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;도움이 되셨다면 좋아요❤️와 댓글  부탁드립니다. 감사합니다 &lt;/p&gt;</description>
      <category>프론트엔드 개발/JS &amp;amp; TS</category>
      <category>Array</category>
      <category>TypeScript</category>
      <category>랜덤뽑기</category>
      <author>아이톤</author>
      <guid isPermaLink="true">https://one-it.tistory.com/55</guid>
      <comments>https://one-it.tistory.com/entry/%EC%BD%94%EB%93%9C%EC%A1%B0%EA%B0%81-Array%EC%97%90%EC%84%9C-%EB%9E%9C%EB%8D%A4%EC%9C%BC%EB%A1%9C-%EC%A4%91%EB%B3%B5%EC%97%86%EC%9D%B4-n%EA%B0%9C-%EA%BA%BC%EB%82%B4%EA%B8%B0#entry55comment</comments>
      <pubDate>Sun, 10 Dec 2023 23:50:34 +0900</pubDate>
    </item>
    <item>
      <title>create-react-app 은 더이상 권장되지 않는 방식인가?</title>
      <link>https://one-it.tistory.com/entry/create-react-app-%EC%9D%80-%EB%8D%94%EC%9D%B4%EC%83%81-%EA%B6%8C%EC%9E%A5%EB%90%98%EC%A7%80-%EC%95%8A%EB%8A%94-%EB%B0%A9%EC%8B%9D%EC%9D%B8%EA%B0%80</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;권장사항에서 빠진 &lt;span style=&quot;font-family: 'Noto Serif KR'; color: #333333; text-align: center;&quot;&gt;create-react-app와&lt;/span&gt; 최근의 프론트엔드 개발 트렌트&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제 블로그에 관심이 많으신 분들은 이미 알고 계시겠지만, 사실 전 React보단 React-Native 개발자에 가깝습니다.(아, 웹 하고 싶다!) 그래서 한동안 React 웹서비스를 처음부터 만들 일이 많지 않았죠. 조그마한 토이프로젝트로 React에 대한 열정을 되살리고자 &lt;b&gt;npx create-react-app&lt;/b&gt; 을 사용했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;388&quot; data-origin-height=&quot;442&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2Dzih/btsn1aLSP4M/KbDKvKCLv8J6zOHfY9iKXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2Dzih/btsn1aLSP4M/KbDKvKCLv8J6zOHfY9iKXK/img.png&quot; data-alt=&quot;The Library&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2Dzih/btsn1aLSP4M/KbDKvKCLv8J6zOHfY9iKXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2Dzih%2Fbtsn1aLSP4M%2FKbDKvKCLv8J6zOHfY9iKXK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;388&quot; height=&quot;442&quot; data-origin-width=&quot;388&quot; data-origin-height=&quot;442&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;The Library&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러던 중 꽤나 충격적인 사실을 알게 되었습니다. &lt;b&gt;바로 React 공식문서에서 더 이상 create-react-app을 권하고 있지 않다는 사실을 말이죠.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React에 관심있으신 분들은 아시겠지만 최근 React 공식 웹사이트가 새로 오픈했습니다.&lt;/p&gt;
&lt;figure id=&quot;og_1689600724440&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;React&quot; data-og-description=&quot;The library for web and native user interfaces&quot; data-og-host=&quot;react.dev&quot; data-og-source-url=&quot;https://react.dev/&quot; data-og-url=&quot;https://react.dev/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/TvcUF/hyTk1x7xw8/gKuKFN3ZDhiQYukksOSlg0/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567,https://scrap.kakaocdn.net/dn/qXjy5/hyTmCcoSAY/mKuu4BRKqP1AHO4qtGWYK0/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567&quot;&gt;&lt;a href=&quot;https://react.dev/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://react.dev/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/TvcUF/hyTk1x7xw8/gKuKFN3ZDhiQYukksOSlg0/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567,https://scrap.kakaocdn.net/dn/qXjy5/hyTmCcoSAY/mKuu4BRKqP1AHO4qtGWYK0/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;React&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The library for web and native user interfaces&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;react.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 &lt;a title=&quot;새로운 React 프로젝트 만들기&quot; href=&quot;https://react.dev/learn/start-a-new-react-project&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Start a New React Project&lt;/a&gt; 라는 메뉴에 들어가면 React 프로젝트를 처음 만드는 공식적인 방법이 나옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;프로덕트 수준의 React 프레임워크를 쓰자.&lt;br /&gt;&amp;nbsp; 1. Next.js&lt;br /&gt;&amp;nbsp; 2. Remix&lt;br /&gt;&amp;nbsp; 3. Gatsby&lt;br /&gt;&amp;nbsp; 4. Expo(for native apps)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;끝입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: right;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666; text-align: start;&quot;&gt;이와중에 App 개발에서도 React-native가 아닌 expo를 추천하고 있는 게 함정&lt;span style=&quot;color: #666666; text-align: start;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 &lt;b&gt;충격적인건 create-react-app의 사용이 나오지 않는다&lt;/b&gt;는 것이죠.&amp;nbsp; 검색 등 아무리 사이트를 뒤져도 create-react-app은 눈을 씻고 찾아도 나오지 않습니다. &lt;b&gt;이것은 입문자에게 &lt;a href=&quot;https://ko.legacy.reactjs.org/docs/create-a-new-react-app.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;맨 첫 꼭지로 Create React App을 추천했던 과거 공식문서&lt;/a&gt;와 비교하면 명확합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;929&quot; data-origin-height=&quot;747&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMj5g8/btsn12tiFXW/RpyKatyOtnF1R7lPV9Vpo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMj5g8/btsn12tiFXW/RpyKatyOtnF1R7lPV9Vpo0/img.png&quot; data-alt=&quot;create-react-app을 가장 먼저 추천하던 과거의 공식문서&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMj5g8/btsn12tiFXW/RpyKatyOtnF1R7lPV9Vpo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMj5g8%2Fbtsn12tiFXW%2FRpyKatyOtnF1R7lPV9Vpo0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;929&quot; height=&quot;747&quot; data-origin-width=&quot;929&quot; data-origin-height=&quot;747&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;create-react-app을 가장 먼저 추천하던 과거의 공식문서&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 그런걸까요? 공식문서의 해당 내용 바로 아래에 &lt;a title=&quot;Deep Dive 원문보기&quot; href=&quot;https://react.dev/learn/start-a-new-react-project#can-i-use-react-without-a-framework&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Deep Dive&lt;/a&gt;라는 꼭지에서 힌트를 찾을 수 있었습니다. (&lt;a href=&quot;https://react.dev/learn/start-a-new-react-project#can-i-use-react-without-a-framework&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;영어 원문보기&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;DEEP DIVE&lt;/b&gt;&lt;br /&gt;&lt;b&gt;프레임워크 없이 React를 사용할 순 없나요?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;프레임워크 없이도 React를 사용할 수 있습니다. 페이지의 일부에 React를 사용하는 방식입니다. 그러나 React로 완전히 새로운 앱이나 사이트를 구축하는 경우 프레임워크를 사용하는 것이 좋습니다. 이유는 다음과 같습니다. 처음에는 라우팅이나 데이터 가져오기가 필요하지 않더라도 일부 라이브러리를 추가하고 싶을 것입니다. JavaScript 번들이 모든 새로운 기능과 함께 커짐에 따라 모든 경로에 대한 코드를 개별적으로 분할하는 방법을 파악해야 할 수 있습니다. 데이터 fetch가 더 복잡해지면 앱이 매우 느리게 느껴지도록 만드는 서버-클라이언트 네트워크 워터폴이 발생할 수 있습니다. 사용자들의 네트워크 상태가 좋지 않고 저가형 장치를 사용하는 사용자가 더 많기 때문에 서버에서 또는 빌드 시간 중에 콘텐츠를 일찍 표시하려면 구성 요소에서 HTML을 생성해야 할 수 있습니다. 서버 또는 빌드 중에 일부 코드를 실행하도록 설정을 변경하는 것은 매우 까다로울 수 있습니다.&lt;br /&gt;&lt;br /&gt;이러한 문제는 React에만 국한되지 않습니다. 이것이 Svelte에 SvelteKit이 있고 Vue에 Nuxt가 있는 이유입니다. 이러한 문제를 직접 해결하려면 번들러를 라우터 및 데이터 가져오기 라이브러리와 통합해야 합니다. 초기 설정을 작동시키는 것은 어렵지 않지만 시간이 지남에 따라 앱이 커져도 빠르게 로드되는 앱을 만드는 데는 많은 미묘함이 있습니다. 최소한의 앱 코드를 전송하고 싶지만 페이지에 필요한 모든 데이터와 병렬로 단일 클라이언트-서버 왕복으로 전송해야 합니다. 점진적 향상을 지원하기 위해 JavaScript 코드가 실행되기 전에 페이지가 상호 작용하기를 원할 것입니다. 어디에서나 호스팅 할 수 있고 JavaScript가 비활성화된 상태에서도 계속 작동할 수 있는 마케팅 페이지에 대한 완전히 정적 HTML 파일의 폴더를 생성할 수 있습니다. 이러한 기능을 직접 구축하려면 실질적인 작업이 필요합니다.&lt;br /&gt;&lt;br /&gt;위 React 프레임워크들은 추가 작업 없이 기본적으로 이와 같은 문제를 해결합니다. 이를 통해 매우 간결하게 시작한 다음 필요에 따라 앱을 확장할 수 있습니다. 각 React 프레임워크에는 커뮤니티가 있으므로 질문에 대한 답변을 찾고 툴을 업그레이드하는 것이 더 쉽습니다. 또한 프레임워크는 코드에 구조를 부여하여 당신과 다른 사람들이 서로 다른 프로젝트 간에 컨텍스트와 기술을 유지하도록 돕습니다. 만약 이런 프레임워크를 사용하지 않고 커스텀 셋업을 사용한다면 미지원 종속성에 걸리기 쉬워지며, 결국 업그레이드를 할 수 없고 커뮤니티의 지원도 받을 수 없는 &quot;나만의 프레임워크&quot;를 마주하게 될 것입니다.(그리고 이런 것들은 과거의 유사품들과 비슷하게 더욱 범용적으로 사용할 수 없게 될 것입니다)&lt;br /&gt;&lt;br /&gt;여전히 확신이 서지 않거나 앱에 이러한 프레임워크에서 제대로 제공되지 않는 비정상적인 제약이 있고 고유한 사용자 지정 설정을 롤링하고 싶다면 우리는 당신을 막을 수 없습니다. npm에서 react 및 react-dom을 가져오고, Vite 또는 Parcel과 같은 번들러로 사용자 정의 빌드 프로세스를 설정하고, 라우팅, 정적 생성 또는 서버 측 렌더링 등에 필요한 다른 도구를 추가하십시오.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;(의역이 섞여있습니다. 자세한 내용은 원문을 확인해주세요.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3줄 요약하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 요즘은 Server Side Rendering이 대세인데,&lt;b&gt; SSR 어려우니 그냥 프레임워크를 따라라&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;b&gt;SSR을 위한 여러 문제들과 커뮤니티, 코드의 일관성을 프레임워크가 보장해 주는데,&lt;/b&gt; 만약 네 스스로 구축한다면 그런 장점은 다 사라지고, &quot;나만의 프레임워크&quot;가 될 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;b&gt;그래도 네 스스로 구축하고 싶다면 말리진 않을게&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아주 쉽게 말하면 스스로 할 생각 말고&lt;b&gt; 그냥 프레임워크 써서 만드는 것을 추천하는 것&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 create-react-app도 생각해 보면 방향성 없이 커스텀하고 자유분방하게 만들 React에 대해 일종의 가이드라인을 제시하여 초기 셋업을 해주는 역할이었을 텐데, 요즘은 이것 조차도 불필요한 과정으로 이해되는 모양입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애초부터 프레임워크였던 Angular나 Vue.js에 비해, 라이브러리임을 강조했던 React는 점점 프레임워크로의 사용을 권하는 것을 보면 개발에 요즘의 트렌드를 보여주는 것 같습니다. (심지어는 Native App에서조차 자기네 라이브러리가 아닌 Expo 프레임워크 사용을 권하고 있죠ㅎㅎ.. 우리 팀 어떻게 하지... )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;개발자의 자율성보다는 프레임워크의 규칙과 엄밀함을 권하는 것이 최근의 트렌드&lt;/b&gt;같습니다. 저도 수혜를 입고 있는 TypeScript의 유행과도 맥이 닿아 보입니다.(TypeScript 잘 쓰고 있습니다. 감사합니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토이 프로젝트는 Next.js를 사용해봐야 하나 고민이 되네요. 이참에 Next.js를 공부해 보는 것도 좋을 것 같습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;번역 및 내용에 대해 이견이 있으시거나 의견이 있으신 분은 댓글을 남겨주세요. 틀린 부분은 수정하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도움이 되셨다면 좋아요 공감❤️과 우측 상단의 구독 부탁드립니다.&lt;/p&gt;</description>
      <category>프론트엔드 개발/React &amp;amp; RN</category>
      <category>create-react-app</category>
      <category>Next.js</category>
      <category>react</category>
      <category>TypeScript</category>
      <category>공식문서</category>
      <category>권장</category>
      <category>라이브러리</category>
      <category>비권장</category>
      <category>프레임워크</category>
      <author>아이톤</author>
      <guid isPermaLink="true">https://one-it.tistory.com/54</guid>
      <comments>https://one-it.tistory.com/entry/create-react-app-%EC%9D%80-%EB%8D%94%EC%9D%B4%EC%83%81-%EA%B6%8C%EC%9E%A5%EB%90%98%EC%A7%80-%EC%95%8A%EB%8A%94-%EB%B0%A9%EC%8B%9D%EC%9D%B8%EA%B0%80#entry54comment</comments>
      <pubDate>Mon, 17 Jul 2023 23:15:46 +0900</pubDate>
    </item>
    <item>
      <title>2023 ONE-IT 티스토리 리부트</title>
      <link>https://one-it.tistory.com/entry/2023-ONE-IT-%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC-%EB%A6%AC%EB%B6%80%ED%8A%B8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;2년 전 쯤에 티스토리가 카카오 로그인을 강제한다고 해서 불만을 품고 다른 블로그 사이트를 알아본 적이 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://one-it.tistory.com/entry/%EC%B9%B4%EC%B9%B4%EC%98%A4-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C%EC%9D%98-%EC%A0%84%ED%99%98%EC%9D%84-%EA%B0%95%EC%A0%9C%ED%95%98%EB%8A%94-%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC&quot;&gt;카카오 계정으로의 전환을 강제하는 티스토리... (tistory.com)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1689595537022&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;카카오 계정으로의 전환을 강제하는 티스토리...&quot; data-og-description=&quot;카카오톡 계정을 강제로 연동시키는 티스토리때문에 너무 많은 불편을 겪고, 스트레스를 받다가 결국에는 카카오계정으로 전환하게 되었다. 마크다운을 지원하지 않는 것부터 시작해 임시저장&quot; data-og-host=&quot;one-it.tistory.com&quot; data-og-source-url=&quot;https://one-it.tistory.com/entry/%EC%B9%B4%EC%B9%B4%EC%98%A4-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C%EC%9D%98-%EC%A0%84%ED%99%98%EC%9D%84-%EA%B0%95%EC%A0%9C%ED%95%98%EB%8A%94-%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC&quot; data-og-url=&quot;https://one-it.tistory.com/entry/%EC%B9%B4%EC%B9%B4%EC%98%A4-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C%EC%9D%98-%EC%A0%84%ED%99%98%EC%9D%84-%EA%B0%95%EC%A0%9C%ED%95%98%EB%8A%94-%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bcYULs/hyTk2DIVP9/SCS4zamjPI2ewnIIT2balk/img.jpg?width=800&amp;amp;height=480&amp;amp;face=0_0_800_480,https://scrap.kakaocdn.net/dn/jyzVh/hyTk7ZmYDn/xHWuvY6UHVtadN834I3uqk/img.jpg?width=800&amp;amp;height=480&amp;amp;face=0_0_800_480,https://scrap.kakaocdn.net/dn/cn20bN/hyTldFfxDF/89cO2As2PWBqvj0OBHkbiK/img.jpg?width=2360&amp;amp;height=1417&amp;amp;face=0_0_2360_1417&quot;&gt;&lt;a href=&quot;https://one-it.tistory.com/entry/%EC%B9%B4%EC%B9%B4%EC%98%A4-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C%EC%9D%98-%EC%A0%84%ED%99%98%EC%9D%84-%EA%B0%95%EC%A0%9C%ED%95%98%EB%8A%94-%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://one-it.tistory.com/entry/%EC%B9%B4%EC%B9%B4%EC%98%A4-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C%EC%9D%98-%EC%A0%84%ED%99%98%EC%9D%84-%EA%B0%95%EC%A0%9C%ED%95%98%EB%8A%94-%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bcYULs/hyTk2DIVP9/SCS4zamjPI2ewnIIT2balk/img.jpg?width=800&amp;amp;height=480&amp;amp;face=0_0_800_480,https://scrap.kakaocdn.net/dn/jyzVh/hyTk7ZmYDn/xHWuvY6UHVtadN834I3uqk/img.jpg?width=800&amp;amp;height=480&amp;amp;face=0_0_800_480,https://scrap.kakaocdn.net/dn/cn20bN/hyTldFfxDF/89cO2As2PWBqvj0OBHkbiK/img.jpg?width=2360&amp;amp;height=1417&amp;amp;face=0_0_2360_1417');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;카카오 계정으로의 전환을 강제하는 티스토리...&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;카카오톡 계정을 강제로 연동시키는 티스토리때문에 너무 많은 불편을 겪고, 스트레스를 받다가 결국에는 카카오계정으로 전환하게 되었다. 마크다운을 지원하지 않는 것부터 시작해 임시저장&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;one-it.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 그냥 블로그를 놔버렸다...ㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블로그를 안 알아본 것은 아닌데, 늘 그렇듯이 배가 아닌 배꼽을 찾아 해매다보면 정작 배가 소홀해지기 마련이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 velog를 가장 유력하게 봤는데, 결정적으로 광고를 달지 못한다는게 고민이었다. 어떻게 받은 구글 애드센스인데 ㅠㅜ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러던 중 일이 바빠지고 이래저래 인생사가 많아지며 블로그는 자연스레 관심 밖으로 밀려났다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러던 중 구글 애드센스에서 인출 최소금액이 되었으니 돈 찾아가라는 알림이 왔고, 그때 이 블로그가 생각났다. 간간히 댓글에 대댓글정도만 달던 블로그였는데 어찌저찌 돈이 되긴 됬구나 싶었다.(그게 최저임금도 안되서 문제지만ㅋㅋ)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;611&quot; data-origin-height=&quot;510&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bf3vXX/btsnZwa5gWR/K2QKyNG1btAVPtXyNKGr50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bf3vXX/btsnZwa5gWR/K2QKyNG1btAVPtXyNKGr50/img.png&quot; data-alt=&quot;노션 고맙다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bf3vXX/btsnZwa5gWR/K2QKyNG1btAVPtXyNKGr50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbf3vXX%2FbtsnZwa5gWR%2FK2QKyNG1btAVPtXyNKGr50%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;611&quot; height=&quot;510&quot; data-origin-width=&quot;611&quot; data-origin-height=&quot;510&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;노션 고맙다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명색이 개발자 블로그인데 노션 글이 1등이라니 뭔가 부끄럽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블로그를 오래 비운 사이 반반택시도 사실상 앱이 완전 바뀌었고(초창기 1등 글이어서 간간히 들어오던 친구초대 마일리지도 이젠 거의 들어오지 않는다) 노션이나 리액트도 많이 바뀌었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 바뀐 세상 물정에 맞게 새롭게 다시 써봐야겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;티스토리는 물론 여전히 구리고, 짜증나고, 뭔가 카카오에서도 손 놓은 느낌이 역력하다. 그럼에도 불구하고 지금까지 쓴 나의 모든 블로그 중에서 가장 성공적인건 티스토리였다.(2등은 이글루스였는데 이것도 망했지...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇지만 기왕 이렇게 된 거 진짜 구미가 확 당기는 서비스가 나타나지 않는 이상 일단 계속 티스토리를 써보기로 했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;i&gt;광고도 달 수 있고 멋진 블로그 서비스야! 내게 와줘!!&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 상황에 따라 언제다시 소홀해질지 모르지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그래도 다시 시작합니다.&lt;/b&gt;&lt;/p&gt;</description>
      <category>리부트</category>
      <category>티스토리</category>
      <author>아이톤</author>
      <guid isPermaLink="true">https://one-it.tistory.com/53</guid>
      <comments>https://one-it.tistory.com/entry/2023-ONE-IT-%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC-%EB%A6%AC%EB%B6%80%ED%8A%B8#entry53comment</comments>
      <pubDate>Mon, 17 Jul 2023 21:18:09 +0900</pubDate>
    </item>
    <item>
      <title>카카오 계정으로의 전환을 강제하는 티스토리...</title>
      <link>https://one-it.tistory.com/entry/%EC%B9%B4%EC%B9%B4%EC%98%A4-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C%EC%9D%98-%EC%A0%84%ED%99%98%EC%9D%84-%EA%B0%95%EC%A0%9C%ED%95%98%EB%8A%94-%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC</link>
      <description>&lt;p&gt;카카오톡 계정을 강제로 연동시키는 티스토리때문에 너무 많은 불편을 겪고, 스트레스를 받다가 결국에는 카카오계정으로 전환하게 되었다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;EE4CF233-23EC-4095-B69B-AD704016FF10.jpeg&quot; data-origin-width=&quot;2360&quot; data-origin-height=&quot;1417&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Qet1Y/btq4s2mqrlE/ku7rlCUSKWi4Kmu62Ub2N0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Qet1Y/btq4s2mqrlE/ku7rlCUSKWi4Kmu62Ub2N0/img.jpg&quot; data-alt=&quot;굴욕적인 계정 전환&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Qet1Y/btq4s2mqrlE/ku7rlCUSKWi4Kmu62Ub2N0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQet1Y%2Fbtq4s2mqrlE%2Fku7rlCUSKWi4Kmu62Ub2N0%2Fimg.jpg&quot; data-filename=&quot;EE4CF233-23EC-4095-B69B-AD704016FF10.jpeg&quot; data-origin-width=&quot;2360&quot; data-origin-height=&quot;1417&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;굴욕적인 계정 전환&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;마크다운을 지원하지 않는 것부터 시작해 임시저장, 광고, 통계 등 여러 불편을 겪던 티스토리였는데, 이렇게 카카오 실명계정과의 연동을 사실상 강제하는 것을 겪으니 정말 블로그를 다른 곳으로 옮겨야겠다는 생각이 많이 든다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;조만간 블로그를 옮기고 옮긴 후기 등을 업데이트해서 올려야겠다.&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이야기</category>
      <author>아이톤</author>
      <guid isPermaLink="true">https://one-it.tistory.com/52</guid>
      <comments>https://one-it.tistory.com/entry/%EC%B9%B4%EC%B9%B4%EC%98%A4-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C%EC%9D%98-%EC%A0%84%ED%99%98%EC%9D%84-%EA%B0%95%EC%A0%9C%ED%95%98%EB%8A%94-%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC#entry52comment</comments>
      <pubDate>Sun, 9 May 2021 19:34:48 +0900</pubDate>
    </item>
    <item>
      <title>Promise 정리: async/await 사용법 &amp;amp; then과의 차이</title>
      <link>https://one-it.tistory.com/entry/Promise-%EC%A0%95%EB%A6%AC-asyncawait-%EC%82%AC%EC%9A%A9%EB%B2%95-then%EA%B3%BC%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
      <description>&lt;p&gt;서비스 개발을 하다보면 비동기적으로 개발해야 할 일이 많습니다.&amp;nbsp;JavaScript에서는 과거 callback 함수를 통해 비동기를 구현하곤 했으나 요즘에는 Promise 객체를 반환하게 하여 async와 await로 작업이 완료되면 다음 로직이 진행되게끔 지연시키는 방식을 통해 비동기를 구현하곤 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;최근 회사에서 앱을 개발하면서 한번 사용하는 방법을 간단하게 정리해봤습니다. (Promise 객체 자체에 대해서는 &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Using_promises&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Using_promises&lt;/a&gt;&amp;nbsp;이 링크를 참고하세요.)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p&gt;Promise 객체를 반환하게끔 작성한 함수를 호출할 땐 함수명 앞에 &lt;code&gt;await&lt;/code&gt; 키워드를 붙이고 호출하면 해당 작업이 완료되고 나서야 이후 코드가 진행됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;의사코드로 간단히 살펴봅시다.&lt;/p&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;// &quot;샘플함수&quot;는 비동기 작업 함수를 호출하여 콘솔에 기록하는 함수

샘플함수 {
  const 작업결과 = 비동기 작업 함수 실행 // 시간이 걸림
  console.log(작업결과)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위 작업을 비동기처리 없이 구현하면 &lt;code&gt;console.log(작업결과)&lt;/code&gt;가 &lt;code&gt;undefined&lt;/code&gt;를 출력합니다.&lt;/p&gt;
&lt;p&gt;즉, 비동기 작업을 수행하는 함수가 결과값을 반환해 '작업결과'에 할당을 하기도 전에 console.log 함수가 실행되었기 때문이죠.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이렇게 Promise를 반환하는 함수 반환값을 사용하기 까지 코드를 지연시키기 위해 async, await를 사용합니다.&lt;/p&gt;
&lt;h2&gt;async와 await를 활용한 방식&lt;/h2&gt;
&lt;p&gt;위 의사코드를 await와 async 키워드와 함께 실제 코드로 변경해봅시다.&lt;/p&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;const sampleFunc = async () =&amp;gt; {
    const result = await asyncFunc() // asyncFunc 함수는 Promise 객체를 반환한다
    console.log(result)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Promise 객체를 반환하는 함수 asyncFunc 앞에 await를 붙이고, 이를 포함하는 함수 앞에 async를 붙여줍니다. 여기서는 sampleFunc에 할당하는 익명함수가 되겠습니다. &lt;code&gt;await&lt;/code&gt; 키워드를 쓰려면 반드시 &lt;code&gt;async&lt;/code&gt; 키워드로 선언된 함수 내부여야 합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이렇게 하면 result가 제대로 출력됩니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;asyncFunc함수의 실행결과가 반환되어 result에 할당되기 전까지,&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;await 키워드가 console.log 함수의 실행을 지연시켰음을 알 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;async/await에서 예외처리&lt;/h3&gt;
&lt;p&gt;위 코드에서 예외처리는 다음과 같이 할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const sampleFunc = async () =&amp;gt; {
    try {
        const result = await asyncFunc() // asyncFunc 함수는 Promise 객체를 반환한다
        console.log(result)
    } catch (err) {
        console.log(err)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;만약 asyncFunc에서 reject를 뿜어냈을 경우 catch에서 해당 내용을 잡아 콘솔에 찍어냅니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2&gt;(참고) then을 활용한 방식&lt;/h2&gt;
&lt;p&gt;지금까지 async, await를 이용한 방식을 보셨는데요, 사실 이런 방식 이전에 &lt;code&gt;then&lt;/code&gt;을 사용하는 방식이 있었습니다. 위의 코드를 &lt;code&gt;then&lt;/code&gt;으로 구현하면 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const sampleFunc = () =&amp;gt; {
    asyncFunc() // asyncFunc 함수는 Promise 객체를 반환한다
          .then(result =&amp;gt; console.log(result))
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;얼핏 보면 코드가 깔끔해보이지만, 사실 depth가 한 단계 더 들어가면서 콜백지옥의 전초처럼 보이기도 한다.&lt;/p&gt;
&lt;p&gt;지금은 매우 간단한 함수여서 그리 복잡해 보이지 않지만, 실제 코드를 다룰 때&amp;nbsp;&lt;code&gt;then&lt;/code&gt;을 활용한 방식은 가독성이 떨어질 수 있습니다. 콜백지옥에서 벗어나기 위해 Promise가 도입되었는데, 콜백지옥같은 들여쓰기 지옥(Tab Hell)을 맛보게 될 수도 있습니다.&lt;/p&gt;
&lt;h3&gt;then 예외처리&lt;/h3&gt;
&lt;p&gt;then을 활용한 방식에서의 예외처리는 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;const sampleFunc = () =&amp;gt; {
    asyncFunc() // asyncFunc 함수는 Promise 객체를 반환한다
        .then(result =&amp;gt; console.log(result))
		.catch(err =&amp;gt; console.log(err))

// 이런 식으로도 가능하다.
const sampleFunc2 = () =&amp;gt; {
    asyncFunc() // asyncFunc 함수는 Promise 객체를 반환한다
		.then(
			result =&amp;gt; console.log(result),
			err =&amp;gt; console.log(err)
        )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이미 알았겠지만 예외처리 과정에서도 await, async를 사용하는 것이 가독성에서도 좋고, 이해하기에도 편합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;그럼 then은 쓰지 말아야 하는 걸까요? 그렇진 않습니다. then은 이러한 비동기가 연속적으로 일어나는 상황에서 각 Promise객체마다 다른 로직으로, 체이닝을 구성하려고 할때 더 유용하게 사용할 수 있습니다. 여기에 관련해선&amp;nbsp;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise/then#체이닝&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Promise.prototype.then()#체이닝&lt;/a&gt;을 참고해주세요.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p&gt;async와 await를 활용한 비동기 구현에 대해 알아봤습니다. 지금은 Promise 객체 하나를 다루는 비동기를 구성했는데, 만약 여러 Promise 객체를 병렬적으로 처리하려고 한다면 어떻게 해야 할까요? 가령 [ Promise 객체, Promise 객체, ... ]라면 각각의 Promise 객체들이 모두 결과를 반환한 뒤에 이후 로직을 처리해야 할 일이 있습니다. 이 때는 Promise.all 을 활용하여 해결할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;다음에는 Promise.all에 대해 알아보겠습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;이 글이 도움이 되셨다면 바로 아래의 좋아요(공감)❤️ 부탁드려요.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;내용 중 오류가 있거나 보충해주실 내용이 있으면 댓글을 통해 알려주시면 바로 반영하겠습니다. 감사합니다.&lt;/p&gt;</description>
      <category>프론트엔드 개발/JS &amp;amp; TS</category>
      <category>async</category>
      <category>Await</category>
      <category>Javascript</category>
      <category>PROMISE</category>
      <category>promise.all</category>
      <category>then</category>
      <category>try~catch</category>
      <category>비동기</category>
      <category>예외처리</category>
      <author>아이톤</author>
      <guid isPermaLink="true">https://one-it.tistory.com/51</guid>
      <comments>https://one-it.tistory.com/entry/Promise-%EC%A0%95%EB%A6%AC-asyncawait-%EC%82%AC%EC%9A%A9%EB%B2%95-then%EA%B3%BC%EC%9D%98-%EC%B0%A8%EC%9D%B4#entry51comment</comments>
      <pubDate>Sun, 11 Apr 2021 18:31:07 +0900</pubDate>
    </item>
  </channel>
</rss>