<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ant-now.log</title>
        <link>https://velog.io/</link>
        <description>아침에는 공부, 저녁에는 개발하는 개발자입니다.</description>
        <lastBuildDate>Sun, 24 Jan 2021 14:59:38 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>ant-now.log</title>
            <url>https://images.velog.io/images/ant-now/profile/7daecc1e-2e9d-4b38-bfd8-ce81e43e05a7/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ant-now.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ant-now" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Vscode SSH 로 AWS 바로 접속하기]]></title>
            <link>https://velog.io/@ant-now/Vscode-SSH-%EB%A1%9C-AWS-%EB%B0%94%EB%A1%9C-%EC%A0%91%EC%86%8D%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ant-now/Vscode-SSH-%EB%A1%9C-AWS-%EB%B0%94%EB%A1%9C-%EC%A0%91%EC%86%8D%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 24 Jan 2021 14:59:38 GMT</pubDate>
            <description><![CDATA[<p><a href="https://dev.to/dre4success/ssh-to-an-ec2-instance-from-vs-code-2707">SSH to an EC2 instance from VS Code</a></p>
<h2 id="1-vsc에서-ssh-실행">1. VSC에서 SSH 실행</h2>
<p>단축키 shift+cmd+P, &quot;SSH&quot;</p>
<blockquote>
<p>Remote-SSH: Connect to Host...</p>
</blockquote>
<p>를 누른다.</p>
<p><img src="https://i.imgur.com/SSEldQ6.png" alt="https://i.imgur.com/SSEldQ6.png"></p>
<h2 id="2-ssh-configure-설정해주기">2. SSH Configure 설정해주기</h2>
<p>AWS 에서 만든 인스턴스의 경우 pem 키가 있어야 접속 가능하기 때문에 <code>.ssh/config</code> 에서 따로 설정을 해줘야 한다.</p>
<p><img src="https://i.imgur.com/3cSo5bJ.png" alt="https://i.imgur.com/3cSo5bJ.png"></p>
<p>메뉴에서 Configure SSH Hosts... 를 누르면 설정파일 경로가 다음과 같이 나온다.</p>
<p><img src="https://i.imgur.com/QGsdh9T.png" alt="https://i.imgur.com/QGsdh9T.png"></p>
<p>이 중 맨 첫번째 <code>/Users/{유저명}/.ssh.config</code> 를 눌러준다.</p>
<p><img src="https://i.imgur.com/8bmbCyf.png" alt="https://i.imgur.com/8bmbCyf.png"></p>
<p>기존 ssh 를 통해 연결한 것이 있다면 이런식으로 각 서버의 설정이 나올 것이다.</p>
<p>aws 연결에 필요한 것은 Host, HostName, User, IdentityFile 이다.</p>
<p>다음과 같이 써준다.</p>
<pre><code class="language-bash">Host personal // 원하는 이름 아무거나
  HostName {퍼블릭DNS주소.ap-northeast-2.compute.amazonaws.com}
  User ec2-user // 서버 생성할 때 썼던 유저이름
  IdentityFile {~/pem/key.pem} // pem 키 위치</code></pre>
<ul>
<li>Host 에는 ssh 접속시 표시될 이름이다. 원하는 것으로 아무거나 해도 된다.</li>
<li>HostName 은 AWS 에서 제공해준 퍼블릭DNS 주소를 쓴다.</li>
<li>User 에는 <code>ec2-user</code> 처럼 AWS 에서 처음에 정해준 서버의 유저명을 쓴다.</li>
<li>IdentityFile 에는 pem 키를 저장한 경로와 파일명을 적어준다.</li>
</ul>
<h2 id="3-접속하기">3. 접속하기</h2>
<p>다시 ssh 를 실행하면 아까 HostName 으로 입력했던 서버가 나올 것이다.</p>
<p>HostName 으로 <code>personal</code> 을 입력했었다.</p>
<p><img src="https://i.imgur.com/vlJuBwD.png" alt="https://i.imgur.com/vlJuBwD.png"></p>
<p>누르면 성공적으로 접속 완료!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS 서버에 AMI Nginx 설치]]></title>
            <link>https://velog.io/@ant-now/AWS-%EC%84%9C%EB%B2%84%EC%97%90-Nginx-%EC%84%A4%EC%B9%98</link>
            <guid>https://velog.io/@ant-now/AWS-%EC%84%9C%EB%B2%84%EC%97%90-Nginx-%EC%84%A4%EC%B9%98</guid>
            <pubDate>Sun, 24 Jan 2021 14:55:24 GMT</pubDate>
            <description><![CDATA[<h3 id="1-설치">1. 설치</h3>
<hr>
<p><code>sudo yum install nginx</code> 로 안됨. 왜냐면 아마존 리눅스에서 사용하는 엔진엑스가 따로 있기 때문</p>
<p><code>sudo amazon-linux-extras install nginx1</code> 로 설치하자.</p>
<p><a href="https://aws.amazon.com/ko/amazon-linux-2/faqs/#Amazon_Linux_Extras">Amazon Linux 2 FAQs</a></p>
<ul>
<li>성공적으로 설치되면 nginx 폴더로 가서 목록을 보자.</li>
</ul>
<p><img src="https://i.imgur.com/PMzZNCH.png" alt="https://i.imgur.com/PMzZNCH.png"></p>
<h3 id="2-시작">2. 시작</h3>
<hr>
<p><code>sudo service nginx start</code></p>
<p>엔진엑스 서버를 시작하는 순간 로그가 쌓인다.</p>
<p><code>sudo tail -f /var/log/nginx/access.log</code> 로 확인할 수 있다.</p>
<h3 id="3-aws-콘솔에서-인바운드-규칙-추가">3. AWS 콘솔에서 인바운드 규칙 추가</h3>
<hr>
<p>아직 브라우저를 통해 서버로 접속할 수 없다. 왜냐면 인바운드 규칙이 막혀있기 때문.</p>
<p><img src="https://i.imgur.com/5mD1Xsl.png" alt="https://i.imgur.com/5mD1Xsl.png"></p>
<p>최초는 22번 포트만 열려있을 것이다. 여기서 http 통신으로 80 포트로 접속하기 위해서는 AWS EC2 &gt; 보안그룹 메뉴로 들어가 80 포트를 열어줘야 한다.</p>
<p><a href="https://medium.com/@taeyeolkim/aws-ec2%EC%97%90-%EC%9B%B9%EC%84%9C%EB%B2%84-nginx-%EC%84%A4%EC%B9%98%ED%95%98%EA%B3%A0-%EA%B5%AC%EB%8F%99%ED%95%98%EA%B8%B0-a46a6e9484a8">AWS EC2에 웹서버(Nginx )설치하고 구동하기</a></p>
<p>위에 친절하게 설명이 되어있으니 따라해보자.</p>
<p><img src="https://i.imgur.com/hfGvhC5.png" alt="https://i.imgur.com/hfGvhC5.png"></p>
<p>해당 인스턴스의 보안그룹 편집을 누르면 설정창이 보인다.</p>
<p>여기서 &quot;인바운드 규칙 편집&quot;을 눌러 HTTP 80 포트를 열어준다.</p>
<p><img src="https://i.imgur.com/Tb5gYIQ.png" alt="https://i.imgur.com/Tb5gYIQ.png"></p>
<p>이 때 소스를 0.0.0.0/0 으로 하면 모든 사용자가 접근할 수 있고, &quot;내 IP&quot; 로 하면 내 PC 에서만 접근 가능하다.</p>
<p>보안을 위해 SSH, HTTP 둘 다 내 IP 로 하는 것이 좋다.</p>
<h3 id="4-다시-퍼블릭-ip-로-접속">4. 다시 퍼블릭 IP 로 접속</h3>
<hr>
<p>내 인스턴스 대시보드로 다시 와서 퍼블릭 IPv4 주소를 누르면 성공적으로 접속이 됨을 확인할 수 있다.</p>
<p><img src="https://i.imgur.com/su1nDF1.png" alt="https://i.imgur.com/su1nDF1.png"></p>
<p><img src="https://i.imgur.com/5lEMgYi.png" alt="https://i.imgur.com/5lEMgYi.png"></p>
<p>완료! 이제 웹서버를 마음껏 세팅해보고 띄워보자!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React Native with TS] 타입스크립트로 리액트네이티브 boilder plate 만들기 (2)스택네비게이션 만들기 (React Navigation 5.0+)]]></title>
            <link>https://velog.io/@ant-now/React-Native-with-TS-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A1%9C-%EB%A6%AC%EC%95%A1%ED%8A%B8%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C-boilder-plate-%EB%A7%8C%EB%93%A4%EA%B8%B0-2%EC%8A%A4%ED%83%9D%EB%84%A4%EB%B9%84%EA%B2%8C%EC%9D%B4%EC%85%98-%EB%A7%8C%EB%93%A4%EA%B8%B0-React-Navigation-5.0</link>
            <guid>https://velog.io/@ant-now/React-Native-with-TS-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A1%9C-%EB%A6%AC%EC%95%A1%ED%8A%B8%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C-boilder-plate-%EB%A7%8C%EB%93%A4%EA%B8%B0-2%EC%8A%A4%ED%83%9D%EB%84%A4%EB%B9%84%EA%B2%8C%EC%9D%B4%EC%85%98-%EB%A7%8C%EB%93%A4%EA%B8%B0-React-Navigation-5.0</guid>
            <pubDate>Mon, 18 Jan 2021 12:28:56 GMT</pubDate>
            <description><![CDATA[<p>이 글은 <a href="https://levelup.gitconnected.com/react-native-react-navigation-b27ab272e09b">https://levelup.gitconnected.com/react-native-react-navigation-b27ab272e09b</a> 을 보고 작성되었습니다.</p>
<blockquote>
<p>git 저장소에서 전체 코드 보기:
<a href="https://github.com/uu29/typescript-stacknavigation-boilerplate">https://github.com/uu29/typescript-stacknavigation-boilerplate</a></p>
</blockquote>
<p>여기서는 타입스크립트를 이용하여 아주 기본적인 리액트네이티브 스택네비게이션을 만들어보도록 한다.</p>
<p>시작하기에 앞서 React Navigation 은 버전마다 구현 방식이 아주 다른데 이 글은 5.0 이상 버전을 사용하였다.</p>
<p>먼저 결과 화면은 아래와 같다.</p>
<img src="https://i.imgur.com/iq5iwOn.gif" alt="Jan-18-2021 20-25-28" style="zoom: 67%;" />

<p>우리가 만들 스크린은 딱 두개다. Main, Details 스크린.</p>
<p>화면 하단에 More 버튼이 있고 버튼을 누르면 스택이 쌓이면서 Details 화면으로 넘어간다. 그리고 Details 에서 &quot;&lt;&quot; 버튼을 눌러 메인으로 돌아올 수 있다.</p>
<h4 id="준비단계">[준비단계]</h4>
<p><strong>(1) 의존성 설치</strong></p>
<p>​    <code>yarn add react-native-gesture-handler react-navigation react-native-safe-area-context react-native-screens @react-native-community/masked-view @react-navigation/native @react-navigation/stack</code></p>
<p><strong>(2) RN 개발 의존성과 연결해주기 (RN 0.59 이하인 경우만)</strong></p>
<p>​    <code>react-native link react-native-gesture-handler</code></p>
<p><strong>(3) 메뉴 구조</strong></p>
<img src="https://i.imgur.com/OByF3zJ.png" alt="메뉴구조" style="zoom:50%;" />

<p>​    메뉴 구조는 이렇다. <code>/src</code> 안에 앞으로 만들 모든 컴포넌트, 스크린, 스토어, 네비게이터가 들어간다.</p>
<p>​    <code>/src</code> 안에 먼저 네비게이터들이 들어갈 <code>navigators</code> 폴더와 스크린들이 들어갈 <code>screens</code> 폴더를 만들어주자. 그리고 각각 <code>navigators/HomeStackNavigators/index.tsx</code> , <code>screens/DetailsScreen/index.tsx</code> , <code>screens/MainScreen/index.tsx</code> 파일을 경로에 맞게 만들어준다.</p>
<h4 id="구현하기">[구현하기]</h4>
<p>여기서부터는 먼저 완성된 코드를 주석과 함께 보여준 뒤, 각 코드를 쪼개서 설명해줄 것입니다. 급하면 주석과 전체 코드만 보시면 됩니다. 중요한 것은 무슨 뜻인지 모르겠어도 그냥 따라하는 것입니다.</p>
<h4 id="1-homestacknavigationindextsx">1. <code>HomeStackNavigation/index.tsx</code></h4>
<ul>
<li>전체 코드</li>
</ul>
<pre><code class="language-tsx">import React from &#39;react&#39;;
// 필요한 모듈과 스크린 tsx 를 불러온다.
import {createStackNavigator} from &#39;@react-navigation/stack&#39;;
import MainScreen from &#39;../../screens/MainScreen&#39;; // 메인스크린
import DetailsScreen, {DetailsParams} from &#39;../../screens/DetailsScreen&#39;; // 디테일스크린(주가정보)

// Home Screen 에서 필요한 스택은 2개 - 메인, 디테일

// 1. 필요한 스크린에 대해 enum 타입을 정의한다. (리듀서에서 액션타입을 지정해주는 것 처럼)
export enum HomeScreens {
  Main = &#39;Main&#39;,
  Details = &#39;Details&#39;,
}

// 2. 각 스크린 마다 필요한 파라미터 타입 정의
export type HomeStackParamList = {
  Main: undefined; // Main 스크린은 아무런 파라미터도 필요 없음
  Details: DetailsParams; // Details 스크린은 DetailsParams 라는 지정 타입의 파라미터가 필요함 =&gt; DetailsScreen 에서 지정할 것임.
};

// 3. 방금 만든 타입을 createStackNavigator 메소드 앞에 지정해주서 HomeStack 네비게이터 객체를 만들어줌.
const HomeStack = createStackNavigator&lt;HomeStackParamList&gt;();
const HomeStackNavigator: React.FunctionComponent = () =&gt; {
  return (
    &lt;HomeStack.Navigator&gt;
      &lt;HomeStack.Screen
        name={HomeScreens.Main} // 처음에 enum 으로 지정했던 HomeScreens 에서 맞는 컴포넌트명을 가져온다.
        component={MainScreen} // 실제 보여주게 될 컴포넌트
      /&gt;
      &lt;HomeStack.Screen name={HomeScreens.Details} component={DetailsScreen} /&gt;
    &lt;/HomeStack.Navigator&gt;
  );
};
export default HomeStackNavigator;</code></pre>
<ul>
<li>설명</li>
</ul>
<p><strong>(1) 라우트를 enum 으로 정의하기</strong></p>
<p>​    가장 먼저 <code>HomeStackNavigator/index.tsx</code> 에서 필요한 모든 스크린에 대해 enum 타입으로 정의한다.</p>
<p>​    enum 에 관한 자세한 글은 <a href="https://medium.com/@seungha_kim_IT/typescript-enum%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-3b3ccd8e5552">https://medium.com/@seungha_kim_IT/typescript-enum%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-3b3ccd8e5552</a> 을 참고바란다.</p>
<p>​    무슨 뜻인지 잘 모르겠어도 그냥 따라하자. 라우팅에 필요한 스크린의 이름을 미리 지정하는 것인데, 리덕스에서 액션 타입을 지정하는 것과 비슷하다고 보면 된다.</p>
<pre><code class="language-tsx">// 1. 필요한 스크린에 대해 enum 타입을 정의한다. (리듀서에서 액션타입을 지정해주는 것 처럼)
export enum HomeScreens {
  Main = &#39;Main&#39;,
  Details = &#39;Details&#39;,
}</code></pre>
<p><strong>(2) 각 스크린마다 필요한 파라미터 정의</strong></p>
<p>​    각 스크린마다 props 를 가지는 것이 있고 필요없는 것이 있다. 이 때 스택의 파라미터 리스트라는 타입을 미리 export 해야하는데 여기서 지정해놓은 타입은 나중에 스크린에서 <code>StackNavigationProp</code> 로 쓰이게 된다.</p>
<p>​    내가 만들 앱은 Home 화면은 아무 props 도 필요없고 Details 화면은 symbol 이라는 string 값을 넘길 예정이다. Details 에 넘길 props 에 대한 자세한 타입은 Details 스크린에서 <code>DetailsParams</code> 라는 타입으로 지정해줄 것이기 때문에 여기서는 앞으로 만들게 될 타입만 명시해준다.</p>
<p>​    해당 스크린에 따로 파라미터가 필요없다면 <code>undefined</code> 라고 써주면 된다.</p>
<pre><code class="language-tsx">// 2. 각 스크린 마다 필요한 파라미터 타입 정의
export type HomeStackParamList = {
  Main: undefined; // Main 스크린은 아무런 파라미터도 필요 없음
  Details: DetailsParams; // Details 스크린은 DetailsParams 라는 지정 타입의 파라미터가 필요함 =&gt; DetailsScreen 에서 지정할 것임.
};</code></pre>
<p><strong>(3) Stack Navigator 객체 만들기</strong></p>
<p>​    <code>createStackNavigator</code> 메소드로 스택네비게이션 객체를 만들어준다. 네비게이터를 만들 때 타입을 지정해줘야 하는데 바로 위에서 만든 <code>HomeStackParamList</code> 타입을 지정해준다.</p>
<p>​    그 다음에는 React.FunctionComponent 로 tsx 형식으로 리턴할 것이다.</p>
<p>​    구조를 잘 보면 이렇게 되어있다.</p>
<blockquote>
<p>​    &lt;네비게이터&gt;</p>
<p>​            &lt;스크린 네임={스크린 이름} 컴포넌트={들어갈 컴포넌트}/&gt;</p>
<p>​            &lt;스크린 네임={스크린 이름} 컴포넌트={들어갈 컴포넌트}/&gt;    </p>
<p>​    &lt;/네비게이터&gt;</p>
</blockquote>
<p>​    여기서 스크린 네임에 해당하는 부분에 enum 으로 지정한 스크린 이름을 써주면 된다. 컴포넌트에는 앞으로 만들게 될 스크린 컴포넌트를 넣어준다.</p>
<pre><code class="language-tsx">// 3. 방금 만든 타입을 createStackNavigator 메소드 앞에 지정해주서 HomeStack 네비게이터 객체를 만들어줌.
const HomeStack = createStackNavigator&lt;HomeStackParamList&gt;();
const HomeStackNavigator: React.FunctionComponent = () =&gt; {
  return (
    &lt;HomeStack.Navigator&gt;
      &lt;HomeStack.Screen
        name={HomeScreens.Main} // 처음에 enum 으로 지정했던 HomeScreens 에서 맞는 컴포넌트명을 가져온다.
        component={MainScreen} // 실제 보여주게 될 컴포넌트
      /&gt;
      &lt;HomeStack.Screen name={HomeScreens.Details} component={DetailsScreen} /&gt;
    &lt;/HomeStack.Navigator&gt;
  );
};
export default HomeStackNavigator;</code></pre>
<h4 id="2-mainindextsx">2. <code>Main/index.tsx</code></h4>
<ul>
<li>전체 코드</li>
</ul>
<pre><code class="language-tsx">import React, {useState} from &#39;react&#39;;
import {SafeAreaView, StyleSheet, Text, View, Button} from &#39;react-native&#39;;
import {StackNavigationProp} from &#39;@react-navigation/stack&#39;;
// 아까 HomeStackNavigator 에서 export 해줬던 타입들을 가지고 온다.
import {
  HomeScreens,
  HomeStackParamList,
} from &#39;../../navigators/HomeStackNavigators&#39;;

// MainScreen 에 필요한 파라미터들을 StackNavigationProp 으로 타입 명시해준다.
type MainScreenNavigationProps = StackNavigationProp&lt;
  HomeStackParamList, // navigators/HomeStackNavigators/index.tsx 에서 지정했던 HomeStackParamList
  HomeScreens.Main // enum 으로 지정했던 타입 중 Main 에 해당하는 부분
&gt;;

// MainScreenProps 에 대한 인터페이스 지정
// 인터페이스: 객체의 타입을 정의할 수 있게 하는 것
interface MainScreenProps {
  navigation: MainScreenNavigationProps; // 네비게이션 속서에 대한 타입으로 방금 지정해주었던 MainScreenNavigationProps 을 지정
}

const styles = StyleSheet.create({
  btnNextContainer: {
    alignSelf: &#39;flex-end&#39;,
  },
  container: {
    flex: 1,
    alignItems: &#39;center&#39;,
    justifyContent: &#39;space-between&#39;,
    margin: 10,
  },
  welcome: {
    fontSize: 30,
  },
  welcomeContainer: {
    alignItems: &#39;center&#39;,
    justifyContent: &#39;center&#39;,
    flex: 1,
    width: &#39;100%&#39;,
  },
});

const MainScreen: React.FunctionComponent&lt;MainScreenProps&gt; = (props) =&gt; {
  const {navigation} = props;
  const initialSymbol: string = &#39;삼성전자&#39;;
  const [symbol, setSymbol] = useState&lt;string&gt;(initialSymbol);
  // MainScreenProps 에 navigation 이 있으니까 비구조화 할당으로 꺼내쓸 수 있음
  return (
    &lt;SafeAreaView style={styles.container}&gt;
      &lt;View style={styles.welcomeContainer}&gt;
        &lt;Text style={styles.welcome}&gt;Main Screen&lt;/Text&gt;
      &lt;/View&gt;
      &lt;View style={styles.btnNextContainer}&gt;
        &lt;Button
          title=&quot;More&quot;
          onPress={() =&gt; navigation.navigate(HomeScreens.Details, {symbol})}
          // More 버튼을 누르면 HomeScreens 로 이동함.
        /&gt;
      &lt;/View&gt;
    &lt;/SafeAreaView&gt;
  );
};
export default MainScreen;</code></pre>
<ul>
<li>설명</li>
</ul>
<p><strong>(1) 스택 네비게이션에서 지정해줬던 타입 가져와서 지정해주기</strong></p>
<p>​    까먹었겠지만 HomeStackNavigator 를 만들 때 HomeScreens 와 HomeStackParamList 라는 enum 과 type 을 export 해줬었다. 그걸 그대로 가져와서 여기에 쓴다.</p>
<p>​    그리고 StackNavigationProps 에 필요한 타입들을 명시해준다.</p>
<pre><code class="language-tsx">// 아까 HomeStackNavigator 에서 export 해줬던 타입들을 가지고 온다.
import {
  HomeScreens,
  HomeStackParamList,
} from &#39;../../navigators/HomeStackNavigators&#39;;

// MainScreen 에 필요한 파라미터들을 StackNavigationProp 으로 타입 명시해준다.
type MainScreenNavigationProps = StackNavigationProp&lt;
  HomeStackParamList, // navigators/HomeStackNavigators/index.tsx 에서 지정했던 HomeStackParamList
  HomeScreens.Main // enum 으로 지정했던 타입 중 Main 에 해당하는 부분
&gt;;</code></pre>
<p><strong>(2) 인터페이스 정의</strong></p>
<p>​    인터페이스는 객체의 타입을 정의하는 것으로 타입과 비슷한 역할이라고 보면 되는데, 여기서는 Main 이라는 스크린에 필요한 props 를 미리 인터페이스로 지정해준다. 방금 명시한 <code>MainScreenNavigationProps</code> 를 지정해준다.</p>
<pre><code class="language-tsx">// MainScreenProps 에 대한 인터페이스 지정
// 인터페이스: 객체의 타입을 정의할 수 있게 하는 것
interface MainScreenProps {
  navigation: MainScreenNavigationProps; // 네비게이션 속성에 대한 타입으로 방금 지정해주었던 MainScreenNavigationProps 을 지정
}</code></pre>
<p><strong>(3) tsx 내보내기</strong></p>
<p>​    방금 만들어준 <code>MainScreenProps</code> 인터페이스를 타입으로 받는 React.FunctionComponent 를 만들어준다.</p>
<p>​    이 안에서 해야할 일은 많이 없고, <code>useState</code> 로 지정한 <code>symbol</code> 값을 받아 이 값을 Details 스크린의 props 로 넘기는 이벤트만 작성해주면 된다.</p>
<p>​    간단하게 하단 버튼을 눌렀을 때 <code>onPress</code> 이벤트에 네비게이션 메소드만 넣어주면 된다.</p>
<p>​    네비게이션은 <code>navigation.navigate({이동할 스크린명}, {파라미터})</code> 의 문법으로 작성하면 된다.</p>
<pre><code class="language-tsx">const MainScreen: React.FunctionComponent&lt;MainScreenProps&gt; = (props) =&gt; {
  const {navigation} = props;
  const initialSymbol: string = &#39;삼성전자&#39;;
  const [symbol, setSymbol] = useState&lt;string&gt;(initialSymbol);
  // MainScreenProps 에 navigation 이 있으니까 비구조화 할당으로 꺼내쓸 수 있음
  return (
    &lt;SafeAreaView style={styles.container}&gt;
      &lt;View style={styles.welcomeContainer}&gt;
        &lt;Text style={styles.welcome}&gt;Main Screen&lt;/Text&gt;
      &lt;/View&gt;
      &lt;View style={styles.btnNextContainer}&gt;
        &lt;Button
          title=&quot;More&quot;
          onPress={() =&gt; navigation.navigate(HomeScreens.Details, {symbol})}
          // More 버튼을 누르면 HomeScreens 로 이동함.
        /&gt;
      &lt;/View&gt;
    &lt;/SafeAreaView&gt;
  );
};
export default MainScreen;</code></pre>
<h4 id="3-detailsindextsx">3. <code>Details/index.tsx</code></h4>
<ul>
<li>전체 코드</li>
</ul>
<pre><code class="language-tsx">import React from &#39;react&#39;;
import {SafeAreaView, StyleSheet, Text, View} from &#39;react-native&#39;;
import {
  HomeScreens,
  HomeStackParamList,
} from &#39;../../navigators/HomeStackNavigators&#39;;
import {StackNavigationProp} from &#39;@react-navigation/stack&#39;;

type DetailsScreenNavigationProps = StackNavigationProp&lt;
  HomeStackParamList,
  HomeScreens.Details
&gt;;

// ~/src/navigators/HomeStackNavigators/index.tsx 에서 2번 각 스크린 마다 필요한 파라미터 타입 정의해줄 때 Details 스크린에 필요한 props 로 지정해줬었음.
export type DetailsParams = {
  symbol: string; // DetailsScreen 에는 symbol 이라는 이름의 string 타입의 파라미터가 필요하다.
};

// DetailsScreen Props 의 타입들을 지정. (리액트에서 proptypes 지정하는 것 처럼)
interface DetailsScreenProps {
  route: {params: DetailsParams}; // 루트의 파라미터로 방금 지정해준 DetailsParams 타입이 온다.
  navigation: DetailsScreenNavigationProps;
}

const styles = StyleSheet.create({
  btnLoginContainer: {
    alignSelf: &#39;center&#39;,
  },
  container: {
    flex: 1,
    alignItems: &#39;center&#39;,
    justifyContent: &#39;space-between&#39;,
    margin: 10,
  },
  txtSignupScreen: {
    fontSize: 30,
  },
  txtSignupScreenContainer: {
    flex: 1,
    alignItems: &#39;center&#39;,
    justifyContent: &#39;center&#39;,
  },
  txtSymbol: {
    fontSize: 25,
    color: &#39;grey&#39;,
  },
});

const DetailsScreen: React.FunctionComponent&lt;DetailsScreenProps&gt; = (props) =&gt; {
  const {navigation, route} = props;
  const {params} = route;
  const {symbol} = params;
  return (
    &lt;SafeAreaView style={styles.container}&gt;
      &lt;View style={styles.txtSignupScreenContainer}&gt;
        &lt;Text style={styles.txtSignupScreen}&gt;DetailsScreen&lt;/Text&gt;
        &lt;Text style={styles.txtSymbol}&gt;{symbol}&lt;/Text&gt;
      &lt;/View&gt;
    &lt;/SafeAreaView&gt;
  );
};
export default DetailsScreen;</code></pre>
<ul>
<li>설명</li>
</ul>
<p>여기서는 위의 Main 스크린에서와 거의 동일한 방법으로 진행하면 된다. 다만 Details 스크린에서는 Main 스크린과는 다르게 <code>symbol</code> 이라는 이름의 파라미터를 받을 것이다. 이를 위해서 <code>DetailsParams</code> 라는 타입을 export 해주고 인터페이스로 지정해야 한다.</p>
<p>*<em>(1) Main 스크린으로부터 파라미터로 넘겨받을 타입 지정하기 *</em></p>
<pre><code class="language-tsx">// ~/src/navigators/HomeStackNavigators/index.tsx 에서 2번 각 스크린 마다 필요한 파라미터 타입 정의해줄 때 Details 스크린에 필요한 props 로 지정해줬었음.
export type DetailsParams = {
  symbol: string; // DetailsScreen 에는 symbol 이라는 이름의 string 타입의 파라미터가 필요하다.
};</code></pre>
<p><strong>(2) 인터페이스 작성하기</strong></p>
<p>방금 export 해주었던 <code>DetailsParams</code> 를 포함하는 인터페이스를 작성해준다.</p>
<pre><code class="language-tsx">// DetailsScreen Props 의 타입들을 지정. (리액트에서 proptypes 지정하는 것 처럼)
interface DetailsScreenProps {
  route: {params: DetailsParams}; // 루트의 파라미터로 방금 지정해준 DetailsParams 타입이 온다.
  navigation: DetailsScreenNavigationProps;
}</code></pre>
<h4 id="4-apptsx">4. <code>App.tsx</code></h4>
<p>마지막으로 처음에 만들었던 HomeStackNavigator 를 가져와서 NavigationContainer 로 감싸서 export 해주기만 하면 된다.</p>
<pre><code class="language-tsx">import React from &#39;react&#39;;
import {NavigationContainer} from &#39;@react-navigation/native&#39;;
import HomeStackNavigatoer from &#39;./navigators/HomeStackNavigators&#39;;

export default function App() {
  return (
    &lt;NavigationContainer&gt;
      &lt;HomeStackNavigatoer /&gt;
    &lt;/NavigationContainer&gt;
  );
}</code></pre>
<p>이렇게 하면 기본 스택네비게이션 화면이 완성된다.</p>
<img src="https://i.imgur.com/Wsfj11z.png" alt="완성 메인스크린" width="360" height="720"/>

<img src="https://i.imgur.com/tGkdA3n.png" alt="완성 디테일 스크린"  width="360" height="720"/>



<p>차근차근 따라하니까 생각보다 어렵지 않다.</p>
<p>다음 글에서는 여기서 좀 더 나아가서 스택네비게이션 + 탭네비게이션이 조합된 Nested Navigation 을 만들어보겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React Native with TS] 타입스크립트로 리액트네이티브 boilder plate 만들기 (1)리액트 네이티브 앱 Typescript 로 세팅하기]]></title>
            <link>https://velog.io/@ant-now/React-Native-with-TS-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A1%9C-%EB%A6%AC%EC%95%A1%ED%8A%B8%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C-boilder-plate-%EB%A7%8C%EB%93%A4%EA%B8%B0-1%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C-%EC%95%B1-Typescript-%EB%A1%9C-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ant-now/React-Native-with-TS-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A1%9C-%EB%A6%AC%EC%95%A1%ED%8A%B8%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C-boilder-plate-%EB%A7%8C%EB%93%A4%EA%B8%B0-1%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C-%EC%95%B1-Typescript-%EB%A1%9C-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 17 Jan 2021 13:33:04 GMT</pubDate>
            <description><![CDATA[<p>이 글은 <a href="https://medium.com/@vdelacou/set-up-react-native-app-with-typescript-6c775e512336">https://medium.com/@vdelacou/set-up-react-native-app-with-typescript-6c775e512336</a> 을 보고 작성되었습니다.</p>
<p>이번 주 목표는 기존에 JS 로 작성하고 있던 주식앱을 TS 로 마이그레이션 하는 것이다.</p>
<p>원래 기존 프로젝트 코드를 TS 로 탈바꿈 하려고 했으나... 온갖 빨간줄과 버그와 혈투끝에 앱도 정상적으로 작동되게 하지 못하고 저버렸다.</p>
<p>몇시간의 삽질 끝에 깃을 다시 원복하고 이럴거면 아예 새로 보일러플레이트를 만들어보는게 낫겠다 싶었다.</p>
<p>적당한 블로그를 찾아 그대로 따라해보았다.</p>
<p>우선 총 4단계로 진행될 것이다.</p>
<blockquote>
</blockquote>
<p>1단계: 리액트 네이티브 앱 Typescript 로 세팅하기 (React Native set JS to TS)
2단계: 리액트 네이티브 백터아이콘 설치하기(Add React Native Vector Icons)
3단계: 리액트 네비게이션 설치 및 구현하기(Add React Navigation)
4단계: 리액트 네이티브 앱에 리덕스 스토어 붙이기</p>
<p>이번 포스팅은 1단계 세팅 부분을 다루겠다.</p>
<h2 id="1단계-리액트-네이티브-앱-typescript-로-세팅하기-react-native-set-js-to-ts">1단계. 리액트 네이티브 앱 Typescript 로 세팅하기 (React Native set JS to TS)</h2>
<p>(1) 타입스크립트로 세팅된 RN 앱 설치</p>
<p><code>react-native init myapp --template typescript</code></p>
<p>(2) ts lint 설치</p>
<p><code>npm install tslib tslint tslint-react tslint-config-standard tslint-config-prettier tslint-react-hooks tsutils tslint-etc --save-dev</code></p>
<p>(3) 루트 경로에 <code>tslint.json</code> 생성하여 린트 파일 설정하기 (본인의 스타일에 맞게 커스텀하면 된다)</p>
<pre><code class="language-json">{
  &quot;extends&quot;: [
    &quot;tslint:recommended&quot;,
    &quot;tslint-config-standard&quot;,
    &quot;tslint-etc&quot;,
    &quot;tslint-react&quot;,
    &quot;tslint-react-hooks&quot;,
    &quot;tslint-config-prettier&quot;
  ],
  &quot;rules&quot;: {
    // types related rules
    &quot;no-inferrable-types&quot;: true,
    &quot;no-namespace&quot;: {
      &quot;options&quot;: [&quot;allow-declarations&quot;]
    },
    &quot;interface-name&quot;: {
      &quot;options&quot;: &quot;never-prefix&quot;
    },
    &quot;no-unsafe-any&quot;: true,
    // core lint rules
    &quot;ban&quot;: {
      &quot;options&quot;: [
        {
          &quot;name&quot;: &quot;parseInt&quot;,
          &quot;message&quot;: &quot;use #type-coercion -&gt; Number(val)&quot;
        },
        {
          &quot;name&quot;: &quot;parseFloat&quot;,
          &quot;message&quot;: &quot;use #type-coercion -&gt; Number(val)&quot;
        },
        {
          &quot;name&quot;: &quot;Array&quot;,
          &quot;message&quot;: &quot;use #array-constructor&quot;
        },
        {
          &quot;name&quot;: [&quot;describe&quot;, &quot;only&quot;],
          &quot;message&quot;: &quot;don&#39;t focus spec blocks&quot;
        },
        {
          &quot;name&quot;: [&quot;it&quot;, &quot;only&quot;],
          &quot;message&quot;: &quot;don&#39;t focus tests&quot;
        }
      ]
    },
    &quot;no-require-imports&quot;: true,
    &quot;no-boolean-literal-compare&quot;: true,
    &quot;no-invalid-this&quot;: {
      &quot;options&quot;: &quot;check-function-in-method&quot;
    },
    &quot;no-invalid-template-strings&quot;: true,
    &quot;ordered-imports&quot;: true,
    &quot;prefer-template&quot;: true,
    &quot;newline-before-return&quot;: true,
    &quot;match-default-export-name&quot;: true,
    &quot;no-parameter-reassignment&quot;: true,
    &quot;file-name-casing&quot;: [true, &quot;kebab-case&quot;],
    &quot;switch-default&quot;: true,
    // tslint:recommended overrides
    &quot;no-any&quot;: true,
    &quot;member-access&quot;: {
      &quot;options&quot;: [&quot;no-public&quot;]
    },
    &quot;object-literal-sort-keys&quot;: false,
    &quot;interface-over-type-literal&quot;: false,
    // tslint:tslint-config-standard overrides
    //
    // tslint-etc rules
    &quot;no-unused-declaration&quot;: true,
    &quot;no-missing-dollar-expect&quot;: true,
    &quot;no-assign-mutated-array&quot;: true,
    // tslint-react rules
    &quot;jsx-boolean-value&quot;: {
      &quot;options&quot;: &quot;never&quot;
    }
  },
  // apply the same rules for any JS if allowJS is gonna be used
  &quot;jsRules&quot;: true
}</code></pre>
<p>(4)  <code>./src</code> 폴더 만들어서 <code>App.tsx</code>  파일 이동 후 클래스형에서 함수형 컴포넌트로 바꿔주기</p>
<pre><code class="language-tsx">import React, { FC } from &quot;react&quot;;
import { Platform, StyleSheet, Text, View } from &quot;react-native&quot;;
const instructions = Platform.select({
  ios: `Press Cmd+R to reload,\n Cmd+D or shake for dev menu`,
  android: `Double tap R on your keyboard to reload,\n Shake or press menu button for dev menu`
});
const App: FC = () =&gt; {
  return (
    &lt;View style={styles.container}&gt;
      &lt;Text style={styles.welcome}&gt;Welcome to React Native!&lt;/Text&gt;
      &lt;Text style={styles.instructions}&gt;To get started, edit App.tsx&lt;/Text&gt;
      &lt;Text style={styles.instructions}&gt;{instructions}&lt;/Text&gt;
    &lt;/View&gt;
  );
};
export default App;
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: &quot;center&quot;,
    alignItems: &quot;center&quot;,
    backgroundColor: &quot;#F5FCFF&quot;
  },
  welcome: {
    fontSize: 20,
    textAlign: &quot;center&quot;,
    margin: 10
  },
  instructions: {
    textAlign: &quot;center&quot;,
    color: &quot;#333333&quot;,
    marginBottom: 5
  }
});</code></pre>
<p>(5) 루트 경로의 <code>index.js</code> 내용 바꿔주기</p>
<ul>
<li>{} 컬리브레이스가 있다면 빼주고 App 임포트 경로 바꿔주기</li>
</ul>
<p><code>import App from &#39;./src/App&#39;;</code></p>
<p>(6) <code>__test__</code> 폴더 내 <code>App-test.js</code> 파일명 <code>app-test.tsx</code> 로 바꿔주기, 안에 있는 App 임포트 경로도 맞게 수정</p>
<p>it 에 빨간줄과 함께 모듈이 없다는 경고가 나오면 <code>npm i --save-dev @types/jest</code></p>
<p>(7) <code>package.json</code> 스크립트에 다음 명령어 추가</p>
<p>​    <code>&quot;lint&quot;: &quot;tslint src/**/*.ts* --project tsconfig.json&quot;</code></p>
<p>(8) 허스키 설치: <code>npm install husky --save-dev</code></p>
<p>​    <code>package.json</code> 에 추가</p>
<pre><code class="language-json">&quot;husky&quot;: {
    &quot;hooks&quot;: {
      &quot;pre-commit&quot;: &quot;npm run lint&quot;,
      &quot;pre-push&quot;: &quot;npm run lint&quot;
    }
  }</code></pre>
<p>위의 과정을 거치면 이제 내 앱이 타입스크립트로 성공적으로 실행이 된다.</p>
<p>아래는 완성된 앱의 기본 UI다.</p>
<img src="https://i.imgur.com/mmx1DJq.png" alt="완성된 UI" width="400" />

]]></description>
        </item>
    </channel>
</rss>