<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>TTOLBE</title>
    <link>https://nadja09.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Thu, 16 Apr 2026 09:50:33 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>TTOLBE</managingEditor>
    <image>
      <title>TTOLBE</title>
      <url>https://tistory1.daumcdn.net/tistory/5339427/attach/981c238002f14089a06954b2f6644a3b</url>
      <link>https://nadja09.tistory.com</link>
    </image>
    <item>
      <title>NextJS 시작하기</title>
      <link>https://nadja09.tistory.com/31</link>
      <description>&lt;h1&gt;Framework overview&lt;/h1&gt;
&lt;p&gt;이 글은 노마드 코더의 NextJS 시작하기라는 무료 강의를 듣고 작성되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://nomadcoders.co/nextjs-fundamentals/lobby&quot;&gt;강의링크&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;1.0 Library vs Framework&lt;/h2&gt;
&lt;h2&gt;1.1 Pages&lt;/h2&gt;
&lt;p&gt;Next.js에는 기본적으로 pages라는 폴더가 있는데, 그 폴더는 라우터 역할을 한다. 안에 index.js를 만들면 로컬호스트의 메인페이지에 자동으로 렌더링 된다. 만약 about.js를 만들면 /about 페이지에 해당 내용이 렌더링 되는 방식이다. 즉 파일의 이름이 url이 된다. 하지만 그 안의 컴포넌트의 이름은 상관이 없다. 하지만 그안에 렌더링 될 컴포넌트는 default export가 되어야 한다. 또한 next.js는 자동으로 404페이지를 제공해준다. pages 폴더 안에는 반드시 index.js가 들어가야한다. jsx를 사용해도 따로 리액트를 임포트 해올 필요가 없는 점도 장점이다.&lt;/p&gt;
&lt;h2&gt;1.2 Static Pre Rendering&lt;/h2&gt;
&lt;p&gt;next.js의 최대 장점은 앱의 페이지들이 미리 렌더링 된다는 점이다. create react app 은 크라이언트 사이드 렌더링을 하는 앱을 만들고, 이 앱안에는 div 하나 뿐이다. 그리고 client-side 자바스크립트가 모든 ui를 만든다. 만약 자바스크립트가 비활성화 된다면 noscript를 보게 된다. 또한 로딩이 느리다면 그냥 흰 화면만 보게 된다. 하지만 next.js에서는 html을 볼 수 있다. 또한 next에서는 state을 사용하면 초기 상태로 html에 prerendering을 한다. 이렇게 react를 프론트엔드 안에서 실행하는 걸 hydration이라고 부른다.&lt;/p&gt;
&lt;h2&gt;1.3 Routing (08:04)&lt;/h2&gt;
&lt;p&gt;이번에는 Navbar를 components 폴더안에 만들어보자. Navbar에서 이동에 a 태그를 쓰면 es lint 에서 a tag를 라우팅에 사용하지 말라고 한다. a 태그를 사용하면 브라우저가 다른페이지로 이동할때 완전히 새로고침 되기 때문이다. a 태그 대신 next 자체의 Link 태그를 사용해야 한다.&lt;/p&gt;
&lt;p&gt;(강의에서는 a 태그로 텍스트를 감싸주지만 버전이 바뀌면서 에러가 난다. 또한 이젠 Link 태그에 클래스 명을 정해주거나 인라인 스타일을 사용할수 있다. )&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;import Link from &amp;#39;next/link&amp;#39;;

export default function Navbar() {
  return (
    &amp;lt;nav&amp;gt;
      &amp;lt;Link href=&amp;quot;/&amp;quot; &amp;gt;
        home
      &amp;lt;/Link&amp;gt;
      &amp;lt;Link href=&amp;quot;/about&amp;quot;&amp;gt;
        about
      &amp;lt;/Link&amp;gt;
    &amp;lt;/nav&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위와 같은 방식으로 링크태그를 사용해주면 된다. 그러면 웹이 리프레시 되지 않는다.&lt;/p&gt;
&lt;p&gt;useRouter 훅에대해 살펴보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;import Link from &amp;#39;next/link&amp;#39;;
import { useRouter } from &amp;#39;next/router&amp;#39;;

export default function Navbar() {
  const router = useRouter();
  return (
    &amp;lt;nav&amp;gt;
      &amp;lt;Link href=&amp;quot;/&amp;quot; className=&amp;quot;dd&amp;quot; style={{ color: &amp;#39;red&amp;#39; }}&amp;gt;
        home
      &amp;lt;/Link&amp;gt;
      &amp;lt;Link href=&amp;quot;/about&amp;quot;&amp;gt;about&amp;lt;/Link&amp;gt;
    &amp;lt;/nav&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;router를 콘솔에 찍어보면 router에서 location 정보를 얻을 수 있단 걸 알수 있다. useRouter를 통해 현재 페이지에 따른 내비게이션 색을 바꿔보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;import Link from &amp;#39;next/link&amp;#39;;
import { useRouter } from &amp;#39;next/router&amp;#39;;

export default function Navbar() {
  const router = useRouter();
  return (
    &amp;lt;nav&amp;gt;
      &amp;lt;Link
        href=&amp;quot;/&amp;quot;
        className=&amp;quot;dd&amp;quot;
        style={{ color: router.pathname === &amp;#39;/&amp;#39; ? &amp;#39;red&amp;#39; : &amp;#39;#000&amp;#39; }}
      &amp;gt;
        home
      &amp;lt;/Link&amp;gt;
      &amp;lt;Link
        href=&amp;quot;/about&amp;quot;
        style={{ color: router.pathname === &amp;#39;/about&amp;#39; ? &amp;#39;red&amp;#39; : &amp;#39;#000&amp;#39; }}
      &amp;gt;
        about
      &amp;lt;/Link&amp;gt;
    &amp;lt;/nav&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;1.4 CSS Modules&lt;/h2&gt;
&lt;p&gt;Navbar에 css 모듈을 적용해보자. NavBar.module.css 라는 파일을 만들고, 그안에 nav 라는 클래스를 하나 생성하자. 그리고 그안에 원하는 스타일 요소들을 넣는다. 다시 NavBar.js 파일로 와서 임포트해주자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;import styles from &amp;#39;./NavBar.module.css&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;그리고는 jsx에 클래스 명을 className={styles.nav} 라고 적으면, 스타일이 적용된다.&lt;br&gt;css 모듈의 장점은 클래스 이름 충돌이 일어나지 않는다는 점이다.&lt;/p&gt;
&lt;h2&gt;1.5 Styles JSX (06:56)&lt;/h2&gt;
&lt;p&gt;Styles jsx는 NextJS 고유의 스타일링 방법이라고도 할 수 있다. 우선 컴포넌트안에 style 태그를 열고, jsx attribute를 추가해준다. 그 다음 그안에 중괄호를 연다. 중괄호 안에 백틱도 넣는다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;      &amp;lt;style jsx&amp;gt;{``}&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;아래처럼 작성하면 스타일이 적용 된다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;import Link from &amp;#39;next/link&amp;#39;;
import { useRouter } from &amp;#39;next/router&amp;#39;;

export default function Navbar() {
 const router = useRouter();
 return (
   &amp;lt;nav&amp;gt;
     &amp;lt;Link
       href=&amp;quot;/&amp;quot;
       legacyBehavior
       style={{ color: router.pathname === &amp;#39;/&amp;#39; ? &amp;#39;red&amp;#39; : &amp;#39;#000&amp;#39; }}
     &amp;gt;
       &amp;lt;a&amp;gt;home&amp;lt;/a&amp;gt;
     &amp;lt;/Link&amp;gt;
     &amp;lt;Link
       href=&amp;quot;/about&amp;quot;
       legacyBehavior
       style={{ color: router.pathname === &amp;#39;/about&amp;#39; ? &amp;#39;red&amp;#39; : &amp;#39;#000&amp;#39; }}
     &amp;gt;
       &amp;lt;a&amp;gt;about&amp;lt;/a&amp;gt;
     &amp;lt;/Link&amp;gt;
     &amp;lt;style jsx&amp;gt;{`
       nav {
         background-color: tomato;
       }
       a {
         font-size: 24px;
       }
     `}&amp;lt;/style&amp;gt;
   &amp;lt;/nav&amp;gt;
 );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;1.6 Custom App&lt;/h2&gt;
&lt;p&gt;우선 Global Style을 설정하는 방법을 알아보자.&lt;/p&gt;
&lt;p&gt;style jsx 태그에 global attribute만 추가해주면 된다. 그런데 이렇게 할 경우에는 그 해당 페이지에만 적용된다. 전체적으로 적용하기 위해선 어떻게 해야할까. 이럴 땐 모든 페이지의 청사진이 되는 App component 가 필요하다. pages 파일에 _app.js 라는 파일을 만들어주면 된다. NEXT.js는 전부 렌더링 하기 전에 _app.js 파일을 참고 할 것이다. 이 파일은 두개의 props를 불러온다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;export default function App({ Component, pageProps }) {
  return &amp;lt;Component {...pageProps} /&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이렇게 하고 앱을 실행하면 여전히 동일하다. 이번에는 이 안에 다른 요소를 넣어보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;export default function App({ Component, pageProps }) {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;Component {...pageProps} /&amp;gt;
      &amp;lt;span&amp;gt;hello&amp;lt;/span&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이렇게 하면 모든 페이지에 hello 가 출력되는 모습을 볼수 있다. 그리고 이 _app.js 파일에 global style을 추가해주면 전체적으로 먹힌다.&lt;/p&gt;</description>
      <category>개발/React</category>
      <category>nextjs</category>
      <category>노마드코더</category>
      <author>TTOLBE</author>
      <guid isPermaLink="true">https://nadja09.tistory.com/31</guid>
      <comments>https://nadja09.tistory.com/31#entry31comment</comments>
      <pubDate>Mon, 2 Jan 2023 16:43:36 +0900</pubDate>
    </item>
    <item>
      <title>TypeScript로 블록체인 만들기(4)</title>
      <link>https://nadja09.tistory.com/30</link>
      <description>&lt;h1&gt;Block Chain&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 노마드 코더의 타입스크립트 무료 강의를 보고 노트 정리를 한 글입니다.&lt;br /&gt;&lt;a href=&quot;https://nomadcoders.co/typescript-for-beginners/lobby&quot;&gt;강의링크&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.0 Introduction&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.1 Targets&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 폴더 생성후 npm init -y를 통해 새 package.json 파일을 생성해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;package.json을 다음과 같이 수정해준다.&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;
{
  &quot;name&quot;: &quot;blockchain&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;scripts&quot;: {

  },
  &quot;keywords&quot;: [],
  &quot;author&quot;: &quot;&quot;,
  &quot;license&quot;: &quot;ISC&quot;
}

&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;터미널에 npm install -D typescript 라고 적으면 된다. 그러면 package.json에 devDependencies 가 추가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 폴더에 src 폴더를 생성 후 index.ts 파일을 그 안에 생성하자. 그리고 그안에 함수를 하나 만들어 컴파일이 되는지 테스트 해보자.&lt;/p&gt;
&lt;pre class=&quot;coffeescript&quot;&gt;&lt;code&gt;
const hello = () =&amp;gt; 'hi';

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tsconfig.json 파일을 생성하자.&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;
{
  &quot;include&quot;: [&quot;src&quot;], //컴파일할 타입스크립트 파일 위치
  &quot;compilerOptions&quot;: {
    &quot;outDir&quot;: &quot;build&quot; //컴파일한 파일의 위치
  }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 package 파일에 build script를 추가해주자.&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;
{
  &quot;name&quot;: &quot;blockchain&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;scripts&quot;: {
    &quot;build&quot;: &quot;tsc&quot;
  },
  &quot;keywords&quot;: [],
  &quot;author&quot;: &quot;&quot;,
  &quot;license&quot;: &quot;ISC&quot;,
  &quot;devDependencies&quot;: {
    &quot;typescript&quot;: &quot;^4.9.4&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 터미널에 npm run build 라고 적으면 build 폴더가 생성 되고 그안에 자바스크립트로 컴파일된 파일이 생긴다.&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;
var hello = function () { return 'hi'; };
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 컴파일 된 것을 확인 할수 있다. 자바스크립트로 변환하면서 더 낮은 버전의 자바스크립트가 되었는데 이는 호환성을 위해서다. 자바스크립트의 버전을 정하려면 tsconfig 파일을 아래와 같이 수정하면 된다.&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;
{
  &quot;include&quot;: [&quot;src&quot;], //컴파일할 타입스크립트 파일 위치
  &quot;compilerOptions&quot;: {
    &quot;outDir&quot;: &quot;build&quot;, //컴파일한 파일의 위치
    &quot;target&quot;: &quot;ES3&quot; //컴파일한 자바스크립트 버전
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 브라우저는 es6을 지원하기 때문에 es6을 쓰는게 추천 된다고 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.2 Lib Configuration&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;lib는 합쳐진 라이브러리의 정의 파일을 특정해주는 역할을 한다. 또한 자바스크립트 코드가 어디서 작동하는지 알려준다. tsconfig 파일을 열자.&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;include&quot;: [&quot;src&quot;], //컴파일할 타입스크립트 파일 위치
  &quot;compilerOptions&quot;: {
    &quot;outDir&quot;: &quot;build&quot;, //컴파일한 파일의 위치
    &quot;target&quot;: &quot;ES6&quot;, //컴파일한 자바스크립트 버전
    &quot;lib&quot;: [&quot;ES6&quot;, &quot;DOM&quot;] //작동환경(es6, 브라우저)
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;DOM&quot;을 추가해줌으로서 타입스크립트는 자체적으로 브라우저 전용 API, 함수등의 자동완성을 지원해준다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.3 Declaration Files&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패키지와 라이브러리를 사용 할 때 대부분 자바스크립트로 만들어진 것들을 사용하게 된다. 그럴 땐 타입스크립트에게 자바스크립트 파일의 모양을 설명해 줘야 한다. src 폴더에 myPackage.js 파일을 만들어보자.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;
export function init(config) {
  return true;
}

export function exit(code) {
  return code + 1;
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 index.ts 파일로 가서 위 파일이 node의 모듈 인 것처럼 사용해보자.&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;
import { init } from 'myPackage';

init();

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직 strictmode를 설정하지 않았으므로 작동은 한다. 그러므로 tsconfig에서 strictmode를 활성시키자.&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;include&quot;: [&quot;src&quot;], //컴파일할 타입스크립트 파일 위치
  &quot;compilerOptions&quot;: {
    &quot;outDir&quot;: &quot;build&quot;, //컴파일한 파일의 위치
    &quot;target&quot;: &quot;ES6&quot;, //컴파일한 자바스크립트 버전
    &quot;lib&quot;: [&quot;ES6&quot;, &quot;DOM&quot;], //작동환경(es6, 브라우저)
    &quot;strict&quot;: true //strict mode
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 변경해주면 index.ts 에 선언 파일을 찾을 수 없다고 에러가 뜰 것이다. 선언 파일을 만들어주자. src에 myPackage.d.ts라는 새 파일을 만들자. 여기서 d.ts 파일은 정의 파일을 의미 한다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;
interface Config {
  urls: string;
}

declare module 'myPackage' {
  function init(config: Config): boolean;
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 모듈을 정의 해주자. 그럼 더이상 init을 import 하는데에 오류가 발생치 않는다.&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;
import { init } from 'myPackage';

init({
  urls: true,
});

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 exit도 추가 해주자.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;
interface Config {
  url: string;
}

declare module 'myPackage' {
  function init(config: Config): boolean;
  function exit(code: number): number;
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 index.ts에서는 두 함수모두 사용 가능하다.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;
import { init, exit } from 'myPackage';

init({
  url: 'true',
});

exit(1);

&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.4 JSDoc&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미 가지고 있는 자바스크립트 파일을 타입스크립트에서 사용하는 방법을 알아보자. 우선 myPackage.d.ts 파일을 삭제하고 index.ts에서의 import 방식을 변경해주자.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;
import { init, exit } from './myPackage';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 오류가 난다.&lt;br /&gt;tsconfig 파일을 아래와 같이 수정해주자.&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;
{
  &quot;include&quot;: [&quot;src&quot;], //컴파일할 타입스크립트 파일 위치
  &quot;compilerOptions&quot;: {
    &quot;outDir&quot;: &quot;build&quot;, //컴파일한 파일의 위치
    &quot;target&quot;: &quot;ES6&quot;, //컴파일한 자바스크립트 버전
    &quot;lib&quot;: [&quot;ES6&quot;, &quot;DOM&quot;], //작동환경(es6, 브라우저)
    &quot;strict&quot;: true, //strict mode
    &quot;allowJs&quot;: true //자바스크립트 허용
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 자유롭게 자바스크립트 파일을 타입스크립트에서도 사용가능하다. 타입스크립트에 넣은 자바스크립트도 보호기능이 작동한다. 자바스크립트 맨위에 주석을 추가하면 된다.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;
//@ts-check

export function init(config) {
  return true;
}

export function exit(code) {
  return code + 1;
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뜨는 에러들을 일일히 고칠 필요는 없고, JSDoc 이란 걸 사용하면 된다. JSDoc이란 코멘트로 이루어진 문법이고, 이걸 사용하면 타입스크립트가 검사할수 있다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;//@ts-check
/**
 * Initializes the project
 * @param {*} config
 * @returns
 */
export function init(config) {
  return true;
}

export function exit(code) {
  return code + 1;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;/**을 적으면 vs 코드에서 제공하는 snippet을 사용가능하다.&lt;/p&gt;
&lt;pre class=&quot;php&quot;&gt;&lt;code&gt;//@ts-check
/**
 * Initializes the project
 * @param {object} config
 * @param {boolean} config.debug
 * @param {string} config.url
 * @returns {boolean}
 */
export function init(config) {
  return true;
}

/**
 *
 * @param {number} code
 * @returns {number}
 */

export function exit(code) {
  return code + 1;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 @뒤에 param을 정해주면 타입스크립트가 자바스크립트를 읽는데 도와준다. 또한 코멘트기 때문에 이미 짜여진 코드가 손상될 일은 없다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.5 Blocks&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블록체인을 만들어보자. 우선 package.json 파일에 start명령을 추가해주자.&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;name&quot;: &quot;blockchain&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;scripts&quot;: {
    &quot;build&quot;: &quot;tsc&quot;,
    &quot;start&quot;: &quot;node build/index.js&quot;
  },
  &quot;keywords&quot;: [],
  &quot;author&quot;: &quot;&quot;,
  &quot;license&quot;: &quot;ISC&quot;,
  &quot;devDependencies&quot;: {
    &quot;typescript&quot;: &quot;^4.9.4&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 터미널에 npm run build &amp;amp;&amp;amp; npm run start 라고 적으면 실행된다. 하지만 너무 비효율적이므로 npm i -D ts-node를 설치해주자. ts node는 빌드없이 타입스크립트를 바로 쓸수 있게 해주는 프로덕션 툴이다. 거기에 npm i nodemon으로 서버를 자동으로 재시작 시켜주는 패키지도 하나깔자. package 에 dev 스크립트를 하나 추가해주자.&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;name&quot;: &quot;blockchain&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;scripts&quot;: {
    &quot;build&quot;: &quot;tsc&quot;,
     &quot;dev&quot;: &quot;nodemon --exec ts-node src/index.ts&quot;,
    &quot;start&quot;: &quot;node build/index.js&quot;
  },
  &quot;keywords&quot;: [],
  &quot;author&quot;: &quot;&quot;,
  &quot;license&quot;: &quot;ISC&quot;,
  &quot;devDependencies&quot;: {
    &quot;ts-node&quot;: &quot;^10.9.1&quot;,
    &quot;typescript&quot;: &quot;^4.9.4&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 설정이 끝났고 본격적으로 블록체인을 디자인 해보자. 이하는 코딩이 대부분이므로 생략한다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;
import crypto from 'crypto';

interface BlockShape {
  hash: string;
  prevHash: string;
  height: number;
  data: string;
}

class Block implements BlockShape {
  public hash: string;
  constructor(
    public prevHash: string,
    public height: number,
    public data: string
  ) {
    this.hash = Block.calculateHash(prevHash, height, data);
  }
  static calculateHash(prevHash: string, height: number, data: string) {
    const toHash = `${prevHash}${height}${data}`;
    return crypto.createHash('sha256').update(toHash).digest('hex');
  }
}

class Blockchain {
  private blocks: Block[];
  constructor() {
    this.blocks = [];
  }
  private getPrevHash() {
    if (this.blocks.length === 0) return '';
    return this.blocks[this.blocks.length - 1].hash;
  }
  public addBlock(data: string) {
    const newBlock = new Block(
      this.getPrevHash(),
      this.blocks.length - 1,
      data
    );
    this.blocks.push(newBlock);
  }
  public getBlocks() {
    return [...this.blocks];
  }
}

const blockchain = new Blockchain();

blockchain.addBlock('first one');
blockchain.addBlock('second one');
blockchain.addBlock('third one');

console.log(blockchain.getBlocks());

&lt;/code&gt;&lt;/pre&gt;</description>
      <category>개발/타입스크립트</category>
      <category>노마드코더</category>
      <category>타입스크립트</category>
      <author>TTOLBE</author>
      <guid isPermaLink="true">https://nadja09.tistory.com/30</guid>
      <comments>https://nadja09.tistory.com/30#entry30comment</comments>
      <pubDate>Fri, 30 Dec 2022 14:26:54 +0900</pubDate>
    </item>
    <item>
      <title>TypeScript로 블록체인 만들기(3)</title>
      <link>https://nadja09.tistory.com/29</link>
      <description>&lt;h1&gt;Classes&lt;/h1&gt;
&lt;p&gt;이 글은 노마드 코더의 타입스크립트 무료 강의를 보고 노트 정리를 한 글입니다.&lt;br&gt;&lt;a href=&quot;https://nomadcoders.co/typescript-for-beginners/lobby&quot;&gt;강의링크&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;4.0 Classes&lt;/h2&gt;
&lt;p&gt;이번에는 객제지향 타입스크립트에 대해 배워보자.&lt;/p&gt;
&lt;p&gt;타입스크립트로 클래스를 만드는 방법은 아래와 같다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
class Player {
  constructor(
    private firstName:string,
    private lastName:string,
    public nickName:string
  )
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;타입스크립트에서는 constructor에서 public, private 속성을 부여할 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
const ttolbe= new Player(&amp;quot;Ttolbe&amp;quot;,&amp;quot;Na&amp;quot;,&amp;quot;Tolby&amp;quot;)

ttolbe.firstName;

ttolbe.nickName;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위와 같이 오브젝트를 만들고 firstName 속성을 불러오면 에러가 나지만 nickName은 에러가 나지 않는다. firstName은 private 속성을 지녔고 nickName은 public속성을 지녔기 때문이다.&lt;/p&gt;
&lt;p&gt;타입스크립트가 가진 기능 중 하나는 abstract class 이다. 추상 클래스는 다른 클래스에게 상속할수 있다. 하지만 새로운 인스턴스를 만들 수는 없다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
abstract class User{
    constructor(
    private firstName:string,
    private lastName:string,
    public nickName:string
  ){}
}

class Player extends User{

}

const ttolbe= new User(&amp;quot;Ttolbe&amp;quot;,&amp;quot;Na&amp;quot;,&amp;quot;Tolby&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위와 같이 User를 새로 만들려고 하면 오류가 발생한다.&lt;/p&gt;
&lt;p&gt;추상 클래스 안에는 추상 메소드를 넣을 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
abstract class User{
    constructor(
    private firstName:string,
    private lastName:string,
    public nickName:string
  ){}
      getFullName(){
      return `${this.firstName} ${this.lastName}`
    }
}

class Player extends User{

}
const ttolbe= new Player(&amp;quot;Ttolbe&amp;quot;,&amp;quot;Na&amp;quot;,&amp;quot;Tolby&amp;quot;)

ttolbe.getFullName()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;추상 메소드로 클래스 안의 private 속성에 접근 가능하다. 한편 이 메소드를 아래와 같이 private 속성으로 변경하면 getFullName() 함수는 실행할수 없어 에러가 난다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
abstract class User{
    constructor(
    private firstName:string,
    private lastName:string,
    public nickName:string
  ){}
     private getFullName(){
      return `${this.firstName} ${this.lastName}`
    }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;또 다른 속성에는 protected가 있다. protected를 사용하면 public 속성 처럼 값에는 접근 가능하지만, 값을 변경 할 수는 없다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
abstract class User{
    constructor(
    protected firstName:string,
    private lastName:string,
    public nickName:string
  ){}
      getFullName(){
      return `${this.firstName} ${this.lastName}`
    }
}

class Player extends User{

}
const ttolbe= new Player(&amp;quot;Ttolbe&amp;quot;,&amp;quot;Na&amp;quot;,&amp;quot;Tolby&amp;quot;)

ttolbe.nickName=&amp;quot;nick&amp;quot;

ttolbe.firstName=&amp;quot;Me&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위와 같이 코드를 짜면 nickName은 변경 가능하지만, firstName은 변경 되지 않아 에러가 발생한다.&lt;/p&gt;
&lt;h2&gt;4.1 Recap&lt;/h2&gt;
&lt;p&gt;지금 까지 배운 것을 응용해 해시맵을 만들어보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
type Words={
  [key:string]:string
}

//키와 값이 둘다 string인 object type

class Dict{
  private words:Words,
  constructor(){
    this.words={}
  }
  add(word:Word){//클래스를 타입처럼 사용가능
    if(this.words[word.term]===undefined){
      this.words[word.term]=word.def
    }
  }
  def(term:string){
    return this.words[term]
  }
}

class Word{
  constructor(
    public readonly term:string,//term은 수정 불가능하게
    public def:string
  ){}
}

const kimchi = new Word(&amp;quot;Kimchi&amp;quot;,&amp;quot;Korean Food&amp;quot;)

const dict=new Dict()

dict.add(kimchi)

dict.def(&amp;quot;kimchi&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;4.2 Interfaces&lt;/h2&gt;
&lt;p&gt;인터페이스는 타입과 비슷하지만, 두가지 부분에서 다르다. 우선 지금 까지 타입을 선언하던 방법을 되돌아보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
type Player={
  nickName:string,
  health:number
}

const Ttolbe:Player={
  nickName:&amp;quot;TTolbe&amp;quot;,
  health:10
}

type Food=string

const kimchi:Food=&amp;quot;kimchi&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;또한 타입을 옵션으로 제한 할 수도 있다. 옵션 외의 값을 입력하면 틀렸다고 한다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
type Team=&amp;quot;red&amp;quot;|&amp;quot;blue&amp;quot;|&amp;quot;yellow&amp;quot;
//Team의 옵션 제한
type Health=1|5|10

type Player={
  nickName:string,
  team:Team,
  health:Health
}

const Ttolbe:Player={
  nickName:&amp;quot;TTolbe&amp;quot;,
  team:&amp;quot;red&amp;quot;,
  health:10
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;인터페이스는 위와는 타입 선언 방식이 다르다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
type Team=&amp;quot;red&amp;quot;|&amp;quot;blue&amp;quot;|&amp;quot;yellow&amp;quot;

type Health=1|5|10

interface Player {
  nickName:string,
  team:Team,
  health:Health
}

const Ttolbe:Player={
  nickName:&amp;quot;TTolbe&amp;quot;,
  team:&amp;quot;red&amp;quot;,
  health:10
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;인터페이스는 타입스크립트에게 오브젝트의 형태를 알리는 방식이다. 다만 타입은 인터페이스보다 활용도가 높다. 인터페이스는 오브젝트외에 다른 변수 모양은 특정 할 수 없다.&lt;/p&gt;
&lt;p&gt;인터페이스는 아래와 같이 상속 또한 가능하다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
interface User{
  name:string
}

interface Player extends User{
}

const ttolbe:Player={
  name:&amp;quot;ttolbe&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위의 작업을 타입으로 적용해보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
type User={
  name:string
}

type Player=User&amp;amp;{
}

const ttolbe:Player={
  name:&amp;quot;ttolbe&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;인터페이스 역시 class처럼 readonly의 속성을 부여 가능하다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
type User={
  readonly name:string
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;인터페이스의 또 다른 특징은 속성의 축적이다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
interface User{
  name:string
}

interface User{
  lastName:string
}

interface User{
  health:number
}

const ttolbeUser:User={
  name:&amp;quot;Ttolbe&amp;quot;,
  lastName:&amp;quot;Kim&amp;quot;,
  health:10
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위와 같이 동일 인터페이스를 여러개 쓰면 타입스크립트가 알아서 합쳐준다. 하지만 타입은 속성의 축정이 불가능하다.&lt;/p&gt;
&lt;h2&gt;4.3 Interfaces part Two&lt;/h2&gt;
&lt;p&gt;다시 한번 추상 클래스에 대해 복습해보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
abstract class User{
  constructor(
    protected firstName:string,
    protected lastName:string,
  ){}
  abstract sayHi(name:string):string;
  abstract fullName():string
}

class Player extends User{
  fullName(){
    return `${this.firstName} ${this.lastName}`
  }
  sayHi(name:string){
    return `Hello ${name}. My name is ${this.fullName()}`
  }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;추상 클래스는 상속 받는 클래스가 어떻게 행동해야하는지 알려주기 위해 존재한다.&lt;/p&gt;
&lt;p&gt;다시 인터페이스로 돌아가자면, 우선 인터페이스는 자바스크립트로 컴파일 되지 않기 때문에 가볍다. 여기서 추상 클래스를 인터페이스로 변환해보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
interface class User{
  firstName:string,
  lastName:string,
  sayHi(name:string):string;
  fullName():string
}

class Player implements User{
  constructor(
    private firstName:string,
    private lastName:string
  ){}
  fullName(){
    return `${this.firstName} ${this.lastName}`
  }
  sayHi(name:string){
    return `Hello ${name}. My name is ${this.fullName()}`
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위의 코드를 적으면 에러가 난다. 인터페이스를 상속할 때는 property를 private 또는 protected 으로 설정할 수 없기 때문이다.&lt;/p&gt;
&lt;h2&gt;4.4 Recap&lt;/h2&gt;
&lt;p&gt;인터페이스는 원하는 메소드와 property를 클래스가 가지도록 강제 할 수 있다. 또한 인터페이스는 자바스크립트로 컴파일되지 않는다. 추상 클래스와 비슷한 보호를 제공하나, 자바스크립트에서는 보이지 않는 것이다.&lt;/p&gt;
&lt;p&gt;또 다시 인터페이스와 타입의 차이를 복습해보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
type PlayerA={
  name:string
}

const playerA:PlayerA={
  name:&amp;quot;ttolbe&amp;quot;
}

interface PlayerB {
  name:string
}

const playerB:PlayerB={
  name:&amp;quot;ttolbe&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위의 코드에서는 타입과 인터페이스 둘다 수행하는 역할이 같기 때문에 차이가 없어보인다. 하지만 타입스크립트에서 허용하는 둘의 기능은 좀 다르다.&lt;/p&gt;
&lt;p&gt;일단 상속 방식의 차이를 보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
type PlayerA={
  name:string
}

type PlayerAA= PlayerA &amp;amp; {
  lastName:string
}
//타입의 상속을

const playerA:PlayerAA={
  name:&amp;quot;ttolbe&amp;quot;,
  lastName:&amp;quot;Kim&amp;quot;
}

interface PlayerB {
  name:string
}

interface PlayerBB extends PlayerB{
  lastName:string
}

const playerB:PlayerBB={
  name:&amp;quot;ttolbe&amp;quot;,
  lastName:&amp;quot;kim&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;둘이 비슷하지만 타입은 하나의 타입에 또다른 property를 추가할수 없다. 하지만 인터페이스는 가능하다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
interface PlayerB {
  name:string
}

interface PlayerB{
  lastName:string
}

const playerB:PlayerBB={
  name:&amp;quot;ttolbe&amp;quot;,
  lastName:&amp;quot;kimm&amp;quot;
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;원한다면 인터페이스와 타입 모두 추상 클래스를 대신할수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
type PlayerA={
  firstName:string
}

class User implements PlayerA{
  constructor(
    public firstName:string
  ){}
}

interface PlayerB {
  firstName:string
}

class User implements PlayerB{
  constructor(
    public firstName:string
  ){}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;4.5 Polymorphism&lt;/h2&gt;
&lt;p&gt;전에 배웠듯이 다형성은 다른 모양의 코드를 가질 수 있게 해주는 것이며 다형성을 이루는 법은 제네릭을 사용하는 것이다.&lt;/p&gt;
&lt;p&gt;브라우저에서 쓰는 로컬스토리지와 유사한 API를 만들어보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-TypeScript&quot;&gt;
interface SStorage&amp;lt;T&amp;gt;{
  [key:string]:T
}

class LocalStorage&amp;lt;T&amp;gt; {
  private storage:SStorage&amp;lt;T&amp;gt;={}
  set(key:string, value:T){
    this.storage[key]=value
  }
  remove(key:string){
    delete this.storage[key]
  }
  get(key:string):T{
    return this.storage[key]
  }
  clear(){
    this.storage={}
  }
}

const stringsStorage= new LocalStorage&amp;lt;string&amp;gt;()

stringsStorage.set(&amp;quot;key&amp;quot;,&amp;quot;hello&amp;quot;)

stringsStorage.get(&amp;quot;key&amp;quot;)//result is string

const booleanStorage=new LocalStorage&amp;lt;boolean&amp;gt;()

booleanStorage.set(&amp;quot;key&amp;quot;,true)

booleanStorage.get(&amp;quot;key&amp;quot;)//result is boolean
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>개발/타입스크립트</category>
      <category>노마드코더</category>
      <category>타입스크립트</category>
      <author>TTOLBE</author>
      <guid isPermaLink="true">https://nadja09.tistory.com/29</guid>
      <comments>https://nadja09.tistory.com/29#entry29comment</comments>
      <pubDate>Thu, 29 Dec 2022 14:36:07 +0900</pubDate>
    </item>
    <item>
      <title>TypeScript로 블록체인 만들기(2)</title>
      <link>https://nadja09.tistory.com/28</link>
      <description>&lt;h1&gt;Functions&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 노마드 코더의 타입스크립트 무료 강의를 보고 노트 정리를 한 글입니다.&lt;br /&gt;&lt;a href=&quot;https://nomadcoders.co/typescript-for-beginners/lobby&quot;&gt;강의링크&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3.0 Call Signatures&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;call signature는 함수의 타입을 정하는걸 의미한다. call signature를 호출하는 방법은 아래와 같다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;
type Add=(a:number, b:number)=&amp;gt;number
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 인자를 숫자로 받고 결과값으로 숫자를 리턴한다는 의미를 갖는다.&lt;/p&gt;
&lt;pre class=&quot;coffeescript&quot;&gt;&lt;code&gt;
const add:Add=(a,b)=&amp;gt; a+b
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;call signature를 사용하면 a,b가 숫자 타입이라고 명시할 필요가 없다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3.1 Overloading&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오버로딩은 외부 라이브러리에 많이 사용 된다. 패키지나 라이브러리는 오버로딩을 많이 사용하기 때문에 모양 정도는 알아두는게 좋다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;
type Add1=(a:number, b:number)=&amp;gt;number


type Add2={
  (a:number, b:number):number
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 두 타입은 동일한 의미를 갖는다. 아래의 방식이 존재하는 이유는 오버로딩 떄문이다. 오버로딩은 함수가 여러개의 다른 call signature를 가질 때 발생한다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;
type Add={
  (a:number, b:number):number
  (a:number, b:string):number
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 상태가 오버로딩이다. 함수의 타입이 두가지 일 수 있단 걸 의미한다. 이런 상황에서 아래와 같은 함수는 에러가 난다.&lt;/p&gt;
&lt;pre class=&quot;coffeescript&quot;&gt;&lt;code&gt;
const add:Add = (a,b)=&amp;gt;a+b
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파라미터 b가 숫자인지 문자열인지 명시해주지 않았기 때문이다.&lt;/p&gt;
&lt;pre class=&quot;coffeescript&quot;&gt;&lt;code&gt;
 const add:Add = (a,b)=&amp;gt;{
  if(typeof b===&quot;string&quot;) return a;
  return a+b;
 }

&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;실제 Next.js에서 오버로딩이 사용되는 예제를 보자.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;
Router.push({
  path:&quot;/home&quot;,
  state:1
})

Router.push(&quot;/home)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Router.push 함수는 오브젝트, 또는 스트링을 인자로 받을 수 있다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;
type Config = {
  path:string,
  state: object
}

type Push={
  (path:string):void
  (config:Config):void
}

const push:Push = (config) =&amp;gt;{
  if(typeof config===&quot;string&quot;) {
    console.log(config)
  }else{
    console.log(config.path, config.state)
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;call signiture 마다 파라미터의 갯수가 다른 경우도 있다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;
type Add={
  (a:number, b:number):number
  (a:number, b:number, c:number):number
}

const add:Add = (a,b,c) =&amp;gt;{
  return a+b
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼 call signature를 작성하고 나서 위의 함수를 작성하면 오류가 난다. c가 optional 하단 걸 명시해야만 한다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;
const add:Add=(a,b,c?:number)=&amp;gt;{
  if(c) return a+b+c
  return a+b
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3.2 Polymorphism&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;polymorphism 이란 여러 다른 구조물이란 의미다. 어떤 배열이든 받아서 각 요소를 프린트하는 함수를 만들어보자.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;
type SuperPrint = {
  (arr:number[]):void
}

const superPrint:SuperPrint = (arr)=&amp;gt;{
  arr.forEach(i=&amp;gt;console.log(i))
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 함수는 숫자 배열 일때만 작동한다. call signature에 여러 배열 종류를 추가 해줄 수 있지만 너무 비효율적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 지금까지 살펴본 number, string등은 concrete 타입이다. 이번에는 generic 타입을 사용해보자. generic이란 placeholder 같은 타입이다. call signature 에서 그 자리에 들어올 정확한 타입을 모를 때 사용한다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;
type SuperPrint = {
  &amp;lt;Generic&amp;gt;(arr:Generic[]):void
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 맨 앞에 &amp;lt;&amp;gt;안에 generic의 명칭을 쓰고 타입의 자리에 그 명칭을 적으면, 이제 SuperPrint 타입의 함수는 어떤 배열이든지 받아올수 있게 된다. 위 타입을 사용하면 Generic이란 값은 숫자로만 이루어진 배열에는 number 타입으로 변하고, string으로 이루어진 배열에서는 string 타입으로 변한다.&lt;/p&gt;</description>
      <category>개발/타입스크립트</category>
      <category>노마드코더</category>
      <category>타입스크립트</category>
      <author>TTOLBE</author>
      <guid isPermaLink="true">https://nadja09.tistory.com/28</guid>
      <comments>https://nadja09.tistory.com/28#entry28comment</comments>
      <pubDate>Wed, 28 Dec 2022 15:50:26 +0900</pubDate>
    </item>
    <item>
      <title>TypeScript로 블록체인 만들기(1)</title>
      <link>https://nadja09.tistory.com/27</link>
      <description>&lt;h1&gt;Overview of TypeScript&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 노마드 코더의 타입스크립트 무료 강의를 보고 노트 정리를 한 글입니다.&lt;br /&gt;&lt;a href=&quot;https://nomadcoders.co/typescript-for-beginners/lobby&quot;&gt;강의링크&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2.0 How TypeScript Works&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입스크립트는 자바스크립트와 다르게 개발자를 보호해준다. 컴파일 이후에 코드의 에러를 알려주는 자바스크립트와 달리, 타입스크립트는 자바스크립트로 변환되기 전에 에러가 있다면 컴파일 되지 않는다.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;
  const Tollbe={
    nickname:&quot;Tolby&quot;
  };

  Tollbe.hello()
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 코드는 자바스크립트에서는 실행후 에러를 보내지만 타입스크립트에서는 실행되기 전 에러를 알려준다.&lt;/p&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;
  function divide(a,b){
    return a/b
  }

  divide(&quot;hello&quot;)
&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;이러한 에러들은 타입스크립트의 특징인 타입 추론을 통해 생긴다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2.1 Implicit Types vs Explicit Types&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입스크립트에는 타입을 지정해주는 특수한 시스템이 있다. 타입스크립트에서는 모든 변수의 타입이 정해진다. 사용자가 직접 정해주거나, 타입스크립트가 타입 추론을 한다.&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;
  let a=&quot;Hello&quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 타입스크립트는 a 가 string 이라고 생각한다.&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;
  a=&quot;bye&quot;;

  a=10;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 타입스크립트로 작성하면 a 값을 bye로 재지정한 것은 오류가 나지 않지만, 10으로 재지정하면 오류가 난다. 타입 추론으로 a 값의 타입을 string으로 정한 것이다. 이 코드를 자바스크립트로 실행하면 아무런 문제 없이 작동하지만, 오류의 원인이 될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 코드는 사용자가 직접 타입을 정하는 방식이다.&lt;/p&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;
  let b:boolean = false
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 방식이 TypeChecker와 소통하는 법이다. 아래는 배열의 타입을 정하는 방식이다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;
  let c : number[] =[1,2,3]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 쓰면 c는 숫자만으로 구성된 배열이 된다.&lt;/p&gt;
&lt;pre class=&quot;gradle&quot;&gt;&lt;code&gt;
  c.push(&quot;4&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 위와 같은 코드는 오류가 난다. 이는 오브젝트에서도 마찬가지다.&lt;/p&gt;
&lt;pre class=&quot;sqf&quot;&gt;&lt;code&gt;
  const Player={
    name:&quot;Ttolbe&quot;
  }

  Player.name=12
  Player.hello()
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드 역시 오류가 난다. Player.name은 이미 string으로 추론 되었고, Player 안에는 hello 라는 메소드가 존재하지 않기 때문이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2.2 Types of TS part One&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 살펴본 타입스크립트의 기본 타입은 아래와 같다.&lt;/p&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;
  let a:number=1;
  let b:string=&quot;abc;
  let c:boolean=true;

  let d:number[]=[1,2,3];
  let e:string[]=[&quot;a&quot;,&quot;b&quot;,&quot;c&quot;];
  let f:boolean[]=[true,false,false];
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 달리 optional type이 존재 한다. 만약 Player라는 object에 모두 name은 존재하지만 age는 optional일때 어떻게 해야 할까. 이때는 object 안의 type을 지정해주고 age에 물음표를 넣어주면 된다.&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;
  const player:{
    name:string,
    age?:number
    }={
    name:&quot;Ttolbe&quot;,
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 위와 같이 코드 작성 후 아래 함수를 짜면 틀렸다고 나온다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;
  if(player.age&amp;lt;10){

  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;age는 undefined일 수도 있기 때문에, age의 여부를 체크하는 보호장치를 넣어야 한다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;
  if(player.age &amp;amp;&amp;amp; player.age&amp;lt;10){

  }

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 위 Player 같은 오브젝트를 여러개 만들고 싶은데 계속 일일히 type을 지정하기 싫다면 Alias 타입을 생성해 줄수 있다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;
  type PlayerType={
    name:string,
    age?:number
  }

  const PlayerTtol:PlayerType={
    name:&quot;Ttolbe&quot;
  }

  const PlayerLynn:PlayerType={
    name:&quot;Lynn&quot;,
    age:23
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Alias 타입을 선언하면 여러번 재사용 가능하기 떄문에 편하다. (Alias 타입명은 항상 대문자로 시작해야 한다.) Alias 타입은 오브젝트뿐 아니라 모든 형식에 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 역시도 타입을 정할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;
  function playerMaker(name:string){
    return{
      name
    }
  }

  const ttolbe=playerMaker(&quot;ttolbe&quot;)

  ttolbe.age=20
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 ttolbe의 age 항목을 더하려고 하면 수정 되지 않는다. 이미 함수에서 오브젝트의 타입을 정했기 때문이다. 만약 playerMaker가 PlayerType의 오브젝트를 리턴한다고 명시하려면 아래와 같이 수정하면 된다.&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;
  function playerMaker(name:string):PlayerType{
    return{
      name
    }
  }

  const ttolbe=playerMaker(&quot;ttolbe&quot;)

  ttolbe.age=20
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 함수에서는 age 값을 추가할수 있게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 함수의 변수, 함수의 return 값 모두 type을 지정해 줄 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 화살표 함수에서는 아래와 같이 써주면 된다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;
  const playerMaker=(name:string) :PlayerType =&amp;gt;({name})
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2.3 Types of TS part Two&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원하면 type에 readonly 속성을 추가 해줄수도 있다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;
type PlayerType={
  readonly name:string,
  age?:number
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 readonly를 앞에 붙이면 해당 값은 바꿀 수 없다. readonly는 어떤 값이든 추가해 줄수 있다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;
const numbers: readonly number[] = [1,2,3,4]

numbers.push(5)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;numbers는 readonly값이기 떄문에 push하면 에러가 난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 Tuple에 관한 걸 배워보자. Tuple은 array를 생성하는데, 특정 길이를 가졌고, 특정 위치에 특정 값이 있어야 한다. 만약 차례대로 string, number, boolean 값이 있는 길이 3의 array가 필요하다고 해보자.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;
  const player:[string, number, boolean]=[&quot;ttolbe&quot;,20,true]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여타 다른 타입은 아래와 같은 것들이 있다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;
let a:undefined =undefined;

let b:null=null;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 다른 타입은 any 가 있다.&lt;/p&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;
let a:any=1
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;any는 그 어떤 타입도 될 수 있다. 하지만 any를 사용하면 타입스크립트의 보호장치를 잃게 되기 때문에 추천되지 않는다.&lt;/p&gt;
&lt;pre class=&quot;nimrod&quot;&gt;&lt;code&gt;
let a:any=1;

let b:any=true;

a+b
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 타입스크립트에서는 위의 코드가 오류 나지만 여기서는 type을 any로 지정했기 때문에 오류가 나지 않는다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2.4 Types of TS part Three (07:21)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 다루는 type은 타입스크립트 만의 type이다.&lt;/p&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;
let a:unknown;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;unknown은 변수의 타입을 알 수 없을 떄 쓰는 타입이다. 이럴 떈 변수를 사용 전에 변수가 어떠한 타입인지 확인하는 작업을 거쳐야 한다.&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;
let a:unknown;

if(typeof a===&quot;number&quot;){
 let b=a+1;
}
if(typeof a==&quot;string&quot;){
  let b = a.toUpperCase();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;void는 리턴하지 않는 함수를 의미한다.&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;
function hello():void{
  console.log('hello')
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 다룰 타입은 never이다. never는 함수가 절대 리턴하지 않을 때 사용되는 타입이다.&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;
function hello():never{
  console.log('hello')
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;never가 쓰이는 경우는 한가지 더 있다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;
function hello(name:string|number){
  if(typeof name==&quot;string&quot;){

  }else if(typeof name==&quot;number&quot;){

  }else{

  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 함수에서 name은 반드시 string 또는 number이기 때문에 if에서의 name은 string, else if에서의 name은 number, 그리고 else에서의 name은 never타입이 된다.&lt;/p&gt;</description>
      <category>개발/타입스크립트</category>
      <category>노마드코더</category>
      <category>타입스크립트</category>
      <author>TTOLBE</author>
      <guid isPermaLink="true">https://nadja09.tistory.com/27</guid>
      <comments>https://nadja09.tistory.com/27#entry27comment</comments>
      <pubDate>Tue, 27 Dec 2022 15:53:52 +0900</pubDate>
    </item>
    <item>
      <title>Vite 시작해보기</title>
      <link>https://nadja09.tistory.com/25</link>
      <description>&lt;p&gt;요즈음 vite가 많이 뜬다고 한다.&lt;/p&gt;
&lt;p&gt;Vite란 터미널 웹팩으로 일종의 엔진 역할을 한다. Vite는 기존의 react, Vue등을 더빠른 속도로 컴파일 할 수 있게 해주는 장점을 가진다고 해서 한 번 간단하게 사용해 보았다.&lt;/p&gt;
&lt;p&gt;vite를 사용해 보는 방법은 아주 쉽다.&lt;/p&gt;
&lt;p&gt;우선 터미널에 아래와 같이 적자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-npm&quot;&gt;npm create vite@latest&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;그러면 패키지를 설치하라고 뜨는데 y를 누르면 된다.&lt;/p&gt;
&lt;p&gt;그 다음 프로젝트 명을 쓰라고 한뒤 폴더 이름을 설정하면 vanilla, vur, react, preact, lit, svelte 등의 variant를 선택하라고 뜬다. variant를 선택 한 뒤에 타입스크립트 사용여부도 선택할 수 있다. 모두 설정 한 뒤에 터미널에 아래와 같이 적으면 된다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-npm&quot;&gt;cd vite-project

npm run dev&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;npm run dev 명령어를 적고 나면 로컬호스트에 프로젝트가 호스팅된다. 정말 간단하고 리액트 프로젝트 설치 속도도 기존과는 비교도 안되게 빠르다. 기존의 리액트 작성과 차이점은 파일 확장명을 js가 아닌 jsx로 설정하는 것외에는 크게 없다고 볼 수 있다. 또한 vite 프로젝트에 기타 다른 모듈을 설치할 때는 그냥 기존과 똑같이 설치 할 수 있다.&lt;/p&gt;
&lt;p&gt;나도 오늘 처음 배워본 웹팩이니 앞으로 많이 배워가야겠다. 공식 가이드는 아래 링크에서 확인가능하다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://vitejs-kr.github.io/guide/why.html&quot;&gt;Vite 가이드&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ps. Vite의 발음은 비-트이다. &lt;/p&gt;</description>
      <category>개발/기타</category>
      <category>Vite</category>
      <author>TTOLBE</author>
      <guid isPermaLink="true">https://nadja09.tistory.com/25</guid>
      <comments>https://nadja09.tistory.com/25#entry25comment</comments>
      <pubDate>Tue, 19 Apr 2022 13:49:22 +0900</pubDate>
    </item>
    <item>
      <title>Vue Computed/Watch</title>
      <link>https://nadja09.tistory.com/24</link>
      <description>&lt;h1&gt;Vue Computed/Watch&lt;/h1&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Computed&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;computed 를 통해 data 필드를 감지하고 새로운 필드를 정의해서 사용하는 법을 알아보자.&lt;/p&gt;
&lt;p&gt;여기 data안에 firstName과 lsatName이 객체로 저장되어 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;  data() {
    return {
      firstName: &amp;#39;Jane&amp;#39;,
      lastName: &amp;#39;Johnson&amp;#39;,
    };
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 두 객체를 한번에 렌더링 하고 싶으면 아래와 같이 적는 방법이 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h1&amp;gt;Hello {{ firstName }} {{ lastName }}&amp;lt;/h1&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이런 방식도 유효하지만 여러번 작성해야 할 때 번거로울 수 있다.&lt;/p&gt;
&lt;p&gt;우선 메소드를 이용하는 방식이있다. 메소드에 아래 처럼 작성한다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;  methods: {
    fullName() {
       return this.firstName + &amp;#39; &amp;#39; + this.lastName;
    },
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;그리고 template 태그에 fullName 함수를 적용시키자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;    &amp;lt;h1&amp;gt;Hello {{ fullName() }}&amp;lt;/h1&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;실행해보면 두 데이터를 따로 적은 것과 같은 결과를 얻을 수 있다. 하지만 이렇게 하면 매번 렌더링 할때마다 같은 값을 컴퓨터가 계산하게 된다. 그래서 필요한 기능이 computing 이다. computed안의 데이터는 단 한번만 계산하고 계산된 값을 재활용한다.&lt;/p&gt;
&lt;p&gt;computed는 script 태그안에 methods 와 같은 방식으로 선언된다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;script&amp;gt;
export default {
  name: &amp;#39;computedVue&amp;#39;,
  components: {},
  data() {
    return {
    };
  },
  setup() {},
  created() {},
  mounted() {},
  unmouted() {},
  methods: {
  },
  computed: {},
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;computed에 선언 된 값은 data에 선언 된 값과 완전히 동일한 역할을 한다. computed에 아까와 같은 함수를 선언하고 h1 태그에 적용해보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h1&amp;gt;Hello {{ firstName }} {{ lastName }}&amp;lt;/h1&amp;gt;
    &amp;lt;h1&amp;gt;Hello {{ fullName }}&amp;lt;/h1&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
.
.
.
  computed: {
    fullName() {
      return this.firstName + &amp;#39; &amp;#39; + this.lastName;
    },
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;computed 안에 생성된 값은 늘 data에서 받아온 값의 변경여부를 체크한다. input에 firstName과 lastName을 v-model로 넣어 확인해보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; v-model=&amp;quot;firstName&amp;quot; /&amp;gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; v-model=&amp;quot;lastName&amp;quot; /&amp;gt;
    &amp;lt;h1&amp;gt;Hello {{ fullNameComputed }}&amp;lt;/h1&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;실행해보면 input의 값을 변경하는 즉시 computed되어 렌더링 된 값 또한 바로 변하는 것을 확인 가능하다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Watch&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;watch 기능은 computed 기능과 비슷하면서도 다르다.&lt;/p&gt;
&lt;p&gt;한번 methods를 사용해 input을 통해 x와 y를 구해와서 결과 값을 z에 넣는 코드를 짜보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    x:&amp;lt;input type=&amp;quot;text&amp;quot; v-model.number=&amp;quot;x&amp;quot; /&amp;gt; + y:&amp;lt;input
      type=&amp;quot;text&amp;quot;
      v-model.number=&amp;quot;y&amp;quot;
    /&amp;gt;
    &amp;lt;br /&amp;gt;
    &amp;lt;button @click=&amp;quot;addNum&amp;quot;&amp;gt;Click to add&amp;lt;/button&amp;gt;
    &amp;lt;br /&amp;gt;
    result:&amp;lt;input type=&amp;quot;text&amp;quot; v-model.number=&amp;quot;z&amp;quot; /&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
export default {
  name: &amp;#39;watchVue&amp;#39;,
  components: {},
  data() {
    return {
      x: 0,
      y: 0,
      z: 0,
    };
  },
  setup() {},
  created() {},
  mounted() {},
  unmouted() {},
  methods: {
    addNum() {
      this.z = this.x + this.y;
    },
  },
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;참고로 여기서 v-model.number=&amp;quot;&amp;quot; 속성은 값을 Number로 받아옴을 의미한다.&lt;/p&gt;
&lt;p&gt;이번에는 한번 watch를 사용해보저. watch는 computed와 같은 방법으로 선언 할 수 있고, 이미 data에 정의된 객체만 사용가능하다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;  watch: {
    x() {},
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;watch에서는 위에 선언한 x라는 값에 변경 사항이 생기는지 감시한다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    x:&amp;lt;input type=&amp;quot;text&amp;quot; v-model.number=&amp;quot;x&amp;quot; /&amp;gt; + y:&amp;lt;input
      type=&amp;quot;text&amp;quot;
      v-model.number=&amp;quot;y&amp;quot;
    /&amp;gt;
    &amp;lt;br /&amp;gt;
    &amp;lt;button @click=&amp;quot;addNum&amp;quot;&amp;gt;Click to add&amp;lt;/button&amp;gt;
    &amp;lt;br /&amp;gt;
    result:&amp;lt;input type=&amp;quot;text&amp;quot; v-model.number=&amp;quot;z&amp;quot; /&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
export default {
  name: &amp;#39;watchVue&amp;#39;,
  components: {},
  data() {
    return {
      x: 0,
      y: 0,
      z: 0,
    };
  },
  setup() {},
  created() {},
  mounted() {},
  unmouted() {},
  methods: {
    addNum() {
      this.z = this.x + this.y;
    },
  },
  watch: {
    x() {
      this.z = this.x + this.y;
    },
    y() {
      this.z = this.x + this.y;
    },
  },
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이렇게 코딩하면 z 값은 x, 또는 y 값이 바뀔때마다 버튼을 누르지 않아도 자동으로 업데이트 된다.&lt;/p&gt;
&lt;p&gt;watch는 자동적으로 업데이트 해주기 때문에 굉장히 편리하지만 많은 자원을 소모하는 기능이다. watch 기능은 반드시 필요한 경우에만 사용하는 것이 좋다.&lt;/p&gt;</description>
      <category>개발/Vue</category>
      <category>VUE</category>
      <author>TTOLBE</author>
      <guid isPermaLink="true">https://nadja09.tistory.com/24</guid>
      <comments>https://nadja09.tistory.com/24#entry24comment</comments>
      <pubDate>Sun, 17 Apr 2022 21:29:28 +0900</pubDate>
    </item>
    <item>
      <title>Vue 이벤트 처리하기 - click/change/key</title>
      <link>https://nadja09.tistory.com/23</link>
      <description>&lt;h1&gt;Vue 이벤트 처리하기 - click/change/key&lt;/h1&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Click 이벤트&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Vue 에서 가장 많이 보게 될 click 이벤트 처리법을 먼저 살펴보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;button&amp;gt;Add 1&amp;lt;/button&amp;gt;
    &amp;lt;p&amp;gt;The count is {{ count }}&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
export default {
  name: &amp;#39;eventVue&amp;#39;,
  components: {},
  data() {
    return {
      count: 0,
    };
  },
  setup() {},
  created() {},
  mounted() {},
  unmouted() {},
  methods: {},
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이제 버튼을 누를 때마다 값이 1씩 증가하게 만들어 보자.&lt;/p&gt;
&lt;p&gt;Vue에서는 이벤트를 추가할때 v-on 속성을 사용한다. 여기서는 클릭 이벤트를 사용하므로 v-on:click=&amp;quot;&amp;quot; 속성을 사용하고 큰 따옴표 안에 함수를 넣어주면 된다.&lt;/p&gt;
&lt;p&gt;(v-on:click=&amp;quot;&amp;quot;은 @click=&amp;quot;&amp;quot;으로 줄여쓸 수 있다.)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;    &amp;lt;button v-on:click=&amp;quot;increaseCounter&amp;quot;&amp;gt;Add 1&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이벤트에 사용되는 함수는 script 태그안의 methods:{} 안에 넣어주면 된다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;script&amp;gt;
export default {
  name: &amp;#39;eventVue&amp;#39;,
  components: {},
  data() {
    return {
      count: 0,
    };
  },
  setup() {},
  created() {},
  mounted() {},
  unmouted() {},
  methods: {
    increaseCount() {
      this.count++;
    },
  },
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;전에 말했듯 메소드의 함수가 data에 접근하기 위해서는 this.을 사용해야 한다.&lt;/p&gt;
&lt;p&gt;위처럼 함수를 넣고 클릭하면 화면에 렌더링 된 count의 값이 버튼을 클릭할 때마다 1씩 더해지는 모습을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;이벤트 메소드는 한 엘레먼트에 여러개를 바인딩 할 수도 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;button v-on:click=&amp;quot;increaseCount(), alertCount()&amp;quot;&amp;gt;Add 1&amp;lt;/button&amp;gt;
    &amp;lt;p&amp;gt;The count is {{ count }}&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
.
.
.
  methods: {
    increaseCount() {
      this.count++;
    },
    alertCount() {
      alert(this.count);
    },
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위 와 같이 코드를 적고 실행해보면 버튼을 클릭 할때 마다 숫자가 더해지고, alert 창에 count가 메세지로 표시 되는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Change 이벤트&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이번에는 select 태그를 사용한 change 이벤트를 배워보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;select v-model=&amp;quot;flavours.name&amp;quot; @change=&amp;quot;changeFlavour()&amp;quot;&amp;gt;
      &amp;lt;option v-for=&amp;quot;(falvour, i) in flavours&amp;quot; :value=&amp;quot;falvour.name&amp;quot; :key=&amp;quot;i&amp;quot;&amp;gt;
        {{ falvour.name }}
      &amp;lt;/option&amp;gt;
    &amp;lt;/select&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
.
.
.
data() {
    return {
      count: 0,
      flavours: [
        { name: &amp;#39;Chocolate&amp;#39; },
        { name: &amp;#39;Vanilla&amp;#39; },
        { name: &amp;#39;Strawberry&amp;#39; },
      ],
    };
  },
.
.
.
  methods: {
    changeFlavour() {
      alert(this.flavours.name);
    },
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;실행하면 옵션을 바꿀때 마다 changeFlavour 함수가 실행 되면서 alert 창에 선택한 flavour.name의 값이 출력 된다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Key 이벤트&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이번에는 key 이벤트를 살펴보자.&lt;/p&gt;
&lt;p&gt;우선 input 태그를 생성 뒤 v-model로 textValue라는 값과 바인딩 해보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;    &amp;lt;input type=&amp;quot;text&amp;quot; v-model=&amp;quot;textValue&amp;quot; /&amp;gt;
.
.
.
 data() {
    return {
      textValue: &amp;#39;&amp;#39;,
    };
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;key와 관련된 이벤트에는 keypress, keyup, keydown이 있는데 일단 keyup을 사용해보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;    &amp;lt;input type=&amp;quot;text&amp;quot; v-model=&amp;quot;textValue&amp;quot; @keyup.enter=&amp;quot;alertInput&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;@keyup.enter는 엔터키를 누르고 뗐을 때의 이벤트를 의미한다. 이는 키보드의 다른 자판의 값으로도 변경할수 있다.(ex. @keyup.k=&amp;quot;&amp;quot;라고 작성하면 k키가 눌렸다가 떼질 때마다 함수가 실행된고, 만약 @keyup=&amp;quot;&amp;quot;이라고 작성하면 아무 키를 눌렀다가 떼도 함수가 실행된다. 이벤트 처리시에 자주 사용되는 키값에는 tab, delete, esc, space, up, down, left, right 등이 있다.)&lt;/p&gt;
&lt;p&gt;메소드에 엔터키를 누르면 실행될 함수를 넣어주자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;    alertInput() {
      alert(this.textValue);
    },&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;엔터키를 떼는 이벤트가 일어날 때마다 alert에 textValue 값이 표시 된다.&lt;/p&gt;</description>
      <category>개발/Vue</category>
      <category>VUE</category>
      <author>TTOLBE</author>
      <guid isPermaLink="true">https://nadja09.tistory.com/23</guid>
      <comments>https://nadja09.tistory.com/23#entry23comment</comments>
      <pubDate>Sun, 17 Apr 2022 19:20:59 +0900</pubDate>
    </item>
    <item>
      <title>Vue 렌더링</title>
      <link>https://nadja09.tistory.com/22</link>
      <description>&lt;h1&gt;Vue 렌더링&lt;/h1&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;리스트 렌더링&lt;/h2&gt;
&lt;p&gt;select와 option태그, 그리고 배열로 이루어진 객체 데이터를 통해 리스트 렌더링을 하는 방법을 알아보자.&lt;/p&gt;
&lt;p&gt;우선 data에 아래와 같이 값을 부여하자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;  data() {
    return {
      options: [
        { v: &amp;#39;02&amp;#39;, t: &amp;#39;서울&amp;#39; },
        { v: &amp;#39;21&amp;#39;, t: &amp;#39;부산&amp;#39; },
        { v: &amp;#39;064&amp;#39;, t: &amp;#39;제주&amp;#39; },
      ],
    };
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이제 tempalte 태그 안에 아래 와 같이 적자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;select&amp;gt;
      &amp;lt;option v-for=&amp;quot;(city, i) in options&amp;quot; v-bind:value=&amp;quot;city.v&amp;quot; v-bind:key=&amp;quot;i&amp;quot;&amp;gt;
        {{i}}-{{ city.t }}
      &amp;lt;/option&amp;gt;
    &amp;lt;/select&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위 코드를 실행하면 0-서울, 1-부산, 3-제주의 세 옵션들이 생성 된 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;v-for 속성의 기본 구조는 v-for=&amp;quot;(item, index) in items&amp;quot; 형태로 items라는 원본 데이터 배열의 각 엘리먼트를 item 으로 받아오는 일을 한다. 이는 아래의 JavaScript의map 함수와도 유사하다고 할수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;items.map((item,index)=&amp;gt;{})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;또한 v-for 태그와 함께 쓰여야 하는 것은 key 값이다. 이는 v-bind:key=&amp;quot;&amp;quot; 속성으로 부여한다.(이는 :key=&amp;quot;&amp;quot; 로도 적을 수 있다.)각 리스트의 key 값은 그 리스트 안에서 고유한 값을 지녀야 한다.&lt;/p&gt;
&lt;p&gt;결국 위 코드는 options 배열의 모든 엘레먼트를 순서대로 가져와 option 태그에 넣는다는 의미 이다.&lt;/p&gt;
&lt;p&gt;이번에는 select 태그에 value를 부여해보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;div&amp;gt;
    &amp;lt;select v-model=&amp;quot;jeju&amp;quot;&amp;gt;
      &amp;lt;option v-for=&amp;quot;(city, i) in options&amp;quot; v-bind:value=&amp;quot;city.v&amp;quot; v-bind:key=&amp;quot;i&amp;quot;&amp;gt;
        {{ i }}-{{ city.t }}
      &amp;lt;/option&amp;gt;
    &amp;lt;/select&amp;gt;
  &amp;lt;/div&amp;gt;
  .
  .
  .
    data() {
    return {
      options: [
        { v: &amp;#39;02&amp;#39;, t: &amp;#39;서울&amp;#39; },
        { v: &amp;#39;21&amp;#39;, t: &amp;#39;부산&amp;#39; },
        { v: &amp;#39;064&amp;#39;, t: &amp;#39;제주&amp;#39; },
      ],
      jeju: &amp;#39;064&amp;#39;,
    };
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;실행시 select의 기본값이 2-제주가 되는 것을 볼수 있다.&lt;/p&gt;
&lt;p&gt;이번에는 table 태그를 사용해서 리스트 렌더링을 해보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;table&amp;gt;
      &amp;lt;thead&amp;gt;
        &amp;lt;tr&amp;gt;
          &amp;lt;th&amp;gt;제품명&amp;lt;/th&amp;gt;
          &amp;lt;th&amp;gt;제품가격&amp;lt;/th&amp;gt;
          &amp;lt;th&amp;gt;배송비&amp;lt;/th&amp;gt;
          &amp;lt;th&amp;gt;카테고리&amp;lt;/th&amp;gt;
        &amp;lt;/tr&amp;gt;
      &amp;lt;/thead&amp;gt;
    &amp;lt;/table&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
.
.
.
  data() {
    return {
      productList: [
        {
          name: &amp;#39;electronic keyboard&amp;#39;,
          price: 20000,
          delivery: 5000,
          category: &amp;#39;electronics&amp;#39;,
        },
        {
          name: &amp;#39;vertical mouse&amp;#39;,
          price: 40000,
          delivery: 2000,
          category: &amp;#39;electronics&amp;#39;,
        },
        {
         name: &amp;#39;china vase&amp;#39;,
         price: 10000,
         delivery: 2500,
         category: &amp;#39;floral vase&amp;#39; },
      ],
    };
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;테이블 태그안에서 반복 되는 것은 tr태그이므로 우선 tr 태그를 아래와 같이 설정해주자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;        &amp;lt;tr v-for=&amp;quot;(product, i) in productList&amp;quot; :key=&amp;quot;i&amp;quot;&amp;gt;&amp;lt;/tr&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;그 안에는 td 태그가 들어가야한다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;        &amp;lt;tr v-for=&amp;quot;(product, i) in productList&amp;quot; :key=&amp;quot;i&amp;quot;&amp;gt;
          &amp;lt;td&amp;gt;{{ product.name }}&amp;lt;/td&amp;gt;
          &amp;lt;td&amp;gt;{{ product.price }}&amp;lt;/td&amp;gt;
          &amp;lt;td&amp;gt;{{ product.delivery }}&amp;lt;/td&amp;gt;
          &amp;lt;td&amp;gt;{{ product.category }}&amp;lt;/td&amp;gt;
        &amp;lt;/tr&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위와 같이 설정해준뒤 실행해보면 각 칸에 잘 들어 가 있는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;렌더링 문법&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;vue에서의 다른 렌더링 문법에는 v-if 와 v-show 가 있다.&lt;/p&gt;
&lt;p&gt;위에서 v-for를 살펴봤으니 이제는 v-if를 이용해보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h1 v-if=&amp;quot;h1Render&amp;quot;&amp;gt;if h1Render is true, this sentence appears&amp;lt;/h1&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
export default {
  name: &amp;#39;rendingGrammer&amp;#39;,
  components: {},
  data() {
    return {
      h1Render: true,
    };
  },
  setup() {},
  created() {},
  mounted() {},
  unmouted() {},
  methods: {},
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;h1Render객체의 값이 true 이니, 화면에는 h1 태그가 보인다. 하지만 h1Render를 false로 설정하면 h1 태그는 더 이상 렌더링 되지 않는다.&lt;/p&gt;
&lt;p&gt;vue 에서는 if뿐 만아니라 else 값도 설정 가능하다. 이는 v-else라는 속성으로 부여 할 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h1 v-if=&amp;quot;h1Render&amp;quot;&amp;gt;if h1Render is true, this sentence appears&amp;lt;/h1&amp;gt;
    &amp;lt;h1 v-else&amp;gt;if h1Render is false, this sentence appears&amp;lt;/h1&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위 코드를 실행하면 h1Render의 값이 true일때는 위의 문장이 나타나고, false이면 아래의 문장이 나타난다.&lt;/p&gt;
&lt;p&gt;vue에서는 else if 문 역시 사용 가능하다. 이는 v-else-if=&amp;quot;&amp;quot; 속성으로 사용가능하다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h1 v-if=&amp;quot;type === &amp;#39;a&amp;#39;&amp;quot;&amp;gt;type is a&amp;lt;/h1&amp;gt;
    &amp;lt;h1 v-else-if=&amp;quot;type === &amp;#39;b&amp;#39;&amp;quot;&amp;gt;type is b&amp;lt;/h1&amp;gt;
    &amp;lt;h1 v-else&amp;gt;type is other&amp;lt;/h1&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
.
.
.
  data() {
    return {
      type: &amp;#39;a&amp;#39;,
    };
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;type 값을 a로 바꾸면 첫번째 문장이, b로 바꾸면 두번째 문장이, 그리고 a나 b가 아닌 다른 값으로 바꾸면 마지막 문장이 나온다.&lt;/p&gt;
&lt;p&gt;이번에는 v-show속성을 사용해 보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;    &amp;lt;p v-show=&amp;quot;pRender&amp;quot;&amp;gt;pRender is true&amp;lt;/p&amp;gt;
    .
    .
    .
    data() {
        return {
            pRender: true,
    };
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 역시 위에서 boolean 값을 사용한 v-if 속성과 같이, pRender가 true면 렌더링 되고, false면 렌더링 되지 않는다.&lt;/p&gt;
&lt;p&gt;v-if 와 v-show는 굉장히 유사해 보이나 둘이 렌더링 방법에서 차이가 있다.&lt;/p&gt;
&lt;p&gt;v-if는 조건을 만족한 순간에 html블럭이 생성되고, 조건을 만족하지 않으면 html블럭이 삭제된다. 하지만 v-show는 렌더링은 하지만 해당 엘레먼트에 style= &amp;quot;display : none&amp;quot; 속성을 준다. 직접 실행해보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h1 v-if=&amp;quot;h1Render&amp;quot;&amp;gt;h1Render is true&amp;lt;/h1&amp;gt;
    &amp;lt;p v-show=&amp;quot;pRender&amp;quot;&amp;gt;pRender is true&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
.
.
.
  data() {
    return {
      h1Render: true,
      pRender: true,
    };
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 상태에서 개발자 모드의 elements 탭을보면 아레와 같이 렌더링 된 모습을 볼 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;h1&amp;gt;h1Render is true&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;pRender is true&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이번에는 h1Render, pRender 모두 false 값을 부여하고 실행해보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;!--v-if--&amp;gt;
&amp;lt;p style=&amp;quot;display: none;&amp;quot;&amp;gt;pRender is true&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;element 탭을 확인하면 위와 같이 렌더링 됨을 확인 할 수 있다.&lt;/p&gt;
&lt;p&gt;만약 해당 엘레먼트가 한번 바뀌고 마는 요소라면 v-if를, 자주 변경되는 요소라면 v-show를 쓰는 것이 더 경제적이라고 할 수 있다.&lt;/p&gt;</description>
      <category>개발/Vue</category>
      <category>VUE</category>
      <author>TTOLBE</author>
      <guid isPermaLink="true">https://nadja09.tistory.com/22</guid>
      <comments>https://nadja09.tistory.com/22#entry22comment</comments>
      <pubDate>Sun, 17 Apr 2022 18:18:26 +0900</pubDate>
    </item>
    <item>
      <title>Vue 데이터 바인딩-attribute/class/style</title>
      <link>https://nadja09.tistory.com/21</link>
      <description>&lt;h1&gt;Vue 데이터 바인딩-attribute/class/style&lt;/h1&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;속성 데이터 바인딩&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이미지의 src를 바인딩 해봄으로서 속성 바인딩 방법을 알아보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;img src=&amp;quot;img/bee.png&amp;quot; /&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;프로젝트의 public 폴더에 img 폴더를 생성한 뒤 파일을 넣고 위와 같이 template안에 img 태그에 속성을 부여해주면 실행 시 이미지를 볼 수 있다.&lt;/p&gt;
&lt;p&gt;데이터의 return 값에 src 객체를 넣어서 src속성을 바인딩해보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;img v-bind:src=&amp;quot;bee&amp;quot; /&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
export default {
  name: &amp;#39;attrBinding&amp;#39;,
  components: {},
  data() {
    return {
      bee: &amp;#39;img/bee.png&amp;#39;,
    };
  },
  setup() {},
  created() {},
  mounted() {},
  unmouted() {},
  methods: {},
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이번에는 input 값이 비었을 때 버튼을 disabled 시키는 방법에 대해 알아보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;    &amp;lt;input type=&amp;quot;text&amp;quot; v-model=&amp;quot;textValue&amp;quot; /&amp;gt;
    &amp;lt;button type=&amp;quot;button&amp;quot; v-bind:disabled=&amp;quot;textValue === &amp;#39;&amp;#39;&amp;quot;&amp;gt;Click&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;로직은 간단하다. 받아온 textValue값이 비었다면 버튼은 활성화 되지 않는다.&lt;/p&gt;
&lt;p&gt;만약 v-bind:disabled=true 이면 버튼은 비활성화되고 v-bind:disabled=false 이면 버튼은 활성화된다.&lt;/p&gt;
&lt;p&gt;데이터의 return에 아래와 같이 textValue객체를 추가해주자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;      textValue: &amp;#39;&amp;#39;,&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;프로그램을 실행시키면 처음에는 버튼이 비활성화 되었다가 입력을 하면 버튼이 활성화 되는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;class에 데이터 바인딩&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;아래와 같이 코딩을 짜보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;Class Binding&amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
export default {
  name: &amp;#39;classBinding&amp;#39;,
  components: {},
  data() {
    return {};
  },
  setup() {},
  created() {},
  mounted() {},
  unmouted() {},
  methods: {},
};
&amp;lt;/script&amp;gt;
&amp;lt;style scoped&amp;gt;
.container {
  width: 100%;
  border: 1px dotted blue;
}

.active {
  border: 1px solid red;
  background: pink;
  font-weight: bold;
}

.text-red {
  color: red;
}
&amp;lt;/style&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;class 바인딩을 위해서는 v-bind:class=&amp;quot;&amp;quot; 라는 속성을 사용한다.&lt;/p&gt;
&lt;p&gt;v-bind:class는 기존에 가진 class에 바인딩된 클래스를 추가하는 속성이다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div class=&amp;quot;container&amp;quot; v-bind:class=&amp;quot;{ active: isActive, &amp;#39;text-red&amp;#39;: isRed }&amp;quot;&amp;gt;
    Class Binding
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
.
.
.
data() {
    return {
      isActive: true,
      isRed: false,
    };
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위 코드를 실행해보면 isActive 라는 클래스는 적용 되지만 isRed 라는 클래스는 적용 되지 않은 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;클래스를 바인딩하는 또 다른 방법은 배열로 바인딩하는 것이다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;&amp;lt;template&amp;gt;
  &amp;lt;div class=&amp;quot;container&amp;quot; v-bind:class=&amp;quot;[activeClass, redText]&amp;quot;&amp;gt;
    Class Binding
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
export default {
  name: &amp;#39;classBinding&amp;#39;,
  components: {},
  data() {
    return {
      activeClass: &amp;#39;active&amp;#39;,
      redClass: &amp;#39;text-red&amp;#39;,
    };
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이번에는 인라인 스타일을 활용한 스타일 바인딩을 배워보자. 스타일 바인딩을 할 때는 v-bind:style=&amp;quot;&amp;quot;속성을 이용한다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;    &amp;lt;div v-bind:style=&amp;quot;styleObject&amp;quot;&amp;gt;Style object&amp;lt;/div&amp;gt;
    .
    .
    .
     data() {
    return {
      styleObject: {
        backgroundColor: &amp;#39;yellow&amp;#39;,
        color: &amp;#39;green&amp;#39;,
      },
    };&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;실행시 노란 바탕에 초록 글씨가 생기는 모습을 볼 수 있다. 인라인 스타일 역시도 객체 형태가 아닌 배열 형태로 사용 할 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;    &amp;lt;div v-bind:style=&amp;quot;[greenBorder, width100px]&amp;quot;&amp;gt;Style object&amp;lt;/div&amp;gt;
.
.
.
 data() {
    return {
      greenBorder: &amp;#39;border: 1px solid green&amp;#39;,
      width100px: &amp;#39;width: 100px; height:100px;&amp;#39;,
    };
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;실행시 greenBorder의 스타일과 width100px의 스타일 모두 적용된다.&lt;/p&gt;</description>
      <category>개발/Vue</category>
      <category>VUE</category>
      <author>TTOLBE</author>
      <guid isPermaLink="true">https://nadja09.tistory.com/21</guid>
      <comments>https://nadja09.tistory.com/21#entry21comment</comments>
      <pubDate>Sat, 16 Apr 2022 17:27:05 +0900</pubDate>
    </item>
  </channel>
</rss>