<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>smart.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Thu, 05 Dec 2024 01:49:45 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>smart.log</title>
            <url>https://velog.velcdn.com/images/ctr_nike/profile/0bb57d19-df0e-40b8-b3ef-8a6b6be626ff/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. smart.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ctr_nike" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[타임 카운트다운 구현 ]]></title>
            <link>https://velog.io/@ctr_nike/%ED%83%80%EC%9E%84-%EC%B9%B4%EC%9A%B4%ED%8A%B8%EB%8B%A4%EC%9A%B4-%EA%B5%AC%ED%98%84-2plstbso</link>
            <guid>https://velog.io/@ctr_nike/%ED%83%80%EC%9E%84-%EC%B9%B4%EC%9A%B4%ED%8A%B8%EB%8B%A4%EC%9A%B4-%EA%B5%AC%ED%98%84-2plstbso</guid>
            <pubDate>Thu, 05 Dec 2024 01:49:45 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>목표</p>
</blockquote>
<ol>
<li>실무에서 자주 사용된다 생각하는것들을 구현한다.</li>
<li>외부의 도움없이, 특히 구조를 짜는 부분에 있어서는 무조건 스스로의 힘으로 생각한다. </li>
</ol>
<blockquote>
<p>코드</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/2c1aff3f-a78c-461d-b8c0-8ed7410b17f0/image.png" alt=""></p>
<blockquote>
<p>레포지토리</p>
</blockquote>
<p><a href="https://github.com/neptune588/source_code_REACT/blob/main/src/pages/TimeCountdown/index.jsx">https://github.com/neptune588/source_code_REACT/blob/main/src/pages/TimeCountdown/index.jsx</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[달력 구현]]></title>
            <link>https://velog.io/@ctr_nike/%EB%8B%AC%EB%A0%A5-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@ctr_nike/%EB%8B%AC%EB%A0%A5-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Thu, 05 Dec 2024 01:42:57 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>목표</p>
</blockquote>
<ol>
<li>실무에서 자주 사용된다 생각하는것들을 구현한다.</li>
<li>외부의 도움없이, 특히 구조를 짜는 부분에 있어서는 무조건 스스로의 힘으로 생각한다. </li>
</ol>
<blockquote>
<p>코드</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/32e004cf-83bf-4c41-9a8d-762d93df3e27/image.png" alt=""></p>
<blockquote>
<p>레포지토리</p>
</blockquote>
<p><a href="https://github.com/neptune588/source_code_REACT/blob/main/src/pages/Calander/index.jsx">https://github.com/neptune588/source_code_REACT/blob/main/src/pages/Calander/index.jsx</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[typescript 기초 정리 - 4]]></title>
            <link>https://velog.io/@ctr_nike/typescript-%EA%B8%B0%EC%B4%88-%EC%A0%95%EB%A6%AC-4</link>
            <guid>https://velog.io/@ctr_nike/typescript-%EA%B8%B0%EC%B4%88-%EC%A0%95%EB%A6%AC-4</guid>
            <pubDate>Wed, 08 May 2024 16:59:46 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>타입스크립트 문법 정리</p>
</blockquote>
<p><strong>1) any와 unknown타입의 차이점은?</strong></p>
<p>일단 any를 사용할빠에는 unknown을 사용하는게 맞다고 기억해두자.</p>
<ul>
<li>any</li>
</ul>
<p>타입에 any를 선언할경우 그 이후로 타입스크립트가 타입 검사를 포기해버린다.
타입스크립트를 쓰는 의미가 없어짐.</p>
<ul>
<li>unknown</li>
</ul>
<p>unknown을 쓰게되면 타입검사는 한다. as를 이용해 unknown타입을 다른 타입으로 바꿔줘야 한다.</p>
<p><strong>그러면 언제 쓰는거지? -&gt; 내가 지금 당장 타입을 정확하게 모르겠을때 사용한다.</strong></p>
<pre><code>try {

} catch(error) {

}

catch(error &lt;&lt; ts에서 이 부분이 unknwon타입으로 내장된다.)
에러같은 경우 어떤 타입이 올지 모르기 때문에
(Axios사용하면 AxiosError가 발생할수도 있고..) 확인 후 as로 타입 지정을 한다.

(error as Error)...
(error as AxiosError)...</code></pre><blockquote>
<ol>
<li>any는 안쓰는게 best</li>
<li>unknwon도 안쓰는게 best</li>
<li>하지만 쓰게 된다면 as로 타입지정을 직접 해줘야 한다.</li>
<li>처음부터 <strong>타입 지정</strong>을 정확하게 해줘야 나중에 as로 변환시키고, 줄줄이 꼬여버리는 일을 방지할수 있다.</li>
<li>타입이 unknown일때 or 남이 만든 코드의 타입이 틀렸을때 빼고는 <strong>as</strong>도 <strong>지양해야한다</strong>.</li>
</ol>
</blockquote>
<ul>
<li>타입스크립트 에러 체크 꿀팁</li>
</ul>
<p>여러줄일 경우 가장 마지막 문장을 확인하면 대략적으로 알수있다.</p>
<p><strong>2) 타입가드 (타입 좁히기)</strong></p>
<p>타입가드란? 예를들면 함수의 매개변수에 여러가지 타입이 오는 경우에 사용한다.</p>
<pre><code>function numOrStr (a: number | string) {
    if(typeof a === &quot;number&quot;) {
        숫자일때 가능한 작업...
    } else {
        문자열일때 가능한 작업...
    }
}</code></pre><p><strong>원시값</strong>인 경우엔 if문과 typeof를 이용해 매개변수의 타입을 걸러주고 각자 타입에 맞는
작업을 해준다.</p>
<pre><code>function numOrArrOrStr (a: number | number[] | string) {
    if(typeof a === &quot;number&quot;) {
        숫자일때 가능한 작업...
    } else if(Array.isArray(a)){
        배열일때 가능한 작업...
    } else {
        문자열일때 가능한 작업...
    }
}</code></pre><p><strong>배열</strong>인 경우엔 isArray를 이용해 타입 걸러서 작업해준다.</p>
<pre><code>type A = {type: &quot;a&quot;, a:string}
type B = {type: &quot;b&quot;, b:string}
type C = {type: &quot;c&quot;, c:string}

1) value로 구별하는 방법

function objInspect (a: A | B | C) {
    if(a.type === &quot;a&quot;) {
        type이 &quot;a&quot;일때 가능한 작업...
    } else if((a.type === &quot;b&quot;)){
        type이 &quot;b&quot;일때 가능한 작업...
    } else {
        type이 &quot;c&quot;일때 가능한 작업...
    }
}


2) 예외사항 알아두기

type A = {type: &quot;a&quot;, a:string}
type B = {type: &quot;c&quot;, b:string}
type C = {type: &quot;c&quot;, c:string}

function objInspect (a: A | B | C) {
    if(a.type === &quot;a&quot;) {
        type이 &quot;a&quot;일때 가능한 작업...
    } else if(a.type === &quot;c&quot;){
        type이 &quot;c&quot;일때 가능한 작업...
    } else {
        --&gt; 이 경우 타입이 never뜸 else에 더 이상의 타입이 존재할수 없으니까..
    }
}

3) key를 이용하여 구별하는 방법
type A = {type: &quot;a&quot;, a:string}
type B = {type: &quot;c&quot;, b:string}
type C = {type: &quot;c&quot;, c:string}

function objInspect (a: A | B | C) {
    if(&quot;a&quot; in a) {
        type이 &quot;a&quot;일때 가능한 작업...
    } else if(&quot;b&quot; in a){
        type이 &quot;c&quot;일때 가능한 작업...
    } else {
        --&gt; 이 경우 타입이 never뜸 else에 더 이상의 타입이 존재할수 없으니까..
    }
}

in을 통해 key를 검사해서 타입 가드를 한다.</code></pre><p><strong>객체</strong>인 경우엔 위와 같이 key or value를 이용해 타입을 걸러서 작업해준다.
key의 경우에는 in문법을 이용해 검사한다.</p>
<ul>
<li><p><strong>따라서 타입스크립트를 이용하면서 객체로 무언가를 만들때는 항상 type이라는 속성을 만들어두는게 좋다.</strong></p>
</li>
<li><p><strong>만약 type 속성이 없어서 구별이 힘든경우, 빠르게 객체안에 구별되는 key를 찾아서 in문법으로 타입을 구별해준다.</strong></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[typescript 기초 정리 - 3]]></title>
            <link>https://velog.io/@ctr_nike/typescript-%EA%B8%B0%EC%B4%88-%EC%A0%95%EB%A6%AC-3</link>
            <guid>https://velog.io/@ctr_nike/typescript-%EA%B8%B0%EC%B4%88-%EC%A0%95%EB%A6%AC-3</guid>
            <pubDate>Wed, 08 May 2024 14:52:36 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>타입스크립트 문법 정리</p>
</blockquote>
<p><strong>1) 넓은타입 &amp; 좁은타입</strong></p>
<p>좁 -&gt; 넓 타입 대입은 되지만 
넓 -&gt; 좁 타입 대입은 안된다.</p>
<pre><code>type A = {a:string}
type B = {b:number}
type AB = A | B
type C = A &amp; B

const c:C = {a:&quot;a&quot;, b:2}
const ab:AB = {a:&quot;a&quot;}

const ab:AB = c 가능(O) 좁은타입 -&gt; 넓은타입
const c:C = ab 불가능(X) 넓은타입 -&gt; 좁은타입

const c2:C = {a:&quot;a&quot;, b:2, //c:&quot;c&quot;} 좁은 타입(C) -&gt; 넓은 타입 대입(C &amp; {c:&quot;c&quot;}) 
c:&quot;c&quot; 부분에서 에러가 뜸 잉여 속성검사라는것이 발동.

이런 경우는 객체 리터럴을 다른 변수에 할당하고 그 변수를 c2에 할당하면 
해결된다.

const c3 = {a:&quot;a&quot;, b:2,c:&quot;c&quot;}
const c2 = c3</code></pre><blockquote>
<p>1) A와 AB를 비교했을때 AB가 or이므로 범위가 더 넓어지므로
A -&gt; AB 타입 대입이 가능하다.
2) A와 C를 비교했을때 C는 A와B타입이 모두 존재해야하는 타입이므로 
A -&gt; C 타입 대입이 불가능하다.
3) AB와 C를 비교했을때 AB가 C보다 넓은 타입이므로
C -&gt; AB 타입 대입이 가능하다.
4) 다만 좁은 타입 -&gt; 넓은 타입에 대입했을시 객체 리터럴일 경우, 객체 리터럴을 변수에 직접 할당하면 잉여 속성검사라는것이 발동된다.</p>
</blockquote>
<ul>
<li><strong>알아두면 좋은 팁</strong>
객체 리터럴에서 객체가 상세할수록 좁은 타입이다.</li>
</ul>
<p><strong>2) void의 여러가지 사용법</strong></p>
<pre><code>fucntion a ():void {}

interface Magician {fire: () =&gt; void}
const magician:Magician = {fire(){return &quot;불꽃마법&quot;}}

function c (arr:number[],callback: (num:number)=&gt;void){}</code></pre><ul>
<li>1) 함수의 리턴타입이 void인 경우는? </li>
</ul>
<p><strong>return값이 undefined</strong>인 경우에 해당.</p>
<ul>
<li>2) 객체의 메서드의 리턴타입이 void인 경우는?</li>
</ul>
<p>여기서는 일반 함수와는 다르게 <strong>리턴값을 사용 안한다</strong>는 의미로 리턴 타입을
<strong>void로 표기해둔다고 한다.</strong></p>
<ul>
<li>3) 매개변수안에 들어오는 콜백함수의 리턴타입이 void인 경우는?</li>
</ul>
<p>여기서도 마찬가지로 일반 함수와는 다르게  <strong>리턴값을 사용 안한다</strong>는 의미로 리턴 타입을
<strong>void로 표기해둔다고 한다.</strong></p>
<p>정리하면 1번의 경우를 제외하곤 리턴타입이 void인 경우 해당 타입과 타입이 달라도 (number,string...등) 오류로 취급하지 않는다. 해당 리턴값을 사용하지 않겠다 or 리턴값을 상관하지 않겠다는 의미로 취급되기 때문, <strong>결국 정리하면 void로 타입표기는 해둔 경우 리턴값이 필요없는 경우에 사용하면 되겠다.</strong></p>
<p>그리고 undifined와 void는 다르다. </p>
<p>*<em>3) declare *</em></p>
<p>declare란 TypeScript로 작성하지 않은 코드의 <strong>타입 정보</strong>를 컴파일러에게 알려주는 선언이다.
컴파일 단계에서 사라짐. === declare가 붙은 코드들은 JS로 컴파일 되지 않는다.
외부에서 만들어진 코드에 타입을 선언할때 유용하다.</p>
<pre><code>declare function a (타입...):타입
declare 변수:타입</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[typescript 기초 정리 - 2]]></title>
            <link>https://velog.io/@ctr_nike/typescript-%EA%B8%B0%EC%B4%88-%EC%A0%95%EB%A6%AC-2</link>
            <guid>https://velog.io/@ctr_nike/typescript-%EA%B8%B0%EC%B4%88-%EC%A0%95%EB%A6%AC-2</guid>
            <pubDate>Fri, 03 May 2024 15:02:09 GMT</pubDate>
            <description><![CDATA[<p>타입 스크립트를 배우면서 </p>
<p>뭔가 문법은 방대(주관적 기준)한데, 이걸 도대체 어디서 활용하지? 라는 의문점만 강하게 생긴다.</p>
<p>그래서 배우는게 더 어려운것같기도하고.. </p>
<blockquote>
<p>타입스크립트 문법 정리</p>
</blockquote>
<p><strong>1) enum 타입</strong></p>
<p>뭔가를 열거할때 쓰는 타입,</p>
<pre><code>enum Direction {
    Up,
    Down,
    Left,
    Right,
}</code></pre><p>제일 위를 기준으로 0부터 오름차순으로 값이 할당된다. 근데 이걸 도대체 어디서 쓰는건지..
감이 안잡힌다. 내가 아직 실무일을 하지 못해서 그런건가?</p>
<p><strong>2) as const 문법</strong></p>
<p>as const로 상수형으로 취급할수 있다. </p>
<pre><code>const people = {
    name: &quot;Tom&quot;,
    age: 24,
    gender: &quot;male&quot;,
} as const</code></pre><p>해당 객체는 상수형으로 취급되어 밸류를 수정할수 없다. + 엄격하게 타입을 추론하게 한다.</p>
<p><strong>3) keyof, typeof</strong></p>
<p>객체에서 key를 리터럴 타입으로 가지고 올때 사용한다.</p>
<pre><code>const people = {
    name: &quot;Tom&quot;
    age: 24,
}
</code></pre><p>여기서 객체 key를 타입으로 사용하려면,</p>
<pre><code>type PeopleKeyType = keyof people -&gt; const people을 타입으로 먼저 변환시켜서 그 타입에서 키를 따와야 하기 때문에 그 때 사용하는게 typeof이다. -&gt; 
type PeopleKeyType = keyof typeof people
결과 -&gt; name | age

만약에 typeof만 입력한다면 객체의 형태의 타입이 됨.

{
    name: string
    age: number,
}
이런식으로</code></pre><p>typeof는 타입을 가져온다고 기억하자.</p>
<p><strong>value를 타입으로 가져오고 싶다면?</strong></p>
<pre><code>const obj = {a: &quot;a&quot;, b: &quot;b&quot;, c: &quot;c&quot;}
type ValueType = keyof typeof obj 로 key타입을 추출하고 -&gt; typeof obj[keyof typeof obj]

객체에서 일반 밸류값 가져올때 하는 방식으로 하면 된다. 다만 타입추론을 느슨하게 하기 떄문에

as const로 엄격하게 타입을 추론하게 한뒤 사용한다.

const obj = {a: &quot;a&quot;, b: &quot;b&quot;, c: &quot;c&quot;} as const 
type ValueType = typeof obj[keyof typeof obj]

이렇게하면 밸류타입이 유니온으로 추출됨.
</code></pre><p>*<em>4) &amp;(intersection)과 |(union) *</em></p>
<p>&amp;과 |이 있는데 의미가 다르다.</p>
<pre><code>
1) type Test01 = {a: &quot;a&quot;} | {b: &quot;b&quot;}
2) type Test02 = {a: &quot;a&quot;} &amp; {b: &quot;b&quot;}</code></pre><p>두개의 차이점은 뭘까?</p>
<p>1번의 경우에는 아래처럼</p>
<pre><code>const obj:Test01 = {a: &quot;a&quot;} or {b: &quot;b&quot;}</code></pre><p>둘중 한개만 있어도 되지만</p>
<p>2번의 &amp;(intersection)의 경우에는 아래처럼</p>
<pre><code>const obj:Test02 = {a: &quot;a&quot;, b: &quot;b&quot;}</code></pre><p>두개의 타입이 다 있어야한다.</p>
<p>*<em>5) type ailas와 interface의 차이점? *</em></p>
<p>1) type ailas
먼저 type은 &amp;을 이용해 확장을 할 수 있다.</p>
<pre><code>type A = {a: &quot;a&quot;}
type B = A &amp; {b: &quot;b&quot;}
type C = B &amp; {c: &quot;c&quot;}
---
const D: C = {a: &quot;a&quot;, b:&quot;b&quot;, c:&quot;c&quot;}</code></pre><p>이런식으로 반드시 있어야 된다는 의미의 &amp;를 활용해 확장이 가능하다.</p>
<p>2) interface</p>
<p>interface의 확장방식은 2가지가 있다.</p>
<p>첫번째는 class와 같이 extends를 이용한 방식</p>
<pre><code>interface A {
    a: &quot;a&quot;,
}

interface B extends A {
    b: &quot;b&quot;,
}</code></pre><p>두번째는 같은 인터페이스를 재 선언 하는것이다.</p>
<pre><code>interface A {
    a: &quot;a&quot;
}
interface A {
    b: &quot;b&quot;
}
interface A {
    c: &quot;c&quot;
}</code></pre><p>간단하게 표현하고 싶을때는 type, 대체로 자주쓰는 방식은 interface방식이라고 한다.
타입 확장의 자유도가 더 높기 때문인것 같다. type같은경우 같은 이름으로 재 선언 하지 못하니,</p>
<blockquote>
<p>실무 이름 표기법</p>
</blockquote>
<p>타입스크립트에서 최근에는 안쓰는 추세라고는 하지만 타입 네이밍 기법이 있다고 한다.</p>
<p>interface면 I를 붙이고 
type이면 T를 붙이고
enum이면 E를 붙이는 기법이라고 한다.</p>
<p>안쓰인다고는 하나, 해당 기법을 이용해 네이밍을 한 경우도 있을테니 숙지해두자~</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[typescript 기초 정리 - 1]]></title>
            <link>https://velog.io/@ctr_nike/typescript-%EA%B8%B0%EC%B4%88-%EC%A0%95%EB%A6%AC-1</link>
            <guid>https://velog.io/@ctr_nike/typescript-%EA%B8%B0%EC%B4%88-%EC%A0%95%EB%A6%AC-1</guid>
            <pubDate>Wed, 01 May 2024 15:39:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>타입스크립트 대원칙</p>
</blockquote>
<p>1) 타입은 변수, 매개변수, 리턴값에만 표기 한다.
2) 최대한 명확하고 정확하게 작성 한다.
3) 타입이 추론가능할땐 타입 추론을 적극 활용해라. 다만 타입 추론이 내가 생각한 타입이 아니거나 any 타입인 경우 직접 타입을 표기해야한다.</p>
<pre><code>const a= 5;
const b= &quot;아&quot;; 
위의 코드들은 상수(변하지 않고 고정된)값이니까 굳이 number나 string으로 표기하여 범위를 넓히는것보단 타입 추론을 하게 두는게 낫다.
</code></pre><blockquote>
<p>타입스크립트 문법</p>
</blockquote>
<p><strong>1) 타입은 고정된 원시값(string,number,null,undifined,boolean...등)으로도 표기가 가능하다.</strong></p>
<p>const a:5 = 5;
const b:false = false;
const c:&quot;문자열&quot; = &quot;문자열&quot;;</p>
<p><strong>2) 배열 타입 유니온 사용할때는 소괄호가 있어야함.</strong></p>
<p>const arr:(string | number) = [] 이런식으루</p>
<p><strong>3) 매개변수에 타입표기만 해줘도 타입스크립트에서 리턴값을 알아서 추론해줄수도 있다.</strong></p>
<p>function foo(x:number, y:number) {return x x y}
위의 경우 타입스크립트는 매개변수 x와 y의 타입을 보고 리턴값을 추론한다.</p>
<p>하지만 항상 명심하자. 내가 예측하지 못한 타입일 경우에는 명확하게 타입을 표기해야하는걸로.</p>
<p><strong>4) 함수의 오버로딩</strong></p>
<p>1) 동일한 이름에 매개 변수만 다른 여러 버전의 함수를 만드는 것을 함수의 오버로딩이라고 한다.
2) 파라미터의 형태가 다양한 여러 케이스에 대응하는 같은 이름을 가진 함수를 만드는 것.
3) function 키워드로만 함수 오버로딩을 할 수 있으며 arrow function으로는 오버로딩을 할 수 없다.
4) 유니온을 쓰는걸 권장하는듯.</p>
<p><strong>5) as문법</strong></p>
<p>1) 타입스크립트가 추론하지 못하는 타입을 as키워드를 통해 명시해주는 것
사용법 : 변수 as 타입
2) chaining 하는 경우 변수를 괄호로 감싼 뒤 그 안에서 as 키워드를 사용
3) as뒤에 명시하고자 하는 데이터 타입을 작성해주면 된다.
4) 실제 데이터 타입을 변경하지 않고 타입 에러가 나지 않게끔만 해준다. 즉 컴파일 과정에서 사라짐.</p>
<p><strong>6) never타입</strong></p>
<p>타입 스크립트에서 빈 배열을 선언할경우 never타입으로 지정이 되고 해당 배열에
어떤 값도 들어올수 없게 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[내가 쓰는 타입스크립트 정리 1(기초)]]></title>
            <link>https://velog.io/@ctr_nike/%EB%82%B4%EA%B0%80-%EC%93%B0%EB%8A%94-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%A0%95%EB%A6%AC-1%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@ctr_nike/%EB%82%B4%EA%B0%80-%EC%93%B0%EB%8A%94-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%A0%95%EB%A6%AC-1%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Fri, 26 Apr 2024 08:08:02 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>기초상식</p>
</blockquote>
<p>원시타입: 객체를 제외한 string,number,undfiend,null...</p>
<blockquote>
<p>튜플,유니온이란?</p>
</blockquote>
<p><strong>튜플(Tuple)</strong>
사전적인 의미론 튜플(tuple)은 셀 수 있는 수량의 순서 있는 열거이다.
길이와 각 요소마다의 타입이 고정된 배열이라고 이해해두면 될듯.</p>
<pre><code>type UserTuple = [string, number, string, boolean]

const user01:UserTuple = [&quot;dbstjghks&quot;,586665,&quot;닉네임&quot;,false]
const user02:UserTuple = [&quot;dbstjghks&quot;,586665,&quot;닉네임&quot;,false,5798798798] //ERROR</code></pre><p>다만, push를 이용하여 해당 배열에 요소를 추가하면 에러가 발생하는게 아닌 정상적으로 요소가 추가되어 배열 요소 타입 밑 타입 순서를 고정시키는 튜플의 의미가 없기 때문에</p>
<p>배열 인덱스마다의 타입과 순서를 “완벽히” 고정시키기 위해 
<strong>readonly</strong> 키워드를 사용한다.</p>
<pre><code>type UserTuple = readonly [string, number, string, boolean]

const user01:UserTuple = [&quot;dbstjghks&quot;,586665,&quot;닉네임&quot;,false]
const user02:UserTuple = [&quot;dbstjghks&quot;,586665,&quot;닉네임&quot;,false,5798798798] //ERROR

push불가</code></pre><p><strong>유니온</strong></p>
<p>string | number 등 또는 |기호를 이용하여 타입 표기한것.</p>
<blockquote>
<p>type과 interface의 차이란?</p>
</blockquote>
<p><strong>type</strong></p>
<p>1) type같은 경우는 자료형이 원시타입일경우 type으로 표기한다</p>
<p>2) 확장시 &amp;기호를 사용한다.</p>
<pre><code>type Person = {
  name: string,
  age: number
}

type Student = Person &amp; { // 확장(상속)
  school: string
}</code></pre><p><strong>interface</strong></p>
<p>1) interace같은 경우는 객체일때 interface를 활용한다. 원시자료형에는 사용할수 없다.</p>
<p>2) 선언적 확장이 가능하다. </p>
<pre><code>interface Person = {
    name: string;
} 
</code></pre><pre><code>interface Person = {
    name: string;
    age: number;
} </code></pre><p>이런식으로도 확장 가능. extends를 사용해도 확장 가능.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[20230823/ 프로그래머스 1) 옹알이]]></title>
            <link>https://velog.io/@ctr_nike/20230823-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-1-%EC%98%B9%EC%95%8C%EC%9D%B4</link>
            <guid>https://velog.io/@ctr_nike/20230823-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-1-%EC%98%B9%EC%95%8C%EC%9D%B4</guid>
            <pubDate>Wed, 23 Aug 2023 07:50:10 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>문제</p>
</blockquote>
<p><strong>머쓱이는 태어난 지 6개월 된 조카를 돌보고 있습니다. 
조카는 아직 &quot;aya&quot;, &quot;ye&quot;, &quot;woo&quot;, &quot;ma&quot; 네 가지 발음을 최대 한 번씩 사용해 조합한(이어 붙인) 발음밖에 하지 못합니다. 문자열 배열 babbling이 매개변수로 주어질 때, 머쓱이의 조카가 발음할 수 있는 단어의 개수를 return하도록 solution 함수를 완성해주세요.</strong></p>
<pre><code>제한사항
1 ≤ babbling의 길이 ≤ 100
1 ≤ babbling[i]의 길이 ≤ 15
babbling의 각 문자열에서 &quot;aya&quot;, &quot;ye&quot;, &quot;woo&quot;, &quot;ma&quot;는 각각 최대 한 번씩만 등장합니다.
즉, 각 문자열의 가능한 모든 부분 문자열 중에서 &quot;aya&quot;, &quot;ye&quot;, &quot;woo&quot;, &quot;ma&quot;가 한 번씩만 등장합니다.
문자열은 알파벳 소문자로만 이루어져 있습니다.

</code></pre><blockquote>
<p>풀이</p>
</blockquote>
<p>이 말인 즉슨, aya&quot;, &quot;ye&quot;, &quot;woo&quot;, &quot;ma&quot;의 조합으로 만 이루어져 있는 단어가 몇개있는지 찾아라는 뜻인데.</p>
<p>처음에는 다음과 같은 단계를 거쳤다.</p>
<pre><code>1. 합성어에 주어진 기본 단어가 포함되는가?

2. 포함 된다면 비교 배열에 push 

3. 그리고 거기 있는 단어들을 더해서 합성와 비교, 같을시에 카운트 증가</code></pre><p>하지만 이런식으로 진행하니 큰 문제가 생겼는데 바로, </p>
<p>단어 구성은 같아도 합성을 했을때 순서가 다를경우 전혀 다른 단어가 된다는 것이다.</p>
<p>해서 머리를 굴리다 다음과 같은 방안으로 수정했다.</p>
<pre><code>1. 합성어에 주어진 기본 단어가 포함되는가?

2. 포함 된다면 비교 배열에 push

3. 비교 배열 반복문을 돌리면서 포함 단어들을 삭제한다.

4. 그렇게 해서 합성어의 갯수가 0이 된다면 오롯이 기본단어의 합성으로 구성된 합성어라는 뜻이 되므로 

5. 카운트를 1개 증가 시킨다. </code></pre><p>나같은 경우는 위와 같은 방법으로 했는데, 다 해결하고 문제 풀이를 보니</p>
<p>정규식으로 1줄로 끝내는 사람도 있더라.. 갑자기 현타가 밀려온다.</p>
<p>그래도 나같은 발상으로 푼 사람은 한명도 없어 보여서 나름 뿌듯하다.</p>
<blockquote>
<p>소스코드</p>
</blockquote>
<pre><code>function solution(babbling) {
    const baseWord = [&quot;aya&quot;,&quot;ye&quot;,&quot;woo&quot;,&quot;ma&quot;];
    const includeWord = [];

    let trueCnt = 0;
    let clearWord = &quot;&quot;;
    //ex: [&quot;ayaye&quot;, &quot;uuuma&quot;, &quot;ye&quot;, &quot;yemawoo&quot;, &quot;ayaa&quot;]

    //1. 합성어에 포함되는 단어들만 배열로 집합
    //2. 합성어의 조합 순서를 바꿀순 없으니 속하는 단어들을 제거하는 형식으로 해보자.
    //3. length가 0이되면 count1 증가로

    babbling.forEach(str =&gt; {
        baseWord.forEach(innerStr =&gt; {
            str.includes(innerStr) ? includeWord.push(innerStr) : &quot;&quot;;
        })

        clearWord = str;

        for(let i = 0; i &lt; includeWord.length; i++) {
            //let idx = clearWord.indexOf(includeWord[i]);
            //let removeWord = clearWord.substring(idx, idx + includeWord[i].length);
            clearWord = clearWord.replace(includeWord[i], &quot;&quot;);
        }

        if(clearWord.length === 0) {
            trueCnt++;
        }

        if(includeWord.length &gt; 0) {
            includeWord.splice(0);   
        }

    })

    return trueCnt;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[spa-deploy관련]]></title>
            <link>https://velog.io/@ctr_nike/spa-deploy%EA%B4%80%EB%A0%A8</link>
            <guid>https://velog.io/@ctr_nike/spa-deploy%EA%B4%80%EB%A0%A8</guid>
            <pubDate>Tue, 27 Jun 2023 05:45:20 GMT</pubDate>
            <description><![CDATA[<p><a href="https://create-react-app.dev/docs/deployment/#building-for-relative-paths">https://create-react-app.dev/docs/deployment/#building-for-relative-paths</a></p>
<p>클릭 한대로 따라하면 새로고침 404오류 해결해줌.</p>
<p><a href="https://github.com/rafgraph/spa-github-pages/blob/gh-pages/index.html">https://github.com/rafgraph/spa-github-pages/blob/gh-pages/index.html</a> 참고.</p>
<blockquote>
<p>사용법</p>
</blockquote>
<p>이것은 GitHub Pages를 사용하여 단일 페이지 앱을 배포하는 간단한 솔루션입니다. React Router의 <BrowserRouter />와 같은 방식으로 React 단일 페이지 앱을 쉽게 배포하거나 다른 프론트엔드 라이브러리 또는 프레임워크로 개발된 단일 페이지 앱을 배포할 수 있습니다.</p>
<p>필요한 이유:
GitHub Pages는 단일 페이지 앱을 기본적으로 지원하지 않습니다. 예를 들어, example.tld/foo와 같은 주소로 새로고침이 발생하면, GitHub Pages 서버는 /foo에 대한 정보를 알지 못하기 때문에 404 오류를 반환합니다.</p>
<p>작동 방식:
GitHub Pages 서버가 frontend routes로 정의된 경로(example.tld/foo와 같은)로 요청을 받으면, 커스텀 404.html 페이지를 반환합니다. 이 커스텀 404.html 페이지에는 현재 URL을 가져와 경로와 쿼리 문자열을 쿼리 문자열로 변환하고, 그런 다음 브라우저를 쿼리 문자열과 해시 프래그먼트만 포함하는 새 URL로 리다이렉트하는 스크립트가 포함되어 있습니다. 예를 들어, example.tld/one/two?a=b&amp;c=d#qwe은 example.tld/?/one/two&amp;a=bandc=d#qwe으로 변환됩니다.</p>
<p>GitHub Pages 서버는 새로운 요청인 example.tld/?/...을 받아들이고, 쿼리 문자열을 무시하고 index.html 파일을 반환합니다. index.html 파일에는 단일 페이지 앱이 로드되기 전에 리다이렉트가 있는지 확인하는 스크립트가 포함되어 있습니다. 리다이렉트가 있으면 적절한 URL로 변환하여 window.history.replaceState(...)를 사용하여 브라우저의 기록에 추가하지만, 브라우저는 새로운 URL을 로드하지 않습니다. 단일 페이지 앱이 로드되면 index.html 파일에서 정상적인 URL이 브라우저의 기록에 남아 있으며, 단일 페이지 앱이 이에 따라 라우팅됩니다. (이러한 리다이렉트는 새로고침으로 페이지를 로드할 때에만 필요하며, 로드된 후에는 단일 페이지 앱 내에서 이동할 때는 필요하지 않습니다).</p>
<p>사용 방법:</p>
<p>본 레포지토리에서 404.html 파일을 그대로 사용하기 위해 복사합니다.
만약 프로젝트 페이지 사이트를 설정하고 커스텀 도메인을 사용하지 않는다면 (예: 사이트 주소가 username.github.io/repo-name인 경우), 404.html 파일에서 pathSegmentsToKeep를 1로 설정해야 합니다. 이렇게 하면 리다이렉트 후에도 /repo-name이 경로에 유지됩니다. 또한 React Router를 사용하는 경우 BrowserRouter에 basename=&quot;/repo-name&quot;과 같이 리포지토리 이름을 basename으로 설정해야 합니다.
index.html 파일에 있는 리다이렉트 스크립트를 복사하여 index.html 파일에 추가합니다. 리다이렉트 스크립트는 반드시 index.html 파일 내의 단일 페이지 앱 스크립트보다 앞에 위치해야 합니다.
자세한 사용 방법은 다음과 같습니다.</p>
<p>React 단일 페이지 앱을 GitHub Pages로 호스팅하기 위해 이 레포지토리를 보일러플레이트(초기 구조)로 사용합니다. 이 보일러플레이트는 TypeScript로 작성되었지만 JavaScript 파일도 지원합니다. 이전에 JS로 작성되었으며, JS 전용 보일러플레이트를 원한다면 버전 6을 사용할 수 있습니다.</p>
<p>이 레포지토리를 클론합니다. ($ git clone <a href="https://github.com/rafgraph/spa-github-pages.git">https://github.com/rafgraph/spa-github-pages.git</a>)
.git 디렉토리를 삭제합니다. (spa-github-pages 디렉토리로 이동한 다음 $ rm -rf .git 명령을 실행합니다.)
레포지토리를 초기화합니다.
새 레포지토리로서 이 보일러플레이트를 사용하는 경우:
spa-github-pages 디렉토리에서 $ git init 명령을 실행한 다음 $ git add .와 $ git commit -m &quot;Add SPA for GitHub Pages boilerplate&quot; 명령을 실행하여 새 레포지토리를 초기화합니다.
기존 레포지토리의 gh-pages 브랜치로서 이 보일러플레이트를 사용하는 경우:
기존 레포지토리에서 새로운 gh-pages 브랜치를 만들고 이동합니다. ($ git checkout --orphan gh-pages) 이 단계에서는 gh-pages 브랜치가 브랜치 목록에 표시되지 않습니다. 첫 번째 커밋을 수행해야 브랜치가 목록에 나타납니다.
기존 레포지토리의 디렉토리에서 .git 디렉토리를 제외한 모든 파일과 디렉토리를 삭제합니다. ($ git rm -rf .)
클론한 spa-github-pages 디렉토리의 모든 파일과 디렉토리(숨겨진 점 파일 포함)를 기존 프로젝트의 빈 디렉토리로 이동합니다. ($ mv path/to/spa-github-pages/{.[!.],}* path/to/your-projects-directory)
$ git add .와 $ git commit -m &quot;Add SPA for GitHub Pages boilerplate&quot;를 실행하여 gh-pages 브랜치를 초기화합니다.
(선택사항) 커스텀 도메인 설정하기 - GitHub Pages에서 커스텀 도메인 설정 방법을 따릅니다.
커스텀 도메인을 사용할 경우 CNAME 파일을 커스텀 도메인으로 업데이트합니다. https://를 포함하지만 서브도메인은 필요에 따라 추가합니다. 예를 들어 www 또는 your-subdomain을 사용합니다.
DNS 제공자에서 CNAME 및/또는 A 레코드를 업데이트합니다.
$ dig your-subdomain.your-domain.tld 명령을 실행하여 DNS 설정이 제대로 되었는지 확인합니다. (https://는 포함하지 않습니다.)
(선택사항) 커스텀 도메인을 사용하지 않을 경우:
CNAME 파일을 삭제합니다.
User 또는 Organization Pages 사이트를 만드는 경우, 더 이상 할 필요가 없습니다.
Project Pages 사이트를 만드는 경우 (예: 사이트 주소가 username.github.io/repo-name인 경우):
404.html 파일에서 pathSegmentsToKeep를 1로 설정합니다.
index.html의 자산에 repo-name을 절대 경로에 추가합니다. 예를 들어, bundle.js의 src를 &quot;/repo-name/build/bundle.js&quot;로 변경합니다.
React Router에서 basename을 /repo-name으로 설정합니다. 예: <BrowserRouter basename="/repo-name" />
package.json의 start 스크립트에서 --open을 --open-page repo-name으로 변경합니다.
webpack.config.js에서 publicPath에 &#39;/repo-name/build/&#39;를 추가합니다.
historyApiFallback 리다이렉트를 rewrites: [{ from: //repo-name/[^?]/, to: &#39;/404.html&#39; }]로 변경합니다.
npm install 명령을 실행하여 React 및 기타 종속성을 설치하고, npm run build 명령을 실행하여 빌드를 업데이트합니다.
$ git add .과 $ git commit -m &quot;Update boilerplate for use with my domain&quot; 명령을 실행한 다음 GitHub에 푸시합니다. (Project Pages의 경우 $ git push origin gh-pages, User 또는 Organization Pages의 경우 $ git push origin main)
이제 원하는 대로 당신의 사이트를 만들어 보세요.</p>
<p>자신만의 React 컴포넌트를 작성하고, 자신만의 라우트를 생성하며, 스타일을 추가하세요.
index.html의 title과 404.html의 title을 사이트의 제목으로 변경하세요.
index.html의 favicon 링크와 favicon 디렉토리를 삭제하세요.
필요에 따라 robots.txt와 sitemap.txt를 업데이트하거나 삭제하세요. (SEO 섹션 참조)
readme, license, package.json을 원하는 대로 수정하거나 삭제하세요.
변경 사항을 로컬에서 테스트하려면 개발 환경 정보를 참조하세요.
변경 사항을 GitHub Pages에 게시하려면 $ npm run build (이는 프로덕션용으로 webpack -p를 실행합니다) 명령을 실행하여 빌드를 업데이트한 다음 $ git commit 및 $ git push를 실행합니다.
메인 브랜치의 /docs 폴더에서 호스팅하기 - 루트 폴더 대신 /docs 폴더에서 사이트를 제공하면서 소스 코드는 루트 폴더에 유지할 수도 있습니다.</p>
<p>위의 지침을 따른 후 /docs 폴더를 루트에 만들고, index.html, 404.html 및 /build 폴더를 /docs로 이동합니다.
package.json의 start 스크립트에 --content-base docs/를 추가합니다.
webpack.config.js에서 output 경로를 path: ${__dirname}/docs/build로 변경합니다.
GitHub에서 레포지토리 설정으로 이동하여 GitHub Pages의 소스로 /docs 폴더를 선택합니다.
개발 환경:
로컬에서 변경 사항을 테스트하기 위해 webpack-dev-server를 포함하였습니다. 이를 실행하려면 $ npm start를 실행하세요. webpack-dev-server는 소스 파일이 변경될 때마다 자동으로 새 번들을 만들고 메모리에서 번들을 제공하여 파일로 디스크에 저장된 번들을 볼 수 없습니다.</p>
<p>$ npm start는 package.json의 start 스크립트를 실행합니다. 이 스크립트는 $ webpack-dev-server --host 0.0.0.0 --disable-host-check --open을 실행합니다.
--host 0.0.0.0 --disable-host-check를 사용하면 다른 장치에서 http://[YOUR COMPUTER&#39;S IP ADDRESS]:8080으로 로컬 네트워크에서 사이트에 접근할 수 있습니다.
--open은 자동으로 브라우저에서 사이트를 엽니다.
webpack-dev-server는 index.html을 <a href="http://localhost:8080%EC%97%90%EC%84%9C">http://localhost:8080에서</a> 제공합니다. (포트 8080은 기본값입니다). 번들은 메모리에서 제공되며 브라우저에서 직접 열리지 않습니다. 서버에서 index.html을 로드해야 스크립트가 로드됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[20230622/ redux toolkit 사용법]]></title>
            <link>https://velog.io/@ctr_nike/20230622-redux-toolkit-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@ctr_nike/20230622-redux-toolkit-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Thu, 22 Jun 2023 07:11:32 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>redux toolkit 사용법</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/a8d6cd36-47ac-4fbf-a72b-d0361cb62662/image.PNG" alt=""></p>
<p>사진을 보면 provider라는 컴포넌트로 전체를 감쌌는데, 이 말은 전체 전역적으로 상태관리를 하겟다는 말이 된다. </p>
<p>저기 안에 라우터 컴퍼넌트도 넣어두고 하면 된다.</p>
<p>요는, 자기가 사용할 범위에 provider컴포넌트로 감싸주면 된다는것이다.</p>
<p>그리고 상태관리를 하는 파일은 별도로 js로 만들어 관리를 한다.</p>
<p>일반적으로 store라는 이름을 많이 쓴다고 한다.</p>
<p>정리하자면,</p>
<p>리액트는 단방향으로 데이터를 전달하고, props의 형태로 데이터를 전달하기 때문에</p>
<p>만약 자식컴포넌트의 숫자는 많고, 상태를 변경해야하는일이 많으면 해야할일이 복잡해지고 많아지기때문에</p>
<p>리덕스를 사용해서, 별도의 js파일을두고 자식이건 부모건 js파일안의 상태관리 함수를 호출해</p>
<p>상태를 관리하는것.</p>
<p><strong>이제 vscode로 가서 직접 사용해보자.</strong></p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/611ac650-4a79-4b32-97e6-0f224fb46edd/image.PNG" alt=""></p>
<p><strong>항상 컴포넌트나, js파일을 사용할때는 import를 사용하는것을 잊지말자.</strong></p>
<p>상태관리 js (store.js)파일을 만들고 프로바이더 컴포넌트의 props로 전달을 했다.</p>
<p><strong>상태관리하는 js, 그리고 prop의 이름은 자율이지만 관례적으로 store라는 이름을 쓰고</strong></p>
<p><strong>두개의 이름을 일치화 시키는것을 선호한다고 한다.</strong> </p>
<p><strong>이제 셋팅이 완료되었으니 redux를 이용하여 장바구니 기능을 만들어보자!</strong></p>
<p>먼저 장바구니 레이아웃을 만들어보자. 간단하게 만들기 위해 부트스트랩을 사용할것이다.</p>
<p><strong>일단 잠시 provider를 주석처리하고, 레이아웃을 먼저 잡고 상태관리 로직을 짜보도록 하자.</strong></p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/b91868cb-265b-4c01-9a04-d7952083a2f9/image.PNG" alt=""></p>
<p>components - table 클릭 - 원하는 레이아웃을 골라서 import 시켜주면 된다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/88e5e4fc-6b19-45ba-9647-d2c2c62b9282/image.PNG" alt=""></p>
<p>일단 간단하게 장바구니 레이아웃을 잡아봤다.</p>
<p>()안에 이름을 전달하고 수량을 변경하는 기능을 넣어보자.</p>
<p>그러기 위해선 상태변화 로직을 짜야한다. shop.js에 설정을 하자.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/495110ad-3637-4f4a-a5f7-003d350e90e2/image.PNG" alt=""></p>
<p>문서에 적힌 사용방법에 따라 먼저 configureStore를 import해준다.</p>
<p>여기서 또 createSlice라는 함수가 있는데, </p>
<p>해당 함수도 같이쓰면 액션과 리듀서를 생성하는 작업을 자동화할 수 있으므로 코드양이 줄어든다고 한다.</p>
<p>따라서 해당 함수도 import 시켜주자.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/46a48737-aa51-4d9a-b932-a634fadd31a4/image.PNG" alt=""></p>
<p>해당 함수를 작성하는 방법은 다음과 같다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/e9a87f96-e00c-4ebe-b3e4-cf1c1d64c508/image.PNG" alt=""></p>
<p>createSlice를 호출하면, createSlice라는 객체를 반환해준다.</p>
<p>그 안에 name, initialstate(상태 관리할 목록 이 안에서 속성을 설정해둬도 되고 사진처럼 외부에서 정의하고 내부에서 갖다 써도 된다.)</p>
<p>여기서 creatSlice객체 내부에 name을 설정하지않으면 자동적으로 내가 설정한 변수명이 name이 된다.</p>
<p>name을 설정하면 해당 객체의 이름이 내가 설정한 name으로 된다.</p>
<p>하지만 관례적으로 변수명과 name 값을 일치화시킨다고 하니 일치화시켜주자.</p>
<p>또한 reducers에서 set함수를 선언해 initialstate의 값을 변경시켜줄수있다.</p>
<pre><code>configureStore 함수는 

스토어를 생성한다.

스토어의 역할은?

상태관리

액션

리듀서

원래 리듀서 함수 안에, 액션 함수 즉 상태를 변경하는 함수를 넣어두고 

reducer에 해당 리듀서함수를 값으로 지정햇는데

createSlice로 reducers를 키값으로 설정뒤 밸류값으로 상태변경 함수를 설정할수 있다.</code></pre><p><img src="https://velog.velcdn.com/images/ctr_nike/post/ba0f10db-8cb2-4270-b98e-e55a88fcf8b7/image.PNG" alt=""></p>
<p>여기서 user의 reducer를사용한다는말은 reducers안에 있는 reducer객체를 사용한다는 말이다</p>
<p>reducer객체는 한 개의 액션에 대한 상태 변경 로직을 담당한다.</p>
<p>즉</p>
<p>reducers안에 reducer (상태변경함수로직1개만 담당) 이러한 리듀서가 여러개 있는것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[20230622 / redux 정리]]></title>
            <link>https://velog.io/@ctr_nike/20230622-redux-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@ctr_nike/20230622-redux-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 22 Jun 2023 02:47:33 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>리액트에서 리덕스를 왜 사용하는가?</p>
</blockquote>
<p>리액트는 기본적으로 단 방향으로 데이터의 흐름이 진행된다.</p>
<p>가장 최상위 부모 컴포넌트에서 상태 관리를 해주고, 자식 컴포넌트에게 props로 전달하게 되는데 </p>
<p>만약 자식 컴포넌트가 수없이 많다면? 그러면 상태 관리가 너무 힘들어지니까 </p>
<p>전역적으로 상태관리를 해주기 위해 생겼다.</p>
<p>리덕스를 사용하면 자식 컴포넌트에서 상태관리js(저장소) 내부의 함수를 꺼내서, 상태변경이 용이해진다.</p>
<p>즉 자식컴포넌트에서도 상태관리가 가능해진다는 말이다.</p>
<blockquote>
<p>설치법</p>
</blockquote>
<p>내가 설치할것은 redux toolkit이다.  Redux Toolkit이 출시됨으로써 </p>
<p>훨씬 더 간편하고 효율적인 방식으로 Redux를 사용할 수 있게 되었다.</p>
<p>다만 주의해야 할점은 해당 프로그램을 사용하려면 react의 버전이 React v16.8 이상이어야 한다는 것이다.</p>
<p>무튼 구글에 redux toolkit을 검색한다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/6d5fecd2-2877-42e8-9bcc-80277bff4f03/image.PNG" alt=""></p>
<p>사이트 접속 </p>
<p>get started를 누르고 아래로 내려가면</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/ca89639e-43aa-4b99-8f7e-dfd85bae7393/image.PNG" alt=""></p>
<p>설치 명령어가 나온다. 난 노드 환경이니 npm으로 설치를 할것이다.</p>
<p>둘다 설치해야 react에서 바인딩이 된다고 한다.</p>
<p>npm install @reduxjs/toolkit react-redux</p>
<p>이런식으로 명령어를 이어붙여서 둘다 설치할수 있다. 아니면 따로입력해도 되고 </p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/d83371c4-2b3e-4ab3-9ff7-4ab1abd0c51a/image.PNG" alt=""></p>
<p>pacakage.json 파일을 확인해보면 잘 설치된것을 알수있다.</p>
<p>설치 끝. 다음 글에서 사용법을 알아보도록 하자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[20230620 / react일기]]></title>
            <link>https://velog.io/@ctr_nike/20230620-react%EC%9D%BC%EA%B8%B0</link>
            <guid>https://velog.io/@ctr_nike/20230620-react%EC%9D%BC%EA%B8%B0</guid>
            <pubDate>Tue, 20 Jun 2023 06:35:15 GMT</pubDate>
            <description><![CDATA[<p>오늘은 배운것을 활용해서</p>
<p>복습을 했다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/959755c6-3439-4d2d-89e6-e4fff9ce7917/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/ctr_nike/post/878cfc4c-4ebb-4d4d-af28-55d955edb517/image.PNG" alt=""></p>
<p>map 함수로 아이템들은 렌더하는것까지는 손쉽게됐으나, key문제로 트러블이 있었다.</p>
<p>원래 계획은 map함수가 실행될때마다 컴포너트가 호출/ 태그가 반환되는 형식으로 계획을 잡았는데</p>
<p>문제가 생겼다.</p>
<p>바로 key부분이다, key 값을 설정하고 컴포넌트에 prop으로 전달, 그 안에서 key값을 설정하려고했으나 </p>
<p>문제가 생겨버린것이다.</p>
<p>key라는 이름으로 속성을 전달하니 undefiend가 떠서 알아보니</p>
<p>key는 컴포넌트의 prop 이름으로 사용해서는 안된다고 한다.  </p>
<p>그 이유는 key 속성은 React에 의해 예약된 속성으로, 컴포넌트의 다른 prop과 구분되어야 하는데 </p>
<p>만약 key 속성으로 prop 이름을 사용하면 React는 해당 prop을 key로 인식하지 않고 </p>
<p>그냥 일반적인 컴포넌트 prop으로 취급하게 되어버린다는것이다.</p>
<p>따라서 key 속성을 통해 컴포넌트를 고유하게 식별할 수 없게 되고, </p>
<p>컴포넌트 리스트를 업데이트할 때 문제가 발생하게 된다고 한다.</p>
<p>그래서 다른 방안으로 속성 이름을 다르게 전달하고 그 값을 </p>
<p>컴포넌트 내부에서 key값으로 설정하려고 했으나</p>
<p>그것마저도 Each child in a list should have a unique &quot;key&quot; prop.</p>
<p>오류가 뜨면서 안되는것이다. 그렇게 여러개 시도해보다가</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/78bbb85d-2694-4475-b948-4b32c6e86c65/image.PNG" alt=""></p>
<p>해당 형태처럼 key값을 전달하는게아니라 key값은 설정하고, 생성되는 list만 컴포넌트로 생성시키니 고쳐졌다. </p>
<p>알아보니까</p>
<p>key 속성은 부모 컴포넌트가 자식 컴포넌트를 렌더링할 때 필요한 정보로, </p>
<p>React에서는 key 값을 사용하여 컴포넌트를 식별하고, 각 컴포넌트의 변화를 추적한다고 한다.</p>
<p>일반적으로 key 속성은 컴포넌트를 렌더링하는 부모 컴포넌트에서 설정해야 하고 </p>
<p>부모 컴포넌트는 각 자식 컴포넌트에 대한 고유한 key 값을 제공하게 되는데 이렇게 하여</p>
<p>React는 각 컴포넌트를 고유하게 식별하고, 리스트의 변화를 정확하게 추적할 수 있게된다고 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[20230620 / 부트스트랩 사용]]></title>
            <link>https://velog.io/@ctr_nike/20230620-%EB%B6%80%ED%8A%B8%EC%8A%A4%ED%8A%B8%EB%9E%A9-%EC%82%AC%EC%9A%A9</link>
            <guid>https://velog.io/@ctr_nike/20230620-%EB%B6%80%ED%8A%B8%EC%8A%A4%ED%8A%B8%EB%9E%A9-%EC%82%AC%EC%9A%A9</guid>
            <pubDate>Tue, 20 Jun 2023 03:34:58 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>셋팅</p>
</blockquote>
<p>간단한 nav메뉴를 가져와서 routing을해보자.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/87f92b36-701e-4661-b23b-95b3408e81dc/image.PNG" alt=""></p>
<p>Navbars 클릭</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/44fb9741-bea8-42d0-8ed9-45ebd9b4787e/image.PNG" alt=""></p>
<p>자신이 원하는 스타일의 레이아웃을 선택하자.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/76fd07ff-f905-41f9-9156-9ef397164eb1/image.PNG" alt=""></p>
<p>해당 태그와 import태그를 복사해서 붙여넣어주면 된다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/ecd8e25b-621e-4107-b61c-32ad77d66fd8/image.PNG" alt=""></p>
<p>이런식으로 한번에 중괄호로 묵어서 import해주면 된다.</p>
<p>또한 부트스트랩 레이아웃을 사용하려면 css스타일도 import시켜주어야한다.</p>
<p>전역 컴포넌트인 app.js부분에 넣어주자. </p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/ba50c76b-7a86-4326-a457-11ed9b2e9851/image.PNG" alt=""></p>
<p>사이트 우측의 css 클릭</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/df67ca1f-be69-4553-b502-dc0d0887bb12/image.PNG" alt="">
해당 명령어를 전역 컴포넌트에 import시키면 완료.</p>
<blockquote>
<p>라우팅</p>
</blockquote>
<p>이번엔 라우트에 연결할때 Link컴포넌트가 아닌 useNavigate를 사용해보도록 하겠다.</p>
<p>Link와 useNavgate의 차이점</p>
<pre><code>Link: 링크 연결 컴포넌트로 정적으로 링킁연결
UseNavigate: 경로 지정 함수를 호출하는것으로, 필요에따라 동적으로 링크 연결이 가능하고
유연하게 링크를 바꿀수있다.

매번 
usenavigate는 유연하게 링크를 바꿀수있는게 핵심이다. </code></pre><p>아무튼 app.js를 전역컴포넌트로 정했고, app.js에 세팅을 다하고 부트스트랩 레이아웃을 넣어주면</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/69a116b5-9e1c-4aad-9b47-44b9ffa4d3a3/image.PNG" alt=""></p>
<p>이런식으로 편하게 레이아웃 작성이 완료되는것이다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/c6dd0ffb-3d42-4c18-a611-95270116cd16/image.PNG" alt=""></p>
<p>useNavigate()는 navigate라는 함수를 반환하는데, 해당 반환함수에 경로를 지정하면 링크연결이 되는원리이다.</p>
<p>즉
navigate는 경로이동지정함수를 반환받은변수이고, ()를호출하여 인자를 넣어주면 해당 링크로 연결되는것이다.</p>
<p>무튼
클릭 함수를 걸어주고, 클릭됐을때 navigate함수를 반환받아 링크연결을 해주었다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/77e26069-7d85-474f-95e6-4fa2d24379ab/image.PNG" alt=""></p>
<p>사진을 보면 부모 라우트 안에 자식 라우트가 들어갔는데 라우터 v6부터 생긴 기능중 하나라고 한다.</p>
<p>저렇게 해줌으로써, 부모 자식 컴포넌트를 같은 위치에 위치시키면서, 클릭하면 부모 컴포넌트의 반환값을 보여줄수있다.</p>
<p>만약 저렇게 부모라우트로 감쌌으면 부모라우트에 Outlet이라는 컴포넌트를 넣어줘야 자식 컴포넌트들이 렌더링이 된다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/4c4c9448-dffb-4d07-9704-c9f36a4fe6ab/image.PNG" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[20230620 / 부트스트랩 설치]]></title>
            <link>https://velog.io/@ctr_nike/20230620-%EB%B6%80%ED%8A%B8%EC%8A%A4%ED%8A%B8%EB%9E%A9-%EC%84%A4%EC%B9%98</link>
            <guid>https://velog.io/@ctr_nike/20230620-%EB%B6%80%ED%8A%B8%EC%8A%A4%ED%8A%B8%EB%9E%A9-%EC%84%A4%EC%B9%98</guid>
            <pubDate>Tue, 20 Jun 2023 02:41:11 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>설치</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/d0abe0c4-ec56-4e07-b98e-12e0a25ae7e1/image.PNG" alt=""></p>
<p>현재 리액트를 공부중이기 때문에 리액트 부트스트랩을 검색했다.</p>
<p>근데 저기서 바닐라 부트스트랩도 같이 설치가 가능하다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/8a118a67-004a-434a-bcfa-1e072605717e/image.PNG" alt=""></p>
<p>항상 이런 프로그램을 다운받고시픙면 get started나 docmuments 즉 문서파일을 확인하면 된다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/e92321b8-c1fe-4956-baa1-73a2af212a31/image.PNG" alt=""></p>
<p>멘트를 보니 scss 사용하고싶으면 바닐라 부트스트랩도 같이 깔아라고한다.</p>
<p>해당 명령어는 리액트 부트스트랩과 부트스트랩을 같이 설치하는 명령어이다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/0ad9e0dd-1a1e-49ae-8354-1a28f81d4871/image.PNG" alt=""></p>
<p>항상 packaga.json파일에서 무사히 잘 깔린것을 확인하는 습관을 들이자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[20230619 / react-router 사용법]]></title>
            <link>https://velog.io/@ctr_nike/20230619-react-router-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@ctr_nike/20230619-react-router-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Mon, 19 Jun 2023 05:33:13 GMT</pubDate>
            <description><![CDATA[<p>라우터를 사용하기에 앞서서..</p>
<ol>
<li><p><strong>a태그는 사용하면 안된다. 페이지를 호출하는 기능이 있기 때문에,</strong></p>
</li>
<li><p>*<em>link 에 to로연결한걸 route path로받아준다. *</em></p>
</li>
</ol>
<blockquote>
<p>사용법</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/ead0120d-3ea6-4d93-944a-e20c1e645b43/image.PNG" alt=""></p>
<p>브라우저라우터는 router들을 감싸는 가장 상위 컴포넌트로, 해당 컴포넌트로 감싸주고 라우팅을 작성해야한다.</p>
<p>해당 컴포넌트를 작성하면, 알아서 임포트 명령어가 작성된다.</p>
<p>&quot;React.StrictMode&quot;는 React의 개발 모드에서 추가적인 검사와 경고를 활성화하는 데 사용되는 컴포넌트로 부작용이 있는 코드, 예상치 못한 동작 등과 관련된 경고를 표시하여 개발자가 이를 수정하도록 유도한다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/bcb69672-d342-437d-bed9-005582bf739c/image.png" alt=""></p>
<p>app컴포넌트 안에 있는 구성이다.</p>
<p>사용할 라우터 컴포넌트들을 import해주고 써야한다.</p>
<p>Link =&gt; Link를 통해 경로를 설정하고 route컴포넌트가 해당 경로에 해당하는 컴포넌트를 뿌려준다.(렌더링)</p>
<p>to = &quot;&quot; 안에 연결한 경로를 설정하면 된다. 또한 main이 속해있는 link컴포넌트에 /라는게 있는데 /는 경로를 나타내는 문자열의 시작을 나타낸다. 즉, 보통 메인페이지를 나타낼때 쓴다.</p>
<p>여기서 NavLink라는 컴포넌트가있는데, Link랑 똑같은 역할을 하지만 클릭한 컴포넌트에 active라는 클래스를 넣어준다.</p>
<p>route =&gt; 앞에서도 말했지만, link to 문자열에 해당하는 부분을 렌더링해준다고 생각하면 된다.</p>
<p>path로 받는 문자열을 일치시켜주고, element = 안에 컴포넌트를 넣어 렌더링해주면 된다.</p>
<p>path에 보면 sub/* 이런식으로 표기되어있는데 그 안에 페이지가 또 들어온다는 의미라고 생각하면된다. </p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/787a3636-61ae-4986-b3ad-aca3677c8e9c/image.png" alt=""></p>
<p>우측에 보면 path에 /*이라는 문자열이있는데, 모든 경로에 대해 해당 element를 띄운다는 의미이다.
그리고 :peopleName이라고 경로를 받았는데, : 뒤에 문자열이있는데 경로 매개변수를 사용하겠다는 말이다.</p>
<p>순서: peopleName에 to에 해당하는 문자열이 들어온다. profile js에서 해당 경로 문자열에 해당하는 속성값을 만들어준다.</p>
<p>ex: to=&quot;김개똥&quot; -&gt; {김개똥 : {표시할 정보}} 이런식으로,</p>
<p><strong>그리고 컴포넌트 내부에서 useParams 훅을 이용해 peopleName이라는 변수로 받고 (보면 객체다, 따라서 구조분해할당을할떄도 같은이름으로 받아야하며, 만약 변수명을 다른이름으로 바꾸고 싶다면
peepleName : changePeopleName) 이런식으로 바꿔줘야한다.</strong></p>
<p>여기서 useParmas란?</p>
<pre><code>
useParams
useParams는 URL 인자들의 key/value(키/값) 짝들의 객체를 반환한다. 현재 &lt;Route&gt; 의 match.params에 접근하기 위해 사용한다.</code></pre><p>따라서 구조분해할당을할때 객체의형태로 받아야하는것이다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/f91cfe58-1937-4b3c-8497-b9c8218cfe2d/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/f12749ca-e9a4-456f-a503-25812cb0eaa1/image.png" alt=""></p>
<p>이렇게 link경로가 잘못됐을경우 예외처리도 가능하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[20230619 / react-router 설치 및 세팅]]></title>
            <link>https://velog.io/@ctr_nike/20230619-react-router-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%84%B8%ED%8C%85</link>
            <guid>https://velog.io/@ctr_nike/20230619-react-router-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%84%B8%ED%8C%85</guid>
            <pubDate>Mon, 19 Jun 2023 02:09:09 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>설치</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/10740e4c-5777-4db4-a243-7bf09a75168e/image.PNG" alt=""></p>
<ol>
<li>react router dom 검색</li>
</ol>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/529ac290-acc1-414e-9429-4c0851cb8de5/image.PNG" alt=""></p>
<ol start="2">
<li>좌측의 튜토리얼 클릭</li>
</ol>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/607f815b-da7c-4fe2-94b7-0f0b0c6f201e/image.PNG" alt=""></p>
<p>컨트롤+f로 npm검색하면 사진과 같이 나오는데</p>
<p>npm install react-router-dom localforage match-sorter sort-by</p>
<p>4개의 패키지를 깐다는건데</p>
<p><strong>npm install react-router-dom</strong> / React Router는 React 컴포넌트를 사용하여 사용자가 애플리케이션의 다른 경로로 이동할 수 있도록 도와줌. react-router-dom은 React Router의 DOM 바인딩을 제공하며, React 애플리케이션에서 브라우저의 주소를 기반으로 라우팅을 처리할 수 있도록 해줌. </p>
<p><strong>localforage</strong> / 웹 브라우저의 로컬 스토리지를 사용하여 데이터를 비동기적으로 저장하고 검색하기 위한 패키지</p>
<p><strong>match-sorter</strong> / 배열의 요소를 검색 기준에 따라 정렬하는 데 도움이 되는 패키지</p>
<p><strong>sort-by</strong> / 정렬 함수를 생성하는 데 사용되는 패키지로, 정렬 기준에 따라 객체 배열을 정렬할 수 있음.</p>
<p>필요에 따라 설치를 하면 된다. 일단 라우터만 설치해보도록 하자.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/d3ce0b6d-0991-4a9e-9fde-6a16491d5e74/image.PNG" alt=""></p>
<ol start="4">
<li>경로를 잡아주고 라우터 설치명령어를 입력한다. 설치가 다됐는지 보려면 항상
pacakage.json을 확인 성공적으로 잘 깔린것을 볼수있다.</li>
</ol>
<blockquote>
<p>셋팅</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/6132853c-972c-4c63-8d8d-d9838978bd25/image.PNG" alt=""></p>
<p>라우팅을 하는곳에 해당 명령어 입력</p>
<p><strong>BrowserRouter</strong> / router들을 감싸는 가장 상위요소, 해당 컴포넌트로 감싸주고 라우팅을 작성해야한다.</p>
<p><strong>Routes</strong> / react-router-dom 패키지의 컴포넌트 중 하나로, 라우팅 구성을 담당</p>
<p>routes는 여러개의 라우터 컴포넌트를 포함하는 <strong>최상위 라우터 컴포넌트</strong>로 각 경로에 대한 컴포넌트를 렌더링 할수 있도록 도와준다. </p>
<p><strong>Route</strong> / react-router-dom 패키지의 컴포넌트 중 하나로, 특정 경로에 대한 라우팅 규칙을 설정한다.</p>
<p><strong>사용자가 특정 경로로 이동하면 해당 경로에 연결된 컴포넌트가 렌더링되게 해줌.</strong></p>
<p><strong>Link</strong> / react-router-dom 패키지의 컴포넌트 중 하나로, <strong>클릭 가능한 링크</strong>를 생성한다. Link 컴포넌트를 사용하여 사용자가 특정 경로로 이동할 수 있는 링크를 생성할 수 있다. 
주로 네비게이션 메뉴나 페이지 간의 이동에 사용 됨.</p>
<p>개념적인건데 아직 잘 이해가 가진 않는다.</p>
<p>일단은 간단하게
<strong>Link 컴포넌트를 사용하여 경로를 연결하고</strong>, 사용자가 해당 경로로 이동하면 
<strong>rotue가 해당 경로에 해당하는 컴포넌트를 렌더링.</strong> 이를 통해 사용자는 링크를 클릭하여 다른 경로로 이동할 수 있고, 해당 경로에 대응하는 컴포넌트를 route가 뿌려주는것.
그리고 <strong>routers 안에는 그런 route를 여러개를 놔둘수 있어 여러개의 링크에 대응하는 컴포넌트를 렌더링할수있다.</strong> 라고 이해했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[20230615 / 컴포넌트 작성]]></title>
            <link>https://velog.io/@ctr_nike/20230615-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%9E%91%EC%84%B1</link>
            <guid>https://velog.io/@ctr_nike/20230615-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%9E%91%EC%84%B1</guid>
            <pubDate>Thu, 15 Jun 2023 05:31:21 GMT</pubDate>
            <description><![CDATA[<p>아까 설치한 라이브러리인 스타일드 컴포넌트를 활용하여</p>
<p>스타일을 입힌 컴포넌트를 작성해보자.</p>
<blockquote>
<p>문법</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/de301ffd-c962-424e-9283-2accc152beb3/image.PNG" alt=""></p>
<p>기존 컴포넌트를 작성할때와 거의 형태가 유사하긴 하다.</p>
<pre><code>변수키워드(const, var, let) 컴포넌트명(Wrap) = styled.태그명(div)백틱(``) 

백틱 안에다 스타일 입혀주면, 해당 스타일이 입혀진 컴포넌트가 되는것.

ex) const Title = styled.h2`
    font-size: 50px;
    background-color: red;
    text-align: center;
`</code></pre><p><img src="https://velog.velcdn.com/images/ctr_nike/post/a1673914-1237-4d61-b005-e5019f5f15a7/image.PNG" alt=""></p>
<p>컴포넌트가 하나 더 들어갈 예정이라 프래그먼트를 미리 넣어줬다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/ea63d587-ceae-4252-8414-125f6491a221/image.PNG" alt=""></p>
<p>root - app 안에 정확히 뿌려졌음.</p>
<p>styled componenet는 또 좋은점이 js문법을 사용할수 잇다는점이다. 예를들면</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/d4f1b307-783a-41c1-b6d2-5d01d1fec0bc/image.PNG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/de3e0c70-2ab0-4aa9-8316-65c214def59e/image.PNG" alt=""></p>
<p>버튼을 임시로 만들어보았다. </p>
<p>plus 버튼 minus버튼은 검은색이다. 근데 여기서 styled의 문법을 또 사용해보면</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/080b164a-0758-40c4-97a9-298c2dcfea65/image.PNG" alt=""></p>
<p>이런식으로 컴포넌트에 속성을 넣어주고</p>
<p>백틱으로 속성을 넣었으니 템플릿 스트링을 이용해 저렇게 함수 처리로 스타일을 넣을수있다.</p>
<p>삼항 연산자로 prop에 해당 키가 있으면 red, 없으면 white가 나오게 된다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/d42a9f36-6de8-424a-b403-0272571a2e4d/image.PNG" alt=""></p>
<p>잘 적용된것을 알 수 가있다.</p>
<p>styled-componenet는 클래스처럼 상속기능도 있다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/87b261c7-f4f1-486c-b9a1-8edaefe93bff/image.PNG" alt=""></p>
<p>stlyed(컴포넌트이름)을 하면 해당 컴포넌트의 스타일을 상속받을수있다.</p>
<p>상속받고 필요한값만 바꿔주면 되는것이다.
<img src="https://velog.velcdn.com/images/ctr_nike/post/6752592b-1e8a-4ebb-ba1a-cfee9ed11113/image.PNG" alt=""></p>
<p>styled-component말고도 라이브러리는 다양하다. sass/scss를 사용할수도 있고 중요한건 개발자의 취향따라 사용하면 된다는것..! </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[20230615 / React 외부 컴포넌트 연결/ 라이브러리 사용]]></title>
            <link>https://velog.io/@ctr_nike/20230615-React-%EC%99%B8%EB%B6%80-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%97%B0%EA%B2%B0-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%82%AC%EC%9A%A9</link>
            <guid>https://velog.io/@ctr_nike/20230615-React-%EC%99%B8%EB%B6%80-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%97%B0%EA%B2%B0-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%82%AC%EC%9A%A9</guid>
            <pubDate>Thu, 15 Jun 2023 03:44:40 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>컴포넌트 입력 / 라이브러리 설치</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/abfec109-0345-4a4d-96fa-9966dbed6b30/image.PNG" alt=""></p>
<p><strong>우선 컴포넌트를 만들어서 렌더하기전에 경로의 개념부터 잡아보자.</strong></p>
<p>src폴더의 index.js폴더에 들어가보면 이렇게 명령어가 나온다.</p>
<pre><code>import React from &#39;react&#39;;
import ReactDOM from &#39;react-dom/client&#39;;
import &#39;./index.css&#39;;
import App from &#39;./App&#39;;
import reportWebVitals from &#39;./reportWebVitals&#39;;</code></pre><p>index.js에서 import해서 사용한다. 
(내 안에서 만들어진게 아니면 전부 import해서 사용한다.)</p>
<p>앵간하면 건드릴 필요가 없는 파일이고, 저기 App이라는 컴포넌트에 우리가 만든 컴포넌트를 넣자. </p>
<p>그렇게 하면 app에 모든 컴포넌트 요소가 들어가고 root에 렌더가 되는것이다.</p>
<p>import로 react파일을 불러왔기때문에 cdn에서 사용하던것처럼 ReactDOM.render() 이렇게 사용을 안해도 된다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/6b2ce73c-4539-47ff-b5a7-f58da0baf407/image.PNG" alt=""></p>
<p>app 안에 각 컴포넌트를 용도별로 나눠서 넣어줄것이다. </p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/76455d2c-08e0-4d0f-ba8a-c13e5c5e4689/image.PNG" alt=""></p>
<p>쓸데없는 요소들을 다 지운결과이다. 리액트는 굉장히 섬세한 프레임워크라, 저렇게 없는 쪽에 import 걸어놓은것들을 다 지워줘야한다 (안지워주면 github에서 배포할때 오류뜨는듯)</p>
<p>그리고 내가 사용할 컴포넌트들을 넣으려면 import로 연결시켜주고 넣어야한다.</p>
<blockquote>
<p>예시</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/f996da56-4a3b-4ef4-a746-8fe980fc892b/image.PNG" alt=""></p>
<p>이런 식으로 사용되는 컴포넌트를 import로 연결시켜주어야한다. import가 됐다는 말은</p>
<p>export가 이루어졌단는 말이니, export하는법도 같이 살펴보자.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/de0a446c-8998-4da9-a084-d5454dc3e574/image.PNG" alt=""></p>
<p>rfc라는 명령어로도 바로 입력가능하다, 이렇게 컴포넌트js안에 컴포넌트명도 js명과 일치시켜준다.</p>
<p>저 위에 import 경로가 몇개있는데 하나는 리액트로 경로연결을하여 명령어를 쉽게 사용하기 위함이고, 또 하나는 라이브러리이다. 컴포넌트를 작성할때 스타일을 미리 입혀서 작성할수 있게 하는 라이브러리이다.</p>
<blockquote>
<p>styled-component 설치하기</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/3403dc54-fb6e-4c03-ac1f-75114efd7ad0/image.PNG" alt=""></p>
<p>npm i styled-components를 입력해보자.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/0345e30a-2a48-47c6-842f-cd4600417e1c/image.PNG" alt=""></p>
<p>오류가 떠버렸다.. 이럴때는 당황하지말고 구글링을 해보자.</p>
<p>나는 에러메시지가 떴을때 다음과 같은 과정으로 구글링을 진행을 한다.</p>
<ol>
<li><p>오류메시지 복붙검색 </p>
</li>
<li><p>그래도 안나오면 한글 or 영어로 구체적인 단어를 조합하여 검색</p>
</li>
<li><p>ai 활용</p>
</li>
</ol>
<p>1번 방법으로 검색을 하니 </p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/f32bac7f-cd67-4ecf-ac68-836c80b3fdaf/image.PNG" alt=""></p>
<p>이렇게 어떤 친절하신분이 해결법을 블로그에 게시를 해놨다.</p>
<p>버전 무문제 때문이라고 하니, 1번 혹은 3번안을 선택하여 설치하면 될듯하다. </p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/0ea0b3ac-64ef-482d-888c-91e34ffba347/image.PNG" alt=""></p>
<p><strong>성공적으로 설치가 된것을 확인할수있다!</strong></p>
<p>사용하기 위해서는 잊지말고 </p>
<p>@import styled from &#39;styled-components&#39; 입력!</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/8cd7197c-c433-49f1-aeb7-6f6e5f0084ab/image.PNG" alt=""></p>
<p>구글링을 해보니 이런 것도 발견했다. json파일에 입력하도록 하자.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/a249ab95-ec81-4b32-aa31-42e2dc52e8aa/image.PNG" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[20230615 / React 설치]]></title>
            <link>https://velog.io/@ctr_nike/20230615-React-%EC%84%A4%EC%B9%98</link>
            <guid>https://velog.io/@ctr_nike/20230615-React-%EC%84%A4%EC%B9%98</guid>
            <pubDate>Thu, 15 Jun 2023 03:15:26 GMT</pubDate>
            <description><![CDATA[<p>이제 cdn이 아닌 진짜 React를 설치하고 사용법까지 익혀보자.</p>
<blockquote>
<p>설치</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/361641fb-dbec-4e37-9c9a-9c168c1f4d0f/image.PNG" alt=""></p>
<ol>
<li>React 검색해서 사이트의 문서 탭 클릭</li>
</ol>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/829411f9-ff7a-47c9-bb96-41bfa9d6a88b/image.PNG" alt=""></p>
<ol start="2">
<li>우측 메뉴의 새로운 React 앱 만들기 클릭</li>
</ol>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/e0ea4200-3359-43aa-ab48-39d64af42c27/image.PNG" alt=""></p>
<p>3.</p>
<p>1) 명령어가 3개있는데, 우선 제일 위의 npx-create-react-app <strong>폴더명</strong>으로 설치</p>
<p>2) cd 만든폴더명 으로 디렉토리 경로 접속</p>
<p>3) npm start로 라이브서버 띄워주면 설치 완료!</p>
<h4 id="단-무조건-노드패키지매니저-nodejs가-깔려있어야한다">단 무조건 노드패키지매니저 Node.JS가 깔려있어야한다!</h4>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/c8a2c8e4-bf0d-4a53-b96e-11192293c5b9/image.PNG" alt=""></p>
<ol start="4">
<li>앱이 깔린다면 해당 사진처럼 나오게 된다.
여기서 public은 정적파일이 들어있는 폴더,
우리가 사용할 폴더는 src이다.
리액트는 번들기능도 가지고있어서, src를 번들하여 정적파일로 변환시켜준다. 
src폴더에는 우리가 개발하면서 만든 동적파일, 컴포넌트등이 들어가있게 된다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/96524bf6-3933-4b77-bd44-e4dca8a02757/image.PNG" alt=""></p>
<p>npm start로 라이브 서버를 띄울수 있다.</p>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/d2601bf4-be3c-4036-88ec-27f938867256/image.PNG" alt=""></p>
<ol start="5">
<li>이런 화면이 뜨면 전부 성공한것이다. 이 화면이 초기의 index.html이고, 이후 root파일 안에서 모든 렌더링이 이루어지게 된다. 우측 상단에 번역표시가있는데 저 문구가 안뜨게 
정적폴더 publick의 index.html에서 설정을 해주자</li>
</ol>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/61af7329-6fb8-4214-a7a7-fcb2612cc73e/image.PNG" alt=""></p>
<ol start="6">
<li>public - index.html에 들어가서 언어를 ko, 그다음 title명을 바꿔주면 된다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[20230613 /react hook 02]]></title>
            <link>https://velog.io/@ctr_nike/20230613-react-hook-02</link>
            <guid>https://velog.io/@ctr_nike/20230613-react-hook-02</guid>
            <pubDate>Tue, 13 Jun 2023 05:52:09 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>관리해야될 상태가 2개인 경우 방법 1</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/ff5143e1-768a-42b7-b968-cad3521767ed/image.png" alt=""></p>
<p><strong>풀이</strong></p>
<p>input에 입력한값을 동적으로 표시되게 짜보았다.</p>
<p>각 input은 입력 될때마다 change함수가 발동, defalutment의 값을 현재 인풋의 밸류로 바꿔주고</p>
<p>h2에 출력해준것이다.</p>
<blockquote>
<p>방법2</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ctr_nike/post/5512b5fc-3196-4c61-8978-208d2659f8fd/image.png" alt=""></p>
<p><strong>풀이</strong></p>
<p>위의 방법이 명확하긴 하지만 이 방법으로 하면 편해서 좋은것 같다.</p>
<p>useState로 객체를 하나 설정</p>
<p>객체의 속성값을 변경하고 그 속성을 할당하는 형식이다.</p>
<p>여기서 알아둬야 할것은 한번에 두개의 속성을 변경할수 없기 떄문에, 한개씩 나눠야 한다는것과</p>
<p>불변성을 유지해야되기 때문에 스프레드 연산자로 객체를 복사 한 후 </p>
<p>그 객체를 기반으로 수정한 밸류값을 뿌려줘야 한다는것이다.</p>
<p>또한 change이벤트가 일어날때마다 객체가 복사되는것이 아니라 , </p>
<p><strong>업데이트가 필요한 경우에만 이전 상태를 복사하여 새로운 상태를 생성한다는것을 알아두자.</strong> </p>
]]></description>
        </item>
    </channel>
</rss>