<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Hyun.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Mon, 17 Jul 2023 14:17:26 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Hyun.log</title>
            <url>https://velog.velcdn.com/images/i_am_heeeun/profile/82a69866-29d4-47be-b0ac-c4ff8ffb508a/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. Hyun.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/i_am_heeeun" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[@keyframes, animation]]></title>
            <link>https://velog.io/@i_am_heeeun/keyframes-animation</link>
            <guid>https://velog.io/@i_am_heeeun/keyframes-animation</guid>
            <pubDate>Mon, 17 Jul 2023 14:17:26 GMT</pubDate>
            <description><![CDATA[<h3 id="keyframes">@keyframes</h3>
<p>@keyframes는 CSS 애니메이션에서 구간을 정하고 각 구간별로 어떤 스타일을 적용시킬지 정하는 문법이다.
keyframes 리스트가 유효하려면 0% ~ 100%와 같은 시간에 대한 규칙을 포함해야 한다. 만약 이 타임 오프셋이 정해져 있지 않으면 parser가 인식하지 않아 keyframes 선언을 무효시킨다. 
만약 한개의 이름에 대해서 여러개의 keyframes set이 존재하면 parser가 마지막으로 마주치는 keyframe set만 유효하다.</p>
<h3 id="keyframes-사용">@keyframes 사용</h3>
<p>@keyframes를 사용하기 위해선 아래의 3가지가 필요하다.</p>
<ul>
<li>animation-name : 사용자가 직접 지정한 이름, @keyframes가 적용될 애니메이션의 이름</li>
<li>스테이지 : from - to 또는 0~100% 의 구간</li>
<li>CSS 스타일 : 각 스테이지(구간)에 적용시킬 스타일</li>
</ul>
<pre><code class="language-css">@keyframes name{
 0%{
     opacity:1;
 }

 50%{
     opacity:2;
 }

 100%{
     opacity:3;
 }

}</code></pre>
<pre><code class="language-css">@keyframes name{
    from{
        opacity:1;
    }

    to{
        opacity:3;
    }
}</code></pre>
<h3 id="animation-속성-종류">animation 속성 종류</h3>
<ul>
<li>animation-name: @keyframes 이름</li>
<li>animation-duration: 타임프레임 길이. 애니메이션 시작부터 마지막까지 총 지속시간</li>
<li>animation-timing-function: 애니메이션 속도 조절 ( linear | ease | ease-in | ease-out | ease-in-out | cubic-bezier </li>
<li>animation-delay: 애니메이션이 시작하기 전 지연시간</li>
<li>animation-iteration-count: 반복 횟수</li>
<li>animation-direction: 루프 (loop) 방향. 정방향으로 반복, 역방향으로 반복, 번갈아가며 반복 등을 설정</li>
<li>animation-fill-mode: 애니메이션 시작/끝 상태 제어 ( none | forwards | backwards | both )</li>
</ul>
<pre><code class="language-css">
div{
  position:absolute;
  left:100px;
  width:100px;
  height:50px;
  margin-left:-50px;
  background-color:#000;
  color:#fff;

  animation-name: name;
  animation-duration:2s;
  animation-duration: leaner;
  animation-iteration-count:3;
  animation-direction:alternate;
  animation-fill-mode: forwards;
}

@keyframes name {
  0% {
    left:100px;
  }
  100% {
    left:300px;
  }
}
</code></pre>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/05ce5d0a-f02e-4b38-a735-1442c73af0ec/image.gif" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[MIME-TYPE]]></title>
            <link>https://velog.io/@i_am_heeeun/MIME-TYPE</link>
            <guid>https://velog.io/@i_am_heeeun/MIME-TYPE</guid>
            <pubDate>Sun, 25 Jun 2023 12:29:21 GMT</pubDate>
            <description><![CDATA[<h3 id="mime-type">MIME-TYPE</h3>
<p>Multipurpose Internet Mail Extensions의 약자로 파일 변환을 의미한다. 현재는 웹을 통해 여러 형태의 파일을 전달하는데 사용하고 있고 문서, 파일 또는 바이트 모음의 특성과 형식을 나타낸다.</p>
<p>브라우저는 파일 확장자가 아닌 MIME TYPE을 사용하여 URL 처리 방법을 결정하므로 응답 Content-Type헤더에 올바른 MIME TYPE을 보내는 것이 중요하다. 올바르게 구성하지 않으면 브라우저가 파일 내용을 잘못 해석해 사이트가 제대로 작동하지 않으며 다운로드한 파일이 잘못 처리될 수 있다.</p>
<h3 id="사용하는-이유">사용하는 이유</h3>
<p>옛날 전자우편은 ASCII파일 전송만 가능했다.하지만 바이너리 파일(음악,동영상 등) 전송이 필요해졌고 이를 전자우편으로 전송하기 위해 개발되었다.
현재는 이메일 뿐만 아니라 웹을 통해 HTTP 통신에서 전달되는 다양한 형태의 데이터를 표현하기 위해 사용되고 있다.브라우저는 리소스를 내려받았을 때, 해야할 기본동작을 MIME TYPE을 기반으로 결정한다. </p>
<h3 id="사용하는-방법">사용하는 방법</h3>
<p>MIME으로 인코딩 한 파일은 데이터의 종류를 알려주는 Content-Type 정보를 파일 앞부분에 담는다.
브라우저의 경우 응답/요청시 HTTP 메시지의 헤더에 정보를 담아서 보내게 되는데 이 헤더에 Content-Type 정보를 담아서 어떤 데이터 종류인지 알려준다.</p>
<h3 id="구조">구조</h3>
<p>MIME TYPE은 가장 일반적으로 슬래시(/)로 구분된 type(유형)과 subtype(하위 유형)의 두 부분으로 구성되어있다.</p>
<pre><code>type/subtype</code></pre><pre><code>type은 데이터 유형이 속하는 일반 범주를 나타낸다. 크게 개별 혹은 멀티타입 으로 나눌 수 있다.    
ex) text, video, image, audio, application

subtype은 MIME Type이 나타내는 정확한 데이터 종류를 식별한다.
ex) 1. 개별 : plain, html, ics
    2. 멀티타입 : multipart/form-data(보통 서버로 데이터 보낼때 사용), 
                multipart/byteranges</code></pre><p>각 type에는 고유한 subtype세트가 있다. MIME Type은 항상 type과 subtype이 모두 존재한다.</p>
<p>추가 세부 정보를 제공하기 위해 선택적 매개 변수를 추가할 수 있다.</p>
<pre><code>type/subtype;parameter=value

text/plain;charset=UTF-8</code></pre><p>MIME TYPE은 대소문자를 구분하지 않지만 대부분 소문자로 작성한다. 하지만 매개변수 값은 대소문자를 구분한다.</p>
<h3 id="type별-정리">TYPE별 정리</h3>
<h4 id="text">text</h4>
<p>: 특정 문자셋으로 구성된 텍스트 정보나 포스트스크립트 같은 formatted text 정보 전송에 사용된다.
ex) text/plain, text/html, text/css, text/javascript</p>
<h4 id="multipart">multipart</h4>
<p>: 모든 종류의 이미지를 나타내며, 비디오는 포함되지 않는다.
ex) audio/midi, audio/mpeg, audio/webm, audio/ogg, audio/wav</p>
<h4 id="audio">audio</h4>
<p>: 모든 종류의 오디오 파일을 전송한다.
ex) audio/midi, audio/mpeg, audio/webm, audio/ogg, audio/wav</p>
<h4 id="video">video</h4>
<p>: 모든 종류의 비디오 파일을 전송한다.
ex) video/webm, video/ogg</p>
<h4 id="application">application</h4>
<p>: 모든 이진 데이터(바이너리 데이터)를 전송합니다.
ex) application/octet-stream, application/pkcs12, application/vnd.mspowerpoint, application/xhtml+xml, application/xml,  application/pdf</p>
<h4 id="multipartform-data">multipart/form-data</h4>
<p>: multipart/form-data는 브라우저에서 서버로 HTML Form의 내용을 전송 시 사용한다.  멀티 파트 문서 형식으로써, 경계로 구분되어지는 다른 파트들로 구성되어있다.</p>
<h4 id="multipartbyteranges">multipart/byteranges</h4>
<p>: multipart/byteranges 는 브라우저로 회신하는 부분적인 응답 전송의 context 내에서 사용된다. 다른 multipart Type처럼, Content-Type은 경계선 문자열을 정의하기 위해 boundary 디렉티브를 사용한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[react - Portal]]></title>
            <link>https://velog.io/@i_am_heeeun/react-Portal</link>
            <guid>https://velog.io/@i_am_heeeun/react-Portal</guid>
            <pubDate>Sun, 18 Jun 2023 14:55:52 GMT</pubDate>
            <description><![CDATA[<h3 id="portal">Portal</h3>
<p>Portal은 부모 컴포넌트의 DOM 계층 구조 바깥에 있는 DOM 노드로 자식을 렌더링하는 최고의 방법을 제공한다.
리액트 포탈은 리액트 라이브러리에서 제공하는 기능 중 하나로, React 컴포넌트에서 DOM 트리 상에서의 위치를 변경할 수 있도록 해준다. 이 기능을 사용하면 컴포넌트의 렌더링 결과를 다른 DOM 노드로 이동시킬 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/827fb17e-9cf4-40b1-9680-f7f746cf414e/image.png" alt=""></p>
<p>&lt; div id=&quot;root&quot; &gt;와 &lt; div id=&quot;modal&quot;&gt; 은 형제 관계처럼 보이지만 실제로 modal은 root 안에서 보여지는 자식 컴포넌트이고,렌더링만 root의 바깥에서 이루어지고 있다.</p>
<h3 id="portal-생성방법">Portal 생성방법</h3>
<pre><code class="language-jsx">ReactDOM.createPortal(child, container)</code></pre>
<p>첫 번째 인자(child)는 엘리먼트, 문자열, 혹은 fragment와 같은 어떤 종류이든 렌더링할 수 있는 React 자식이고, 두 번째 인자(container)는 DOM 엘리먼트이다.</p>
<h3 id="장점">장점</h3>
<ol>
<li><p>유연한 구성
: 리액트 포탈은 컴포넌트를 다른 DOM 위치로 이동시키기 때문에 UI 구성을 더욱 유연하게 할 수 있다.
예를 들어, Modal 창을 구현할 때 일반적으로는 모달 컴포넌트를 최상위 컴포넌트의 자식으로 추가해야 하는데 리액트 포탈을 사용하면 모달 컴포넌트를 원하는 위치로 이동시킬 수 있다. 복잡한 UI 구성을 쉽게 구현할 수 있다.</p>
</li>
<li><p>성능 최적화
: 리액트 포탈은 컴포넌트의 렌더링 결과를 다른 DOM 위치로 이동시키는 기능을 제공하므로, 컴포넌트의 렌더링이 최적화될 수 있다. 
예를 들어, 상위 컴포넌트에서 자식 컴포넌트를 렌더링하면서 상태(State)를 변경하면, 해당 컴포넌트와 그 자식 컴포넌트가 모두 다시 렌더링된다. 
하지만 리액트 포탈을 사용하면 해당 컴포넌트와 자식 컴포넌트 중에서 변경된 부분만 렌더링되므로, 불필요한 렌더링을 최소화할 수 있다.</p>
</li>
</ol>
<h3 id="언제-사용하면-좋은가">언제 사용하면 좋은가??</h3>
<ol>
<li><p>모달(Modal): 모달은 부모 컴포넌트의 스타일링 속성에 제약을 받아 z-index 등으로 번거로운 후처리를 해줘야한다.하지만 포탈을 사용하면 독립적인 구조와 부모-자식 관계를 동시에 유지하면서, z-index 등 부모 컴포넌트의 제약에서 벗어날 수 있다.</p>
</li>
<li><p>포탈(Portal): 포탈은 일반적으로 다른 웹 페이지로 이동하는 링크를 클릭할 때, 새로운 브라우저 탭이나 창을 열어서 해당 페이지를 보여주는 기능을 말한다. 이 기능을 구현할때 포탈을 사용해보자</p>
</li>
</ol>
<h3 id="구현-방법">구현 방법</h3>
<ol>
<li><p>index.html에 모달이 렌더링될 위치를 잡아준다.</p>
<pre><code class="language-jsx">&lt;body&gt;
 &lt;div id=&quot;root&quot;&gt;&lt;/div&gt;
 &lt;div id=&quot;modal&quot;&gt;&lt;/div&gt; // 모달이 렌더링 될 위치
&lt;/body&gt;</code></pre>
</li>
<li><p>Potal.js 생성</p>
<pre><code class="language-jsx">//modal div를 가져와 children으로 넣어주는 Portal역할을 할 Portal.js를 만들어준다.
import reactDom from &quot;react-dom&quot;;
</code></pre>
</li>
</ol>
<p>export const ModalPortal = ({ children }) =&gt; {
  const el = document.getElementById(&quot;modal&quot;);
  return reactDom.createPortal(children, el);
};</p>
<pre><code>
3. modal 컴포넌트 생성

4.  modal을 사용할 컴포넌트에 Portal, Modal를 렌더링
```jsx
//modal을 띄우려는 컴포넌트 파일
import ModalPortal from &quot;../helpers/Portal&quot;;
import alertModal from &quot;./defaultAlert1&quot;;

const Group = props =&gt; {
  const [modalOn, setModalOn] = useState(false);

  const handleModal = () =&gt; {
    setModalOn(!modalOn);
  };

  return (
    &lt;&gt;
       &lt;button onClick={handleModal} className=&quot;btn_registReq&quot;&gt;alert창 띄우기&lt;/button&gt;
       &lt;ModalPortal&gt;
         {modalOn &amp;&amp; &lt;Modal onClose={handleModal} /&gt;}
       &lt;/ModalPortal&gt;
    &lt;/&gt;
  );
};

export default Group;
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[React - FORM (폼)]]></title>
            <link>https://velog.io/@i_am_heeeun/React-FORM-%ED%8F%BC</link>
            <guid>https://velog.io/@i_am_heeeun/React-FORM-%ED%8F%BC</guid>
            <pubDate>Sun, 11 Jun 2023 13:07:29 GMT</pubDate>
            <description><![CDATA[<p>HTML 폼 엘리먼트는 폼 엘리먼트 자체가 내부 상태를 가지기 때문에, React의 다른 DOM 엘리먼트와 다르게 동작한다. 
예를 들어, 아래의 순수한 HTML에서 아래의 폼은 name을 입력받는다.</p>
<pre><code class="language-javascript">&lt;form&gt;
  &lt;label&gt;
    Name:
    &lt;input type=&quot;text&quot; name=&quot;name&quot; /&gt;
  &lt;/label&gt;
  &lt;input type=&quot;submit&quot; value=&quot;Submit&quot; /&gt;
&lt;/form&gt;
</code></pre>
<p>이 폼은 사용자가 폼을 제출하면 새로운 페이지로 이동하는 기본 HTML 폼 동작을 수행한다. React에서 동일한 동작을 원한다면 그대로 사용하면 된다. 그러나 대부분의 경우, JavaScript 함수로 폼의 제출을 처리하고 사용자가 폼에 입력한 데이터에 접근하도록 하는 것이 편리하다. 이를 위한 표준 방식은 “제어 컴포넌트 (controlled components)“라고 불리는 기술을 이용하는 것이다.</p>
<hr>
<h3 id="제어-컴포넌트-controlled-components">제어 컴포넌트 (Controlled Components)</h3>
<p>HTML에서 &lt; input &gt; , &lt; textarea &gt;, &lt; select &gt;와 같은 폼 엘리먼트는 일반적으로 사용자의 입력을 기반으로 자신의 state를 관리하고 업데이트를 한다. React에서는 변경할 수 있는 state가 일반적으로 컴포넌트의 state 속성에 유지되며 setState()에 의해 업데이트된다.</p>
<p>React에 의해 값이 제어되는 입력 폼 엘리먼트를 “제어 컴포넌트 (controlled component)“라고 한다.</p>
<h3 id="textarea-태그">textarea 태그</h3>
<p>HTML에서 &lt; textarea &gt; 엘리먼트는 텍스트를 자식으로 정의한다.</p>
<pre><code>&lt;textarea&gt;
  나는 text
&lt;/textarea&gt;</code></pre><p>React에서 &lt; textarea &gt;는 value 어트리뷰트를 대신 사용한다.
이렇게하면 &lt; textarea &gt;를 사용하는 폼은 한 줄 입력을 사용하는 폼과 비슷하게 작성할 수 있다.</p>
<pre><code class="language-jsx">class EssayForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: &#39;Please write an essay about your favorite DOM element.&#39;
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert(&#39;An essay was submitted: &#39; + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      &lt;form onSubmit={this.handleSubmit}&gt;
        &lt;label&gt;
          Essay:
          &lt;textarea value={this.state.value} onChange={this.handleChange} /&gt;
        &lt;/label&gt;
        &lt;input type=&quot;submit&quot; value=&quot;Submit&quot; /&gt;
      &lt;/form&gt;
    );
  }
}
</code></pre>
<p>여기서 주의할 점은 this.state.value 를 생성자에서 초기화하므로 textarea는 일부 텍스트를 가진채 시작되는 점이다.</p>
<h3 id="select-태그">select 태그</h3>
<p>HTML에서 &lt; select &gt;는 Dropdown 목록을 만든다. 
아래의 예제는 지역 목록을 만든 것이다.</p>
<pre><code class="language-jsx">&lt;select&gt;
  &lt;option value=&quot;Seoul&quot;&gt;Seoul&lt;/option&gt;
  &lt;option value=&quot;Busan&quot;&gt;Busan&lt;/option&gt;
  &lt;option selected value=&quot;Ulsan&quot;&gt;Ulsan&lt;/option&gt;
&lt;/select&gt;</code></pre>
<p>selected 옵션이 있으므로 Busan 옵션이 초기값이 된다. React에서는 selected 어트리뷰트를 사용하는 대신 최상단 select태그에 value 어트리뷰트를 사용한다. 한 곳에서 업데이트만 하면되기 때문에 제어 컴포넌트에서 사용하기 더 편하다.</p>
<pre><code class="language-jsx">class RegionForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: &#39;Ulsan&#39;};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert(&#39;Your favorite area is: &#39; + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      &lt;form onSubmit={this.handleSubmit}&gt;
        &lt;label&gt;
          Pick your favorite area:
          &lt;select value={this.state.value} onChange={this.handleChange}&gt;
            &lt;option value=&quot;Seoul&quot;&gt;Seoul&lt;/option&gt;
            &lt;option value=&quot;Busan&quot;&gt;Busan&lt;/option&gt;
            &lt;option value=&quot;Ulsan&quot;&gt;Ulsan&lt;/option&gt;
          &lt;/select&gt;
        &lt;/label&gt;
        &lt;input type=&quot;submit&quot; value=&quot;Submit&quot; /&gt;
      &lt;/form&gt;
    );
  }
}
</code></pre>
<p>select 태그에 multiple 옵션을 허용한다면 value 어트리뷰트에 배열을 전달할 수 있다.</p>
<pre><code class="language-jsx">&lt;select multiple={true} value={[&#39;Seoul&#39;, &#39;Busan&#39;]}&gt;</code></pre>
<h3 id="제어-컴포넌트를-사용할-때-문제점">제어 컴포넌트를 사용할 때 문제점</h3>
<p>제어 컴포넌트는 UI에 입력한 데이터 상태와 저장한 데이터의 상태가 항상 일치하는 것을 알 수 있다. 즉 사용자가 입력하는 모든 데이터가 동기화 된다.
예를들면, input태그 안에 &quot;배고프다&quot;라는 값을 입력한다고 했을때 아래 형식으로 업데이트가 되는데</p>
<pre><code>ㅂ
배
배ㄱ
배고
배고ㅍ
배고프
배고프ㄷ
배고프다</code></pre><p>이런식으로 불필요한 단어 입력시에도 값이 갱신되어 버린다. 이는 불필요한 리렌더링, 불필요한 api요청으로 인한 자원 낭비 문제로 연결 될 수 있다.</p>
<p>이러한 불필요한 방법을 막기 위해선 스로틀링이나 디바운싱(throttle&amp;debounce)을 사용할 수 있다.</p>
<blockquote>
</blockquote>
<p> 스로틀링: 마지막 함수가 호출된 후 일정 시간이 지나기 전에 다시 호출되지 않도록 하는 것
 디바운싱 : 연이어 호출되는 함수들 중 마지막 함수(또는 제일 처음)만 호출하도록 하는 것</p>
<h3 id="비제어컴포넌트와-제어컴포넌트의-차이점">비제어컴포넌트와 제어컴포넌트의 차이점</h3>
<ol>
<li>제어컴포넌트는 실시간으로 필드값의 유효성 검사가 가능하다.</li>
<li>조건부로 submit버튼을 비활성화 할 수 있다.</li>
<li>동적 입력이 가능하다.</li>
<li>실시간으로 입력 형식을 지정 가능하다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[CSR(Client Side Rendering)]]></title>
            <link>https://velog.io/@i_am_heeeun/CSRClient-Side-Rendering-ewm1fxb7</link>
            <guid>https://velog.io/@i_am_heeeun/CSRClient-Side-Rendering-ewm1fxb7</guid>
            <pubDate>Sun, 21 May 2023 15:22:58 GMT</pubDate>
            <description><![CDATA[<h3 id="csr">CSR</h3>
<p>서버에서 전체 페이지를 렌더링하여 보여주고 사용자가 요청할때마다 리소스를 서버에서 제공받아 클라리언트가 해석하고 렌더링하는 방식이다.  쉽게 말해서 클라이언트에서 모두 처리하는 것이다.
SSR과 달리 서버에 HTML를 요청하는게 아니라 브라우저에서 자바스크립트로 렌더링하는 것이다. 
주로 리액트나 뷰, 앵귤러같은 SPA가 동작하는 방식이다. </p>
<h3 id="장점">장점</h3>
<ol>
<li>사용자 친화적이다. 화면 깜박임이 없다. </li>
<li>필요한 부분만 요청하고 응답하기 때문에 서버 부하가 감소한다. </li>
<li>변경된 부분과 관련된 데이터만 가져오므로 서버사이드 렌더링 보다 빠른 속도를 보인다.</li>
</ol>
<h3 id="단점">단점</h3>
<ol>
<li>초기에 모든 JS를 다운받아야 하기 때문에 사용자가 첫 화면을 보기까지 시간이 오래걸린다. </li>
<li>사용자와 상호작용 후에 페이지 내용을 로드하기 때문에 SEO가 불리하다. </li>
<li>CSR은 브라우저의 쿠키, 로컬 스토리지에 정보를 저장한다
이는 XSS(Cross-Site Scripting) 공격에 대한 취약점을 드러내어 보안 이슈가 발생할 수 있다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/99272f5e-a19c-4cc7-8888-b3ff4944b284/image.png" alt=""></p>
<h3 id="렌더링-방식-선택기준-팁">렌더링 방식 선택기준 팁</h3>
<p>검색엔진의 상위노출이 중요하거나 페이지마다 데이터가 자주 바뀐다면 SSR</p>
<p>상위노출보다 고객의 데이터 보호가 더 중요하고 보다 나은 사용자 경험을 제공하고 싶으면 CSR을 선택하는게 좋다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[서버사이드렌더링(SSR)]]></title>
            <link>https://velog.io/@i_am_heeeun/%EC%84%9C%EB%B2%84%EC%82%AC%EC%9D%B4%EB%93%9C%EB%A0%8C%EB%8D%94%EB%A7%81SSR</link>
            <guid>https://velog.io/@i_am_heeeun/%EC%84%9C%EB%B2%84%EC%82%AC%EC%9D%B4%EB%93%9C%EB%A0%8C%EB%8D%94%EB%A7%81SSR</guid>
            <pubDate>Sun, 21 May 2023 14:27:56 GMT</pubDate>
            <description><![CDATA[<h3 id="ssrserver-side-rendering">SSR(Server Side Rendering)</h3>
<p>: 클라이언트에서 요청이 들어올때마다 매번 서버에서 새로운 뷰를 만들어 제공하는 방식이다. 즉 서버가 화면을 그리는 주체가 된다.</p>
<h3 id="동작방식">동작방식</h3>
<ol>
<li>클라이언트가 초기 화면을 로드하기 위해 서버에 요청을 보낸다.</li>
<li>서버는 화면을 그리는데 필요한 데이터와 CSS를 모두 적용해 HTML과 JS코드를 브라우저에 전달한다.</li>
<li>브라우저에서는 전달받은 페이지를 화면에 띄우고 JS코드를 다운받고 HTML을 실행시킨다.
<img src="https://velog.velcdn.com/images/i_am_heeeun/post/ef4e5c41-2bd7-4a39-91e4-4a7af186f1b3/image.png" alt=""></li>
</ol>
<h3 id="장점">장점</h3>
<ol>
<li>SEO(검색엔진최적화) : 모든 데이터가 이미 HTML에 담겨진채로 브라우저에 전달되기 때문에 검색엔진 최적화에 유리하다. </li>
<li>서버로부터 화면을 렌더링하기 위한 필수적인 요소를 먼저 가져오기 때문에 초기 로딩속도가 빠르다.</li>
<li>SNS에서 링크를 공유했을때 해당 링크의 정보를 미리보기 기능을 해주는 OG(Open Graph)TAG를 적용시켜준다.</li>
</ol>
<ul>
<li>OG Tag는 og-image, og-title, og-description으로 나누어 화면에 보여지게 된다. 
<img src="https://velog.velcdn.com/images/i_am_heeeun/post/6956e81c-bd14-4fc5-bfdd-dd723bada98d/image.png" alt=""></li>
</ul>
<h3 id="단점">단점</h3>
<ol>
<li>요청시 마다 새로고침을 하기때문에 화면의 깜빡임이 보인다. </li>
<li>새로운 요청이 생길때마다 바뀌지 않아도 되는 부분도 렌더링되기때문에 서버 부하가 생길 수 있다 .</li>
<li>초기 로딩속도가 빠른 만큼 동시에 이것이 제일 치명적인 단점이 되기도한다.
SSR은 서버에서 만들어진 HTML파일을 가져오게 되고 사용자는 바로 웹사이트를 볼수 있게되는데 하지만 웹사이트를 동적으로 제어할 수 있는 자바스크립트 파일은 아직 받아오지 못했기때문에 사용자가 화면을 클릭해봐도 아무런 반응이 없는 상태가 된다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[React - SPA]]></title>
            <link>https://velog.io/@i_am_heeeun/React-SPA</link>
            <guid>https://velog.io/@i_am_heeeun/React-SPA</guid>
            <pubDate>Sun, 30 Apr 2023 14:10:59 GMT</pubDate>
            <description><![CDATA[<h3 id="spa-single-page-application">SPA (Single Page Application)</h3>
<p>서버로부터 완전한 새로운 페이지를 불러오지 않고 현재의 페이지를 동적으로 다시 작성함으로써 사용자와 소통하는 웹 애플리케이션이나 웹사이트를 말한다. 
이러한 접근은 연속되는 페이지들 간의 사용자 경험의 간섭을 막아주고 애플리케이션이 더 데스크톱 애플리케이션처럼 동작하도록 만들어준다.</p>
<p>SPA의 경우 서버에서 사용자에게 제공하는 페이지는 한 종류이지만, 해당 페이지에서 로딩된 자바스크립트와 현재 사용자 브라우저의 주소상태에 따라 다양한화면을보여준다.</p>
<p>다른 주소에 다른 화면을 보여 주는 것을 라우팅이라고 한다. 리액트 라이브러리 자체에 이 기능이 내장되어 있지는 않지만 브라우저의 API를 직접 사용하여 관리하거나, 라이브러리를 사용하여 구현할 수 있다. </p>
<p>리액트 라우팅 라이브러리는 리액트 라우터(react-router), 리치 라우터(reach-router), Next.js 등 여러가지가 있다. 
리액트 라우터는 클라이언트 사이드에서 이루어지는 라우팅을 아주 간단하게 구현할 수 있도록 해준다. 서버 사이드 렌더링을 할 때도 라우팅을 도와주는 컴포넌트들을 제공해 주고있다.</p>
<h3 id="spa의-단점">SPA의 단점</h3>
<ul>
<li><p>앱의 규모가 커지면 자바스크립트 파일이 너무 커진다.</p>
<ul>
<li>페이지 로딩시 사용자가 실제로 방문하지 않을수도 있는 페이지의 스크립트도 불러오기 때문이다. 하지만 이건 코드 스플리팅을 사용하면 라우트별로 파일들을 나누어서 트래픽과 로딩속도를 개선할 수 있다.</li>
</ul>
</li>
<li><p>자바스크립트를 사용하지 않는 일반 크롤러에서는 페이지의 정보를 제대로 수집하지 못한다는 단점이 있다. 그렇기 때문에 구글, 네이버, 다음 같은 검색 엔진의 검색 결과에 페이지가 잘 나타나지 않을 수도 있다.</p>
<ul>
<li>이러한 문제점들은 서버 사이드 렌더링(server side rendering)을 통해 모두 해결할 수 있다.</li>
</ul>
</li>
</ul>
<h3 id="리액트-라우터react-router">리액트 라우터(React-Router)</h3>
<p>리액트에서는 경로에 따라 다른 뷰를 보여줄 수 있다. 이때 사용하는 라이브러리가 리액트라우터이다.
리액트 라우터는 크게 3가지로 나누어서 볼 수 있다.</p>
<ol>
<li>라우터 역할을 하는 BrowserRouter
: 컴포넌트의 최상위에 있어 리액트 라우터의 컴포넌트를 활용할 수 있도록 한다.<ol start="2">
<li>경로를 매칭해주는 Routes, Route
: Routes컴포넌트가 경로가 일치하는 하나의 Route만 렌더링한다. Route 컴포넌트 안에는 path속성과 element속성이 존재하는데 이 속성들이 경로와 그 경로에 일치하는 컴포넌트를 매칭해준다.</li>
</ol>
</li>
<li>경로를 변경해주는 Link
: a태그와 비슷한 역할을 하는 Link컴포넌트이다. 누르면 화면(경로)를 변경해주는 역할을 한다. a태그는 페이지 전환시 처음부터 렌더링 시키는 새로고침을 하지만 Link는 페이지 전환을 방지하는 기능이 내장되어 있다. 따라서 SPA구현에 적합하다고 한다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[리액트 - responsive]]></title>
            <link>https://velog.io/@i_am_heeeun/%EB%A6%AC%EC%95%A1%ED%8A%B8-responsive</link>
            <guid>https://velog.io/@i_am_heeeun/%EB%A6%AC%EC%95%A1%ED%8A%B8-responsive</guid>
            <pubDate>Sun, 09 Apr 2023 13:38:47 GMT</pubDate>
            <description><![CDATA[<p>저번시간에 했던 media query로 반응형웹을 만드는건 html과 css만으로 구현이 가능한것이다. 
반응형 웹을 만들때 디자인뿐만 아니라 구조나 기능을 다르게 해야하는 경우가 있는데 react-responsive라는 라이브러리를 통해 반응형 웹을 구현할 수 있다.
ex) pc에선 길게 늘어져있던 메뉴가 모바일에선 메뉴버튼으로 적용(애플홈페이지가 이렇게 되어있다.)</p>
<h3 id="responsive-설치">responsive 설치</h3>
<pre><code>yarn add react-responsive</code></pre><p>설치는 간단하다 yarn을 이용해 라이브러리를 설치해주면 끝이다.</p>
<h3 id="usemediaquery">useMediaQuery</h3>
<p>useMediaQuery는 responsive라이브러리에서 제공하는 hook이다.
useMediaQuery에 media-query조건을 넣어주면 해당 조건에 따라 true, false boolean값을 리턴해준다.</p>
<pre><code class="language-jsx">import {useMediaQuery} from &#39;react-responsive&#39;</code></pre>
<h3 id="usemediaquery-문법">useMediaQuery 문법</h3>
<pre><code class="language-jsx">const 변수명 = useMediaQuery ({
query : &quot;(min or max-width :100px)&quot;
})

//ex
const isPc = useMediaQuery ({
query : &quot;(min-width : 1024px) and (max-width :1920px)&quot;
});
// width값이 최소 1024 ~ 1920px 까지의 범위는 isPc가 출력된다.</code></pre>
<h3 id="hook을-왜-사용해야하는가">hook을 왜 사용해야하는가</h3>
<p>PC에서는 &quot;web&quot;라는 텍스트를 , 모바일에서는 &quot;mobile&quot; 이라는 텍스트를 보여주려고 할 때 단순 CSS Media-Query로 작성 하려면 매번 두가지 케이스를 작성해서 display : none, block; 으로 나눠서 처리를 해야하는 번거로움이 있다. 하지만 Hook을 사용하면 아래처럼 해결이 가능합니다.</p>
<pre><code class="language-jsx">import React from &quot;react&quot;
import { useMediaQuery } from &quot;react-responsive&quot;

const isPc = useMediaQuery ({
    query: &quot;(min-width:1024px)&quot;
}); //리턴값이 boolean이다.

  const text = isPc ? &quot;web&quot; : &quot;mobile&quot;

  return (
    &lt;div&gt;
      {text}
    &lt;/div&gt;
  );
}

export default App;</code></pre>
<h3 id="간단한-예제">간단한 예제</h3>
<p>이제 간단한 예제를 살펴보자. pc사이즈로 들어오면 초록색바탕색에 텍스트는 &#39;PC 사이즈!!&#39;를 출력하고 모바일 사이즈로 들어오면 파랑색바탕색에 텍스트는 &#39;모바일 사이즈!!&#39;를 출력하는 스크립트를 만들어보자.</p>
<p>//MediaQuery.js</p>
<pre><code class="language-jsx">import React from &quot;react&quot;
import { useMediaQuery } from &quot;react-responsive&quot;

const Mobile  = ({children}) =&gt; { //여기서 children은 하위 컴포넌트이다.
  const isMobile = useMediaQuery({
    query : &quot;(max-width:767px)&quot;
  });

  return &lt;&gt;{isMobile &amp;&amp; children}&lt;/&gt;
}

const PC  = ({children}) =&gt; {
  const isPc = useMediaQuery({
    query : &quot;(min-width:768px) &quot;
  });

  return &lt;&gt;{isPc &amp;&amp; children}&lt;/&gt;
}

export  {Mobile,PC};</code></pre>
<p>// app.js</p>
<pre><code class="language-jsx">import React from &quot;react&quot;;
import { Mobile, PC } from &quot;./MediaQuery.js&quot;
import &quot;./App.scss&quot;;


function App() {
  return (
    &lt;&gt;
        &lt;div&gt;
          &lt;Mobile&gt;
            &lt;div className=&quot;mobile_container&quot;&gt;
            모바일 사이즈 !!
            &lt;/div&gt;
          &lt;/Mobile&gt;
        &lt;/div&gt;

        &lt;div className=&quot;pc_container&quot;&gt;
          &lt;PC &gt;
            PC 사이즈!
          &lt;/PC&gt;
        &lt;/div&gt;
    &lt;/&gt;
      )
}

export default App;
</code></pre>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/708e58dd-08a9-4804-8da3-dd4820a8bffa/image.gif" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React- Media Query]]></title>
            <link>https://velog.io/@i_am_heeeun/React-Media-Query</link>
            <guid>https://velog.io/@i_am_heeeun/React-Media-Query</guid>
            <pubDate>Sun, 02 Apr 2023 13:34:55 GMT</pubDate>
            <description><![CDATA[<h3 id="반응형-웹">반응형 웹</h3>
<p>: 디바이스 종류에 따라 웹페이지가 자동적으로 재조정되는 것을 말한다.
어떠한 환경에서도 그에 맞게 사이즈를 변화시켜 사용자가 보기 편리하게 만드는것이 반응형 웹이다.</p>
<h3 id="media-query-미디어-쿼리">Media Query (미디어 쿼리)</h3>
<p>단말기의 종류에 따라 각각 다른 스타일을 적용시켜줄 수 있었던 미디어 타입이라는 것에서 더 발전시켜 좀 더 구체적인 조건으로 필요한 스타일을 적용할 수 있도록 만든것이 미디어 쿼리이다.</p>
<h3 id="미디어-쿼리-문법">미디어 쿼리 문법</h3>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/760d9e62-6a1f-438e-8229-529828d80fdd/image.png" alt=""></p>
<ul>
<li><p>only | not
: only는 뒤의 조건만 적용한다는 것이고  not은 뒤의 조건을 제외하고 적용한다는 뜻이다.</p>
</li>
<li><p>미디어 타입</p>
<ul>
<li>all : 모든 미디어 타입</li>
<li>aural : 음성장치</li>
<li>braille : 점자 장치</li>
<li>print : 인쇄 용도</li>
<li>projection : 프로젝터</li>
<li>screen : 컴퓨터 스크린</li>
<li>tv : 음성과 영상이 동시에 출력되는 장치</li>
<li>embrossed : 페이지에 인쇄된 점자 표시장치</li>
</ul>
</li>
</ul>
<p>우리가 많이 쓰는 타입은 screen과 print이다. 
여러 미디어 타입을 적용하고 싶으면 아래와 같이 쉼표로 구분지어서 사용하면 여러개의 타입을 적용할 수 있다.</p>
<pre><code class="language-css">@media only screen, print and(width: 1000px){...]</code></pre>
<ul>
<li>속성<ul>
<li>width : 페이지의 가로길이</li>
<li>height : 페이지의 세로길이</li>
<li>device-width : 단말기의 가로길이</li>
<li>device-height : 단말기의 세로길이</li>
<li>aspect-ratio : width와 height의 비율을 판단</li>
<li>device-aspect-ratio : 단말기의 물리적인 화면 비율</li>
<li>color-index : 단말기에서 사용하는 최대 색상수</li>
<li>resolution : 지원하는 해상도를 판단, 화면의 크기는 같지만 지원하는 해상도가 다른 기기의 경우 판단할때 쓰면 좋다고 한다.</li>
</ul>
</li>
</ul>
<h3 id="간단한-미디어-쿼리-예시">간단한 미디어 쿼리 예시</h3>
<pre><code class="language-html">&lt;style&gt;
  div{
    width: 100%;
    height: 100%;
  }

  @media screen and(max-width:100px){
    div{background-color: blue;}
  }

  @media screen and(min-width:100px) and(max-width:200px){
    div{background-color: red;} 
  }

  @media screen and(min-width:200px){
     div{background-color: green}
  }
&lt;/style&gt;

&lt;body&gt;
  &lt;div&gt;&lt;/div&gt;
&lt;body&gt;</code></pre>
<p>위의 예시는 웹에 접근한 기기가 screen일때 가로길이가 100px미만이면 배경을 파랑색으로 200px이상이면 초록색으로 100px에서 200px사이이면 빨강색으로 적용된다는 것이다. </p>
<h3 id="마무리">마무리</h3>
<p>전통적인 방식으로 반응형 웹을 구현할때 media query를 많이 사용하지만 화면 비율별로 기능을 다르게 하고싶다면 리액트에서는 react-responsive라는 것을 사용하여 반응형 웹을 구현한다고 한다.
다음시간엔 react-responsive라는 것을 알아보도록 하자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React- Hooks(3)]]></title>
            <link>https://velog.io/@i_am_heeeun/React-Hooks3</link>
            <guid>https://velog.io/@i_am_heeeun/React-Hooks3</guid>
            <pubDate>Sun, 12 Mar 2023 10:50:16 GMT</pubDate>
            <description><![CDATA[<h3 id="1-useref">1. useRef</h3>
<h4 id="11-useref란">1.1. useRef란?</h4>
<p>: 저장공간또는 DOM요소에 접근하기 위해 사용하는 Hook이다.
 자바스크립트에서 특정 DOM을 선택할땐 querySelector, getElementById 등의 함수를 사용해서 접근하는데 리액트에서는 useRef를 사용해 접근한다.</p>
<p>useRef는 current 속성을 가지고 있는 객체를 반환한다. current 속성은
값을 변경해도 상태를 변경할 때처럼 컴포넌트가 다시 렌더링되지 않는다.
즉, 컴포넌트가 리렌더링되어도 current 속성의 값은 사라지지 않는다.</p>
<h4 id="22-사용법">2.2. 사용법</h4>
<pre><code class="language-jsx">import { useRef} from &quot;react&quot;;

function App() {
  const inputRef = useRef();
  const passRef = useRef();
  //  const inputRef = useRef([]);  
  // ref를 여러개 관리하고싶을땐 초기값에 빈 배열만들어서 쓰는것이 효율적이다.

  function focus() {
    inputRef.current.focus();
    console.log(inputRef.current);
  }

  function passfocus() {
    passRef.current.focus();
    console.log(passRef.current);
  }

  return (
    &lt;div&gt;
      &lt;input ref={inputRef} type=&quot;text&quot; placeholder=&quot;아이디 또는 이메일&quot; /&gt;
      &lt;input ref={passRef} type=&quot;text&quot; placeholder=&quot;패스워드&quot; /&gt;
      &lt;button&gt;Login&lt;/button&gt;
      &lt;br /&gt;
      &lt;button onClick={focus}&gt;ID focus&lt;/button&gt;
      &lt;button onClick={passfocus}&gt;pass focus&lt;/button&gt;
    &lt;/div&gt;
  );
}

export default App;
</code></pre>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/725f6680-c8f3-4060-91a3-05660df8098b/image.png" alt=""></p>
<h3 id="2-usecontext">2. useContext</h3>
<h4 id="21-usecontext란">2.1. useContext란?</h4>
<p>: 부모에서 자식컴포넌트로 바로 넘겨주는 props라면 큰 불편함없이 바로 넘겨주면 되지만 부모에서 자식의 자식컴포넌트로 2중,3중,4중으로 props넘겨주어야할때 아주 불편하고 에러가 발생하면 에러를 찾기도힘든데 이것을 해결해주는 것이 useContext라는 것이다. context는 별도의 공간에 전역적으로 데이터를 저장하기 때문에 데이터를 필요로하는 컴포넌트에서 context객체를 불러 데이터를 가져다 쓸 수 있다.</p>
<h4 id="22-사용법-1">2.2. 사용법</h4>
<ul>
<li>부모컴포넌트<pre><code class="language-jsx">import React, { createContext } from &quot;react&quot;;
import Children from &quot;./Children&quot;;
</code></pre>
</li>
</ul>
<p>//createContext()는 Context 객체를 생성해주는것이다.
export const AppContext = createContext();</p>
<p>const App = () =&gt; {
  const user = {
    name: &quot;길동&quot;,
    age: 26,
  };</p>
<p>  return (
    &lt;&gt;
      //AppContext.Provider로 자식컴포넌트를 감싸면 자식컴포넌트에서
      //value인 user데이터를 사용할 수 있다.
      &lt;AppContext.Provider value={user}&gt;
        <div>
          <Children />
        </div>
      &lt;/AppContext.Provider&gt;
    &lt;/&gt;
  );
};</p>
<p>export default App;</p>
<pre><code>
- 하위 컴포넌트
```jsx
import React, { useContext } from &quot;react&quot;;
import { AppContext } from &quot;./App&quot;;

const Children = () =&gt; {
  const user = useContext(AppContext);
  return (
          &lt;&gt;
            &lt;h3&gt;user의 이름은 {user.name}입니다.&lt;/h3&gt;
            &lt;h3&gt;user의 나이는 {user.age}입니다.&lt;/h3&gt;
          &lt;/&gt;
  );
};

export default Children;
</code></pre><p>Context를 사용하게되면 컴포넌트가 직접 props 를 전달받지 않고 AppContext 객체 안에있는 user 데이터를 전달받아서 사용할 수 있게된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React-Hooks(2)]]></title>
            <link>https://velog.io/@i_am_heeeun/React-Hooks2</link>
            <guid>https://velog.io/@i_am_heeeun/React-Hooks2</guid>
            <pubDate>Mon, 06 Mar 2023 12:18:40 GMT</pubDate>
            <description><![CDATA[<h3 id="1-usereducer">1. useReducer</h3>
<h4 id="11-usereducer란">1.1. useReducer란?</h4>
<p>: useState보다 더 다양한 컴포넌트 상황에 따라 다양한 상태를 다른 값으로 업데이트해주고 싶을때 사용하는 Hook이다.
useState를 사용할때는 컴포넌트 업데이트 로직을 컴포넌트 내부에서 이루어졌어야했는데 useReducer는 컴포넌트 바깥으로 빼낼 수 있고 이것이 큰 장점이다.</p>
<p>여기서 reducer는 현재상태, 업데이트를 위해 필요한 정보를 담은 액션값을 전달받아 새로운 상태를 반환하는 함수이다. </p>
<h4 id="12-사용법">1.2. 사용법</h4>
<ol>
<li>useReducer의 첫번째 파라미터에 리듀서 함수를 넣고, 두번째 파라미터에는 초기값을 넣어준다.</li>
<li>이 hook을 사용하면 state값과 dispatch함수를 받아온다. 여기서 state는 현재 가리키고 있는 상태이고 dispatch는 액션을 발생시키는 함수이다.</li>
<li>함수안에 파라미터로 액션 값을 넣어주면 리듀서함수가 호출되는 구조이다.<pre><code class="language-jsx">import React, {useReducer} from &#39;react&#39;
</code></pre>
</li>
</ol>
<p>function reducer(state, action){
    switch(action.type){
        case &#39;INCREMENT&#39; : // value에 1을 더하는 액션
             return {value : state.value +1};
        case &#39;DECREMENT&#39; : // value에 1을 빼는 액션
             return {value : state.value -1};
        default:
            return state;
    }</p>
<p>}</p>
<p>const Counter = () =&gt;{
    const[state, dispatch] = useReducer(reducer, {value : 0});</p>
<pre><code>return(
    &lt;div&gt;
        &lt;p&gt;
            현재 카운터 값 : &lt;b&gt;{state.value}&lt;/b&gt;
        &lt;/p&gt;

        &lt;button onClick={() =&gt; dispatch({type : &#39;INCREMENT&#39;})}&gt;+1&lt;/button&gt;
        &lt;button onClick={() =&gt; dispatch({type : &#39;DECREMENT&#39;})}&gt;-1&lt;/button&gt;

    &lt;/div&gt;
);</code></pre><p>}</p>
<p>export default Counter;</p>
<pre><code>
### 2. useMemo
#### 2.1. useMemo란?
: 컴포넌트의 성능을 최적화 하는데 사용되는 hook이다.
useMemo에서 memo는 memoization을 뜻하는데 이는 메모리에 넣기라는 의미이며 동일한 값을 반환하는 함수를 반복적으로 호출해야할때 처음 값을 계산할때 해당 값을 메모리에 저장한 뒤 필요할때마다 다시 계산하지 않고 메모리에서 꺼내서 재사용해 실행 속도를 빠르게 하는 기술이다.
쉽게말해서 함수형 컴포넌트 내부에서 발생하는 연산을 최적화시켜주는 Hook이다.

#### 2.2. 사용법
```jsx
import React, {useMemo,useEffect,useState} from &#39;react&#39;;

function App(){
    const [number, setNumber] = useState(0);
    const [success, setSuccess] = useState(true);

    const succ = useMemo( () =&gt; {
      return{
        isResult: success ? &#39;성공&#39; : &#39;실패&#39;
      }
    },[success])

    useEffect(() =&gt; {
      console.log(&quot;useEffect 호출&quot;);

    },[succ])

    return (
    &lt;&gt;
      &lt;h2&gt; 하루에 담배 몇개 피세요?&lt;/h2&gt;
      &lt;input type=&quot;number&quot; value={number} onChange={(e) =&gt; setNumber(e.target.value)}/&gt;
      &lt;hr/&gt;

      &lt;h2&gt;현재 금연성공??? 실패???&lt;/h2&gt;
      &lt;p&gt;현재: {succ.isResult}&lt;/p&gt;
      &lt;button onClick={() =&gt; setSuccess(!success)}&gt;update&lt;/button&gt;
    &lt;/&gt;
    );
}

export default App;</code></pre><p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/0d8d0b30-03dc-49d6-9c39-8973558cb25b/image.png" alt=""></p>
<p>주의사항 :  값을 재활용하기 위해 따로 메모리를 사용해 저장해놓기때문에 불필요한 값을 모두 memoization 해버리면 성능이 안좋아질 수 있다. 그렇기때문에 필요할때만 사용하도록 하자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React- Hooks(1)]]></title>
            <link>https://velog.io/@i_am_heeeun/React-Hooks1</link>
            <guid>https://velog.io/@i_am_heeeun/React-Hooks1</guid>
            <pubDate>Sun, 05 Mar 2023 14:20:49 GMT</pubDate>
            <description><![CDATA[<p>Hooks는 리액트 V16.8에 새로 도입된 기능으로 함수형 컴포넌트에서도 상태 관리를 할 수 있는 useState, 렌더링 직후 작업을 설정하는 useEffect 등의 기능을 제공하여 기존의 함수형 컴포넌트에서 할 수 없었던 다양한 작업을 할 수 있게 해준다.</p>
<p>리액트에서 기본적으로 제공하는 Hooks는 총9개이다.
오늘은 useState와 useEffect를 알아보도록 하자.</p>
<h3 id="1-usestate">1. useState</h3>
<h4 id="11-usestate란">1.1. useState란??</h4>
<p>: useState는 가장 기본적인 Hook이며 컴포넌트에서 state(상태)를 관리할 수 있다. 만약 함수형 컴포넌트에서 상태를 관리해야 한다면 useState를 사용하면 된다.</p>
<h4 id="12-사용법">1.2. 사용법</h4>
<ol>
<li>리액트 패키지에서 useState함수를 불러온다.</li>
<li>useState함수를 호출하면 배열이 반환되는데 첫번째 원소의 value는 현재 상태값 변수이고 두번째 원소 setValue는 상태 값을 갱신해주는 Setter 함수이다. useState괄호안의 값은 상태의 초기값이다.<pre><code class="language-jsx">import React, {useState} from &#39;react&#39;
</code></pre>
</li>
</ol>
<p>const Counter = () =&gt;{
    const [value, setValue] = useState(0);</p>
<pre><code>return(
    &lt;div&gt;
        &lt;p&gt;
            현재 카운터 값 &lt;b&gt;{value}&lt;/b&gt;
        &lt;/p&gt;
        &lt;button onClick={()=&gt;setValue(value+1)}&gt;+1&lt;/button&gt;
        &lt;button onClick={()=&gt;setValue(value-1)}&gt;-1&lt;/button&gt;
    &lt;/div&gt;
);</code></pre><p>}</p>
<p>export default Counter;</p>
<pre><code>

### 2. useEffect
#### 2.1. useEffect란?
: 컴포넌트가 렌더링될때마다 특정 작업을 실행할 수 있도록하는 Hook이다.
 컴포넌트가 마운트 됐을때(처음 생성) 언마운트됐을때(제거될때) 그리고 업데이트 될때 특정 작업을 실행할 수 있다.

#### 2.2. 사용법
1. 리액트 패키지에서 useEffect함수를 불러온다.
2. 컴포넌트가 화면에 처음 마운트 됐을때 한번만 실행하고 싶을땐 deps위치에 빈배열을 넣는다.
3. 컴포넌트가 리렌더링될때마다 실행하고 싶을땐 배열을 생략한다.
4. 컴포넌트의 특정값이 업데이트될때마다 실행하고 싶을땐 deps에 검사하고 싶은 값을 넣어준다.
```jsx
import React, {useEffect} from &#39;react&#39;;

const Effect = () =&gt; {

  useEffect(()=&gt;{
    console.log(&quot;마운트 될때만 실행&quot;);
  },[]);


  useEffect(()=&gt;{
    console.log(&quot;렌더링 시 실행&quot;);
  });

  useEffect(()=&gt;{
    console.log(&quot;value값이 업데이트 될때마다 실행&quot;);
  },[value]);

}

export default Effect;
</code></pre><p>useEffect는 기본적으로 렌더링되고 난 직후마다 실행되며, 두 번째 파라미터 배열에 무엇을 넣는지에 따라 실행되는 조건이 달라진다.
컴포넌트가 언마운트되기 전이나 업데이트되기 직전에 어떠한 작업을 수행하고 싶다면 useEffect 에서 cleanup 함수를 반환해 주어야 합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React- Component]]></title>
            <link>https://velog.io/@i_am_heeeun/React-Component</link>
            <guid>https://velog.io/@i_am_heeeun/React-Component</guid>
            <pubDate>Wed, 01 Mar 2023 15:13:41 GMT</pubDate>
            <description><![CDATA[<p>리액트의 컴포넌트 선언방식은 두가지로 나뉜다. 첫번째는 클래스형 컴포넌트, 두번째는 함수형 컴포넌트이다.</p>
<p>이제 이 두가지 선언방식에 대해서 알아보자.</p>
<h3 id="1-class-component">1. Class Component</h3>
<ul>
<li>클래스형 컴포넌트에서는 Component를 상속받아야하고 render() 함수가 필수적으로 있어야한다.</li>
<li>state와 LifeCycle API 사용이 가능하다.</li>
<li>임의 메서드를 정의할 수 있다.</li>
<li>과거에는 클래스 컴포넌트에서만 state와 LifeCycle API 사용할수 있었기 때문에 state가 변경되고 업데이트가 되어야하면 클래스 컴포넌트를 만들었다.</li>
<li>프로퍼티를 사용해야할때 this.props 를 사용하여 가져와야한다.<pre><code class="language-jsx">import React, {Component} from &#39;react&#39;;
</code></pre>
</li>
</ul>
<p>class App extends Component{
     render(){
      const {id,pass} = this.props;
      return( 
        &lt;&gt;
         <div className="react">아이디 : {id} </div>
         <div className="react">비밀번호 : {pass} </div>
        &lt;/&gt;
      );
    }
}</p>
<p>export default App;</p>
<pre><code>
- state를 사용해야할때는 생성자 메서드를 사용하여 초기 state값을 설정한다. 이때 super(props)를 호출해주어야 한다.
this.setState 함수로 state값을 변경할 수 있다.
```jsx
import React, {Component} from &#39;react&#39;

class Counter extends Component {

    constructor(props) {
        super(props); //자바스크립트 에서는 super는 부모 클래스 생성자를 가리킨다(리액트에서는 React.Component)
        this.state = {
            Num : 0
        };
    }

    render(){
        const {Num} = this.state;
        return(
            &lt;div&gt;
                &lt;h1&gt;값 : {Num}&lt;/h1&gt;
                &lt;button
                    onClick={()=&gt;{
                        this.setState({
                            Num : Num + 1
                        });
                    }}
                &gt;
                    +1
                &lt;/button&gt;
            &lt;/div&gt;
        );
    }
}

export default Counter;</code></pre><h3 id="2-functional-component">2. Functional Component</h3>
<ul>
<li>클래스 컴포넌트와 비교해서 간결하게 코드를 작성할 수 있다. 함수 자체가 렌더함수이기 때문에 render()함수를 사용하지 않아도 된다. </li>
<li>메모리 자원을 덜 사용한다.</li>
<li>React 16버전이전까지는 함수형 컴포넌트에서는 state 및 lifecycle Api 기능을 지원해주지 않아서 변화가 없는 정적인 컴포넌트를 만들 때 사용했다.</li>
<li>프로퍼티를 사용해야할때 parameter로 props를 전달받아 가져온다.<pre><code class="language-jsx">import React from &#39;react&#39;;
</code></pre>
</li>
</ul>
<p>const App = (id,pass) =&gt; {
      return(
        &lt;&gt;
         <div className="react">아이디: {id}</div>
         <div className="react">비밀번호: {pass}</div>
        &lt;/&gt;
      );
}</p>
<p>export default App;</p>
<pre><code>- 함수형 컴포넌트에선 setState로 state값을 변경한다. 

```jsx
import React , {useState} from &#39;react&#39;;
const App = () =&gt; {
  //첫번째 원소는 state이름, 두번째원소는 state의 값을 변경해주는 함수이름이다.
  const[num, setNum] = useState(0); //useState의파라미터는 초기값이다.

  const increase = () =&gt; {
       setNum(num +1)
  }

  return (
     &lt;&gt;
      &lt;h1&gt;{num}&lt;/h1&gt;
      &lt;button onClick ={increase} &gt;+1&lt;/button&gt;
     &lt;/&gt;
  );
}
export default App;</code></pre><p>현재 리액트 공식 매뉴얼에는 컴포넌트를 작성할때 클래스컴포넌트보다 함수형 컴포넌트를 사용하도록 권장하고있다. </p>
<p>함수형컴포넌트의 state와 LifeCycle사용이 불가능하다는 단점을 리액트 16버전부터 Hook이라는걸 지원하여 보완하였다. </p>
<p>공식 매뉴얼에서 함수형 컴포넌트를 사용하도록 권장하고있다고 하더라도 유지보수를 진행해야할 상황이 있을 수 있기때문에 클래스형 컴포넌트도 잘알아두도록하자. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React - JSX]]></title>
            <link>https://velog.io/@i_am_heeeun/React-JSX</link>
            <guid>https://velog.io/@i_am_heeeun/React-JSX</guid>
            <pubDate>Mon, 20 Feb 2023 12:25:23 GMT</pubDate>
            <description><![CDATA[<h3 id="1-jsx란">1. JSX란??</h3>
<ul>
<li>자바스크립트의 확장 문법이며 XML과 매우 비슷하게 생겼다.</li>
<li>JSX로 작성된 코드는 브라우저에서 실행되기 전에 코드가 번들링되는 과정에서 
바벨을 사용하여 일반자바스크립트 형태의 코드로 변환된다.</li>
</ul>
<h3 id="2-jsx의-장점">2. JSX의 장점</h3>
<ul>
<li>보기 쉽고 익숙하다.</li>
<li>활용도가 높다.</li>
</ul>
<h3 id="3-jsx문법">3. JSX문법</h3>
<h4 id="31-컴포넌트에-여러-요소가-있다면-반드시-부모-요소-하나로-감싸야한다">3.1. 컴포넌트에 여러 요소가 있다면 반드시 부모 요소 하나로 감싸야한다.</h4>
<pre><code class="language-jsx">import React from &#39;react&#39;;

function App(){
     return(
        &lt;h1&gt;VELOG&lt;/h1&gt;
          &lt;h2&gt;TSTORY&lt;/h2&gt;
    )
}

export default App;</code></pre>
<p>위의 코드를 실행하면 아래와 같은 오류가 나타난다.
<img src="https://velog.velcdn.com/images/i_am_heeeun/post/22ffaff8-d68f-4041-9300-78b0d5c5ac01/image.png" alt=""></p>
<p>요소 여러개가 부모 요소 하나에 의해 감싸져 있지 않기 때문에 일어나는 오류이다. 
꼭 감싸주어야 하는 이유는 Virtual Dom에서 컴포넌트 변화를 감지할때 효율적으로 비교할 수 있도록 컴포넌트 내부는 하나의 DOM 트리 구조로 이루어져야 한다는 규칙이 있기 때문이다.</p>
<p>그렇기 때문에 Fragment라는 기능을 사용하여 감싸주면 오류가 해결된다.
꼭 Fragment가 아니더라도 div요소를 사용해도 된다.</p>
<pre><code class="language-jsx">import React, {Fragment} from &#39;react&#39;;


function App(){
     return(
  //Fragment를 사용하는 두가지 방법
      &lt;Fragment&gt;
        &lt;h1&gt;VELOG&lt;/h1&gt;
          &lt;h2&gt;TSTORY&lt;/h2&gt;
      &lt;/Fragment&gt;

      &lt;&gt;
        &lt;h1&gt;VELOG&lt;/h1&gt;
        &lt;h2&gt;TSTORY&lt;/h2&gt;
      &lt;/&gt;
    )
}

export default App;</code></pre>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/eab95bc1-9049-418f-bd48-282b76652cfa/image.png" alt=""></p>
<h4 id="32-자바스크립트-사용가능">3.2. 자바스크립트 사용가능</h4>
<p>: JSX안에서 자바스크립트 표현식을 { }로 감싸면 사용가능하다.</p>
<pre><code class="language-jsx">import React ,{Fragment} from &#39;react&#39;;

function App(){
  const name = &#39;REACT&#39;;
     return(
    &lt;Fragment&gt;
    &lt;h1&gt;{name}&lt;/h1&gt;
      &lt;h2&gt;TSTORY&lt;/h2&gt;
    &lt;/Fragment&gt;
    )
}
export default App;</code></pre>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/6e90a5d5-ee89-4bfe-9636-89bd97f31e39/image.png" alt=""></p>
<h4 id="33-if문-대신-조건부-연산자-사용">3.3. if문 대신 조건부 연산자 사용</h4>
<p>: JSX내부의 자바스크립트 표현식에선 if문을 사용할 수 없다.
 조건에 따라 다른 내용을 렌더링해야 할때는 JSX밖에서 if문을 사용하여 사전에 값을 설정하거나 { }안에 조건부 연산자 즉 삼항연산자를 사용해야한다.</p>
<pre><code class="language-jsx">import React from &#39;react&#39;;

function App(){
     const name =&#39;REACT&#39;;
      return(
        &lt;&gt;
        {name == &#39;REACT&#39; ? 
          (
              &lt;h1&gt;REACT입니다.&lt;/h1&gt;
          ) :
          (
            &lt;h1&gt;REACT가 아닙니다.&lt;/&lt;h1&gt;
          )
        }
        &lt;/&gt;

    );
}

export default App;</code></pre>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/b9fb6db4-25f3-4c4a-8b11-1b210a76e7d4/image.png" alt=""></p>
<pre><code class="language-jsx">import React from &#39;react&#39;;

function App(){
     const name =&#39;VUE&#39;;
      return(
        &lt;&gt;
        {name == &#39;REACT&#39; ? 
          (
              &lt;h1&gt;REACT입니다.&lt;/h1&gt;
          ) :
          (
            &lt;h1&gt;REACT가 아닙니다.&lt;/&lt;h1&gt;
          )
        }
        &lt;/&gt;

    );
}

export default App;</code></pre>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/43ad9112-e0c4-4978-b1a9-45e429fbde6b/image.png" alt=""></p>
<h4 id="34-class-대신-classname-사용">3.4. class 대신 className 사용</h4>
<p>: 일반 HTML에서는 CSS클래스를 사용할때는 아래와 같은 코드를 작성하여 설정한다. </p>
<pre><code class="language-javasctipt">&lt;div class=&quot;myclass&quot;&gt; &lt;/div&gt;</code></pre>
<p>하지만 JSX에서는 class가 아닌 className을 사용한다.</p>
<pre><code class="language-jsx">import React from &#39;react&#39;;
import &#39;./App.css&#39;;

function App(){
     const name =&#39;REACT&#39;;
      return(
        &lt;div className=&quot;react&quot;&gt;{name}&lt;/div&gt;
    );
}

export default App;</code></pre>
<p>className이 아닌 class를 사용해도 스타일이 적용되기는 하나 개발자 도구의 console탭에 다음과 같은 경고가 나타난다.
 <img src="https://velog.velcdn.com/images/i_am_heeeun/post/ca8cba7d-ebde-40db-b343-c605c4e040da/image.png" alt=""></p>
<p>예전에는 class를 사용하면 오류가 발생하고 css가 적용되지 않았는데 리액트 v16 이상부터는 class를 className으로 변환시켜주고 경고를 띄운다.</p>
<h4 id="35-태그는-꼭-닫아야-한다">3.5. 태그는 꼭 닫아야 한다!</h4>
<p>: HTML 코드를 작성할때 가끔씩 태그를 닫지 않는 상태로 코드를 작성하기도 한다. 
예를 들면 </p>
<pre><code class="language-html">&lt;input&gt;&lt;/input&gt; //input요소를 
&lt;input&gt; //이런식으로 닫지않고 입력해도 작동한다.</code></pre>
<p>하지만 JSX에서는 input 태그를 닫지않으면 오류가 발생한다.
<img src="https://velog.velcdn.com/images/i_am_heeeun/post/eb85ec45-bdd6-43d4-94a0-3703e09e5571/image.png" alt=""></p>
<p>태그사이에 별도의 내용이 들어가지 않는 경우에는 태그를 선언하면서 동시에 닫을 수 있는 self-closing 태그를 사용할 수 있다.</p>
<pre><code class="language-jsx">import React from &#39;react&#39;;
import &#39;./App.css&#39;;

function App(){
     const name =&#39;REACT&#39;;
      return(
      &lt;&gt;
          &lt;div class=&quot;react&quot;&gt;{name}&lt;/div&gt;
          &lt;input /&gt;  // self-closing 태그
      &lt;/&gt;
    );
}

export default App;
</code></pre>
<h4 id="36-주석작성하는-법">3.6. 주석작성하는 법</h4>
<p>: 일반 자바스크립트에서 주석을 작성할때와 조금 다르다.</p>
<pre><code class="language-jsx">import React from &#39;react&#39;;
import &#39;./App.css&#39;;

function App(){
     const name =&#39;REACT&#39;;
      return(
      &lt;&gt;
        {/* 주석 작성 */}
        &lt;div
            className=&quot;react&quot; //시작 태그를 여러줄로 작성 하게 된다면 
                             //여기에 주석 작성 가능  
        &gt;
          {name}
        &lt;/div&gt;
        // 여기는 작성불가
        /* 이것도 불가 */

      &lt;/&gt;
    );
}

export default App;
</code></pre>
<p>JSX는 { } 안에 작성하거나 태그안에 작성해야 주석으로 인정된다.
{/ * 주석작성 /}
{  // 주석 작성 }</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React - 개발환경 구축]]></title>
            <link>https://velog.io/@i_am_heeeun/React-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%B6%95</link>
            <guid>https://velog.io/@i_am_heeeun/React-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%B6%95</guid>
            <pubDate>Sat, 18 Feb 2023 09:55:26 GMT</pubDate>
            <description><![CDATA[<h3 id="개발환경-정보">개발환경 정보</h3>
<ul>
<li><p>Visual Studio Code</p>
<img src="https://velog.velcdn.com/images/i_am_heeeun/post/00632e02-cace-4bca-8539-92e222639748/image.jpeg" width="90" height="200"/>
</li>
<li><p>React </p>
<img src="https://velog.velcdn.com/images/i_am_heeeun/post/b5a9739b-110d-46d3-9bfd-a95406406dec/image.png" width="200" height="200"/>
</li>
<li><p>Node.js</p>
<img src="https://velog.velcdn.com/images/i_am_heeeun/post/3aaa4859-be92-4fb3-9ba4-30150c5f9828/image.png" width="200" height="200"/>


</li>
</ul>
<ul>
<li>yarn<ul>
<li>Node.js 자바스크립트 런타임 환경을 위해 페이스북이 2016년 개발한 소프트웨어 패키지 시스템<img src="https://velog.velcdn.com/images/i_am_heeeun/post/a64b9e05-b7e9-4822-927f-2b795c0458c3/image.png" width="200" height="200"/>

</li>
</ul>
</li>
</ul>
<hr>
<h2 id="설치시작">설치시작~!</h2>
<h3 id="1-nodejs">1. Node.js</h3>
<h4 id="11-구글에-nodejs-검색한-후-홈페이지-들어가서-lts버전-다운받기">1.1. 구글에 Node.js 검색한 후 홈페이지 들어가서 LTS버전 다운받기</h4>
<p> <a href="https://nodejs.org/ko/">클릭하여 Node.js홈페이지로 이동</a></p>
<p> <img src="https://velog.velcdn.com/images/i_am_heeeun/post/e97a39ed-2e9e-4796-a51a-e8cc6e427642/image.png" alt=""></p>
<h4 id="12-설치파일을-클릭하여-설치해주기">1.2. 설치파일을 클릭하여 설치해주기</h4>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/bef48e0a-ca3d-41fc-815e-8e283a91cce1/image.png" alt=""></p>
<h4 id="계속-continue-눌러주면-설치-끝">계속 Continue 눌러주면 설치 끝!!</h4>
<h3 id="2-visual-studio-code">2. Visual Studio Code</h3>
<h4 id="21-구글에-visual-studio-code를-검색한-후-홈페이지-들어가서-download클릭">2.1. 구글에 Visual Studio Code를 검색한 후 홈페이지 들어가서 Download클릭</h4>
<p><a href="https://code.visualstudio.com/">클릭하여 공식홈페이지로 이동</a></p>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/1bd26685-5c7a-42ac-a2e0-7dcf01decaa1/image.png" alt=""></p>
<h4 id="22-다운받은-파일을-클릭하면-자동으로-visual-studio-code가-다운받아진다">2.2. 다운받은 파일을 클릭하면 자동으로 visual studio code가 다운받아진다.</h4>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/1cc9feba-0736-4453-b202-8f9838f3c32f/image.png" alt=""></p>
<h4 id="23-자신이-만들고-싶은-프로젝트-위치에-폴더-생성">2.3. 자신이 만들고 싶은 프로젝트 위치에 폴더 생성</h4>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/3b4a07d6-a26b-4cf1-84d0-9560d1379c4f/image.png" alt=""></p>
<h4 id="24-visual-studio-code를-실행">2.4. Visual Studio Code를 실행</h4>
<p>   파일- Open Folder를 선택한 후 내가 만든 폴더를 연다.
<img src="https://velog.velcdn.com/images/i_am_heeeun/post/0717dd20-39f4-4bf9-b753-5361febe2c55/image.png" alt=""></p>
<h3 id="4-yarn">4. Yarn</h3>
<h4 id="41-brew를-이용해서-yarn-다운받기">4.1. brew를 이용해서 yarn 다운받기</h4>
<pre><code>brew install yarn</code></pre><p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/6359faa0-cdc1-4770-bb9a-054cd059e164/image.png" alt="">
끝!</p>
<h3 id="5-react-프로젝트-파일생성">5. React 프로젝트 파일생성</h3>
<h4 id="51-리액트-프로젝트에-필요한-패키지들을-묶어-생성해주는-도구는-create-react-app를-다운받는다">5.1. 리액트 프로젝트에 필요한 패키지들을 묶어 생성해주는 도구는 create-react-app를 다운받는다</h4>
<pre><code>yarn global add create-react-app</code></pre><h4 id="52-터미널에서-create-react-app-프로젝트명-명령어를-입력하여-프로젝트-생성">5.2. 터미널에서 create-react-app &quot;프로젝트명&quot; 명령어를 입력하여 프로젝트 생성</h4>
<pre><code>create-react-app study</code></pre><p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/2f3cea09-1581-464d-8931-63aefc9207a8/image.png" alt=""></p>
<h4 id="근데-packagejson파일을-찾을-수-없다는-에러가-발생하여-구글링-해봤는데-yarn-init-해주면-해결된다고-한다">근데 package.json파일을 찾을 수 없다는 에러가 발생하여 구글링 해봤는데 yarn init 해주면 해결된다고 한다.</h4>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/08a7eeb9-6be6-424f-810d-6ce802d539e4/image.png" alt="">
질문에 열심히 답하면 package.json을 만들어줌</p>
<p>다시 create-react-app study를 입력하면 프로젝트가 생성된다.
<img src="https://velog.velcdn.com/images/i_am_heeeun/post/feb083a2-0bba-4c3c-9296-d2d0c8f1439a/image.png" alt=""></p>
<h3 id="6-실행">6. 실행</h3>
<h4 id="61-터미널에-yarn-start를-하면-실행이-잘되는걸-볼수있다">6.1. 터미널에 yarn start를 하면 실행이 잘되는걸 볼수있다.</h4>
<pre><code>yarn start</code></pre><p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/218b9621-2315-4b94-b314-818e2c74565c/image.png" alt=""></p>
<h3 id="끝">끝~!!!</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[React - 리액트]]></title>
            <link>https://velog.io/@i_am_heeeun/React%EA%B0%9C%EB%85%90</link>
            <guid>https://velog.io/@i_am_heeeun/React%EA%B0%9C%EB%85%90</guid>
            <pubDate>Mon, 13 Feb 2023 11:04:22 GMT</pubDate>
            <description><![CDATA[<p>본격적인 프로젝트를 시작하기 전에 리액트에 대한 개념이 부족하다고 느껴 스터디 첫번째 시간으로 개념을 정리해보도록 하겠다. </p>
<h3 id="--react">- React</h3>
<pre><code> 자바스크립트 라이브러리로 사용자 인터페이스를 만드는 데 사용한다. MVC, MVW 등인 프레임워크와 달리,
 오직 V(View)만 신경 쓰는 라이브러리이다.
</code></pre><h3 id="--jsx-javascript-xml">- JSX (Javascript XML)</h3>
<pre><code>- Javascript에 XML를 추가한 확장된 문법이다.
- UI가 어떻게 생겨야 하는지 설명하기 위해 React와 함께 사용할 것을 권장한다.
  리액트는 JSX 사용이 필수가 아니지만 대부분의 사람들은 Javascipt 코드 안에서 UI관련 작업을 할때 시각적으로 
  더 도움이 된다고 생각하여 많이 사용한다.
- 브라우저에서 실행하기 전에 바벨을 사용하여 일반 자바스크립트 형태의 코드로 변환된다.</code></pre><p>ex)</p>
<pre><code class="language-jsx">const name = &#39;Park&#39;;
const element = &lt;h1&gt;Hello, {name}&lt;/h1&gt;;
//JSX 중괄호 안에는 유효한 모든 Javascript 표현식을 넣을 수 있다.
//JSX는 하나의 파일에 자바스크립트와 HTML을 동시에 작성하여 편리하다.</code></pre>
<h3 id="--babel">- babel</h3>
<pre><code>- Javascript 컴파일러이다. 
- Babel을 이용하면 ES6 이상의 최신 문법으로 작성한 자바스크립트 코드를 ES5 이하의 예전 문법으로 작성한 것 처럼 
  소스 코드 내의 문법의 형태를 변경할 수 있다. </code></pre><h3 id="--element">- Element</h3>
<pre><code>- 리액트의 가장 작은 단위이다.
- 엘리먼트는 화면에 표시할 내용을 기술한다.
- 엘리먼트와 컴포넌트를 혼동할 수 있다. 엘리먼트는 컴포넌트의 &quot;구성요소&quot;이다.</code></pre><h3 id="--component-컴포넌트">- Component 컴포넌트</h3>
<pre><code> - 리액트 프로젝트에서 특정 부분이 어떻게 생길지 정하는 선언체가 있는데, 이를 컴포넌트라고 한다.
 - 컴포넌트는 다른 프레임워크에서 사용자 인터페이스를 다룰 때 사용하는 템플릿과는 다른개념이다.
 - 컴포넌트는 재사용이 가능한 API로 수많은 기능들을 내장하고 있으며, 컴포넌트 하나에서 해당 컴포넌트의 생김새와 작동 방식을 
     정의한다.
 - 컴포넌트를 정의하는 가장 간단한 방법은 Javascript 함수를 작성하는 것이다.
 - 컴포넌트의 이름은 항상 대문자로 시작한다. 소문자로 시작하는 것은 DOM태그로 처리한다.
 - 버튼, 폼, 다이얼로그, 화면등의 모든것들이 컴포넌트로 표현된다.</code></pre><h3 id="--함수-컴포넌트-예시">- 함수 컴포넌트 예시</h3>
<pre><code class="language-jsx">function Test(props){
     return &lt;h1&gt;Hello, {props.name}&lt;/h1&gt;; 
} //props는 속성을 나타내는 데이터이다.</code></pre>
<h3 id="--클래스-컴포넌트-예시">- 클래스 컴포넌트 예시</h3>
<pre><code class="language-jsx">class Test extends React.Component {
    render(){
      return &lt;h1&gt;Hello, {this.props.name}&lt;/h1&gt;;
    }
}</code></pre>
<h3 id="--props-프로퍼티">- props (프로퍼티)</h3>
<pre><code>- properties의 줄임말이다.
- 상위컴포넌트가 하위컴포넌트에 값을 전달할때 사용한다.
- 프로퍼티는 수정할 수 없다는 특징이 있다.</code></pre><h3 id="--rendering-렌더링">- Rendering 렌더링</h3>
<pre><code>  - 사용자 화면에 뷰를 보여 주는 것을 렌더링이라고 한다.
  - 리액트 라이브러리는 데이터가 변할때마다 새롭게 리렌더링하면서 성능을 아끼고, 최적의 사용자 경험을 제공한다. </code></pre><p>리액트 라이브러리가 새롭게 리렌더링하면서 성능을 아끼고, 최적의 사용자 경험을 제공할 수 있는 이유를 알려면 리액트 컴포넌트가 최초로 실행한 &#39;초기 렌더링&#39;과 컴포넌트의 데이터 변경으로 다시 실행되는 &#39;리렌더링&#39; 개념을 이해해야한다.</p>
<h4 id="--초기-렌더링">- 초기 렌더링</h4>
<p>어떤 UI관련 프레임워크, 라이브러리를 사용하든지 간에 맨 처음 어떻게 보일지를 정하는 초기 렌더링이 필요하다. 리액트에서는 render함수가 있다.</p>
<pre><code class="language-javascript">render() {...}</code></pre>
<p>render함수는 컴포넌트가 어떻게 생겼는지 정의하는 역할을 한다. 
이 함수는 html형식의 문자열을 반환하는게 아니라 뷰가 어떻게 생겼고 어떻게 작동하는지에 대한 정보를 지닌 객체를 반환한다.
컴포넌트 내부에는 또 다른 컴포넌트들이 들어갈 수 있다. 이때 render함수를 실행하면 그 내부에 있는 컴포넌트들도 재귀적으로 렌더링한다. 이렇게 최상위 컴포넌트의 렌더링 작업이 끝나면 지니고 있는 정보들을 사용하여 HTML 마크업을 만들고 이를 우리가 정하는 실제 페이지의 DOM요소 안에 주입한다.</p>
<h4 id="--조화-과정">- 조화 과정</h4>
<p>리액트 라이브러리에서 중요한 부분인 업데이트를 어떻게 진행하는지 알아보자.
리액트에서 뷰를 업데이트할때는 업데이트 과정이라고 하기보다는 조화 과정을 거친다라고 하는것이 더 정확한 표현이다. 컴포넌트에서 데이터에 변화가 있을 때 우리가 보기에는 뷰가 변형되는 것처럼 보이지만 사실은 새로운 요소로 갈아 끼우기 때문이다. </p>
<p> 이 작업또한 render함수가 한다. 컴포넌트는 데이터를 업데이트했을 때 새로운 데이터를 가지고 render함수를 또 다시 호출한다. 그러면 그 데이터를 지닌 뷰를 생성해낸다.
이때 render함수가 반환하는 결과를 곧바로 DOM에 반영하지 않고 이전에 render함수가 만들었던 컴포넌트 정보와 현재 render함수가 만든 컴포넌트 정보를 비교한다. </p>
<p> 자바스크립트를 사용하여 두가지 뷰를 최소한의 연산으로 비교한 후 둘의 차이를 알아내 최소한의 연산으로 DOM 트리를 업데이트하는 것이다. 
결국 방식 자체는 루트노드부터 시작하여 전체 컴포넌트를 처음부터 다시 렌더링하는 것처럼 보이지만 사실 최적의 자원을 사용하여 이를 수행하는 것이다.</p>
<h3 id="--virtual-dom">- Virtual Dom</h3>
<pre><code>  - 리액트의 주요 특징 중 하나이다.
  - Virtual Dom을 사용하면 실제 DOM에 접근하여 조작하는 대신, 이를 추상화한 자바스크립트 객체를 구성하여 사용한다. 
      마치 실제 DOM의 가벼운 사본과 비슷하다.
  - DOM을 반복적으로 직접 조작하면 그만큼 브라우저가 렌더링을 자주하게 되고, 그만큼 자원이 많이 소모하게되는 문제를 해결하기 
      위한 기술이다.
</code></pre><p>리액트에서 데이터가 변하여 웹브라우저에 실제 DOM을 업데이트할 때는 다음 세가지 절차를 밟는다.</p>
<ol>
<li>데이터를 업데이트하면 전체 UI를 Virtual DOM에 리렌더링한다.</li>
<li>이전 Virtual DOM에 있던 내용과 현재 내용을 비교한다.</li>
<li>바뀐 부분만 실제 DOM에 적용한다.</li>
</ol>
<hr>
<p>참고 자료 : 리액트르 다루는 기술</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL- 데이터베이스 I/O 메커니즘]]></title>
            <link>https://velog.io/@i_am_heeeun/SQL-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-IO-%EB%A9%94%EC%BB%A4%EB%8B%88%EC%A6%98</link>
            <guid>https://velog.io/@i_am_heeeun/SQL-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-IO-%EB%A9%94%EC%BB%A4%EB%8B%88%EC%A6%98</guid>
            <pubDate>Tue, 15 Nov 2022 12:39:19 GMT</pubDate>
            <description><![CDATA[<p>데이터베이스 I/O 효율화 및 버퍼캐시 최적화 방법을 이해하는데 필요한 기본 개념과 원리를 알아보도록 하자.</p>
<h3 id="블록-단위-io">블록 단위 I/O</h3>
<p>Oracle을 포함한 모든 DBMS에서 I/O는 블록단위로 이뤄진다. 즉 하나의 레코드를 읽더라도 레코드가 속한 블록 전체를 읽는다.</p>
<p>SQL성능을 좌우하는 가장 중요한 성능지표는 액세스하는 블록개수이다. 옵티마이저의 판단에 가장 큰 영향을 미치는 것도 액세스해야 할 블록개수이다.</p>
<p>블록단위 I/O는 버퍼캐시와 데이터 파일 I/O 모두에 적용된다.</p>
<ul>
<li>데이터 파일에서 DB버퍼캐시로 블록을 적재할때</li>
<li>데이터 파일에서 블록을 직접 읽고 쓸때</li>
<li>버퍼캐시에서 블록을 읽고 쓸 때</li>
<li>버퍼캐시에서 변경된 블록을 다시 데이터 파일에 쓸 때</li>
</ul>
<hr>
<h3 id="메모리-io-vs-디스크-io">메모리 I/O VS 디스크 I/O</h3>
<h4 id="1-io-효율화-튜닝의-중요성">1. I/O 효율화 튜닝의 중요성</h4>
<ul>
<li>모든 DBMS는 읽고자 하는 블록을 먼저 버퍼캐시에서 찾아보고, 없을 경우에만 디스크에서 읽어 버퍼 캐시에 적재한 후 읽기/쓰기 작업을 수행한다.</li>
<li>물리적인 디스크 I/O가 필요할 때면 서버 프로세스는 시스템에 I/O Call을 하고 잠시 대기상태에 빠진다. 디스크 I/O경합이 심할수록 대기 시간도 길어진다.</li>
<li>디스크 I/O를 최소화하고 버퍼캐시 효율을 높이는 것이 데이터베이스 I/O 튜닝의 목표가 된다.</li>
</ul>
<h4 id="2-버퍼-캐시-히트율">2. 버퍼 캐시 히트율</h4>
<p>: 버퍼 캐시 효율을 측정하는 지표로서, 전체 읽은 블록 중에서 메모리 버퍼 캐시에서 찾은 비율을 나타낸다.</p>
<ul>
<li><p>버퍼캐시히트율(BCHR, Buffer Cache Hit Ratio)는 물리적인 디스크 읽기를 수반하지 않고 곧바로 메모리에서 블록을 찾은 비율을 말한다.</p>
</li>
<li><p>모든 블록 읽기는 버퍼 캐시를 통해 이뤄진다. 읽고자 하는 블록을 먼저 버퍼 캐시에서 찾아보고, 없을 때만 디스크로부터 버퍼캐시에 적재한 후 읽어 들인다.</p>
</li>
</ul>
<blockquote>
<p>BCHR = (버퍼 캐시에서  곧바로 찾은  블록 수 / 총 읽은 블록 수) X 100</p>
</blockquote>
<ul>
<li>BCHR은 주로 시스템 전체적인 관점에서 측정하지만, 개별 SQL측면에서 구해볼 수도 있는데 이 비율이 낮은 것이 SQL 성능을 떨어뜨리는 주원인이다.</li>
</ul>
<p>&lt;사진&gt;</p>
<p>위의 샘플의 BCHR을 구해보자
버퍼캐시에서 읽은 블록 수는 Query와 Current항목을 더해서 구한다.</p>
<blockquote>
<ul>
<li>총 읽은 블록수 = 822+0 = 822</li>
</ul>
</blockquote>
<ul>
<li>버퍼캐시에서 곧바로 찾은 블록수 = 822-18 =804</li>
<li>BCHR = (822-18) / 822 = 97.8%</li>
</ul>
<p>100개 블록읽기를 요청하면 98개는 메모리에서 찾고 나머지 2개는 디스크 I/O를 발생시켰다는 뜻이다.</p>
<ul>
<li><p>논리적인 블록 요청 횟수를 줄이고, 물리적으로 디스크에서 읽어야 할 블록 수를 줄이는 것이 I/O효율화 튜닝의 핵심원리이다.</p>
</li>
<li><p>논리적으로 읽어야 할 블록수의 절대량이 많다면 반드시 튜닝을 통해 논리적인 블록읽기를 최소화해야 한다.</p>
</li>
</ul>
<h4 id="3-네트워크-파일시스템-캐시가-io-효율에-미치는-영향">3. 네트워크, 파일시스템 캐시가 I/O 효율에 미치는 영향</h4>
<p>: SQL을 작성할 때는 다양한 I/O 튜닝 기법을 사용해서 네트워크 전송량을 줄이려고 노력하는 것이 중요하다.</p>
<ul>
<li><p>RAC같은 클러스터링 데이터베이스 환경에선 인스턴스 간 캐시된 블록을 공유하므로 메모리 I/O 성능에도 네트워크 속도가 지대한 영향을 미친다.
*RAC (Real Application Cluster)
: 여러개의 인스턴스가 하나의 데이터베이스를 액세스 할 수 있는 것. 어플리케이션에서 접속할 수 있는 통로는 여러개이며 데이터베이스는 하나인 형태이다.</p>
<blockquote>
<p>Oracle RAC = N개의 인스턴스 + 1개의 데이터베이스</p>
</blockquote>
</li>
<li><p>네트워크 문제이든 파일시스템 문제이든 I/O 성능에 관한 가장 확실하고 근본적인 해결책은 논리적인 블록 요청횟수를 최소화하는 것이다.</p>
</li>
</ul>
<hr>
<h3 id="sequential-io-vs-random-io">Sequential I/O VS Random I/O</h3>
<p>&lt;사진&gt;</p>
<blockquote>
<ul>
<li>Sequential 액세스</li>
</ul>
</blockquote>
<ul>
<li>코드간 논리적 또는 물리적인 순서에 따라 차례대로 읽어 나가는 방식이다.</li>
<li>인덱스 리프블록에 위치한 모든 레코드는 포인터를 따라 논리적으로 연결되어있고 이 포인터를 따라 스캔하는것은 Sequential 액세스 방식이다.</li>
</ul>
<blockquote>
<ul>
<li>Random 액세스</li>
</ul>
</blockquote>
<ul>
<li><p>레코드간 논리적,물리적인 순서를 따르지 않고 한 건을 읽기위해 한 블록씩 접근하는 방식을 말한다.</p>
</li>
<li><p>하나의 레코드를 읽으려고 한 블록씩 랜덤액세스를 한다면 매우 비효율적이다.</p>
<p>여기서 I/O 튜닝의 핵심 원리 두가지를 발견할 수 있다.</p>
</li>
<li><p>시퀀셜 액세스에 의한 선택 비중을 높인다.</p>
</li>
<li><p>랜덤 액세스 발생량을 줄인다.</p>
</li>
</ul>
<h4 id="1-시퀀셜-액세스에-의한-선택-비중-높이기">1. 시퀀셜 액세스에 의한 선택 비중 높이기</h4>
<p>: 시퀀셜 액세스 효율성을 높이려면, 읽은 총 건수 중에서 결과 집합으로 선택되는 비중을 높여야 한다. 즉 같은 결과를 얻기 위해 얼마나 적은 레코드를 읽느냐로 효율성을 판단할 수 있다.</p>
<p>테이블을 스캔하면서 읽은 레코드중 대부분 필터링되고 일부만 선택된다면 인덱스를 이용하는 게 효과적이다.</p>
<p>하지만 인덱스를 사용할때도 비효율이 나타날 수 있다. 조건절에 사용된 컬럼과 연산자 형태, 인덱스 구성에 의해 효율성이 결정된다.</p>
<h4 id="2-랜덤-액세스-발생량-줄이기">2. 랜덤 액세스 발생량 줄이기</h4>
<p>인덱스를 사용해 테이블 랜덤 액세스 발생량을 줄일 수 있다. 같은 쿼리를 수행했는데도 인덱스 구성에 따라 랜덤액세스가 다를 수 있으므로 인덱스 구성을 잘해야 한다.</p>
<hr>
<h3 id="single-block-io-vs-multiblock-io">Single Block I/O VS MultiBlock I/O</h3>
<blockquote>
<ul>
<li>Single Block I/O</li>
</ul>
</blockquote>
<ul>
<li>한번의 I/O Call에 하나의 데이터 블록만 읽어 메모리에 적재하는 방식이다.</li>
<li>인덱스를 통해 테이블을 액세스할때는 기본적으로 인덱스와  테이블 블록 모두 이 방식을 사용한다.</li>
</ul>
<blockquote>
<ul>
<li>MultiBlock I/O</li>
</ul>
</blockquote>
<ul>
<li>I/O Call이 필요한 시점에 인접한 블록들을 같이 읽어 메모리에 적재하는 방식이다.</li>
<li>Table Full Scan처럼 물리적으로 저장된 순서에 따라 읽을 때는 인접한 블록들을 같이 읽는 것이 유리하다. </li>
<li>인접한 블록이란 한 익스텐트내에 속한 블록을 말한다. 달리 말하면 MultiBlock I/O 방식으로 읽더라도 익스텐트 범위를 넘어서까지 읽지는 않는다.</li>
</ul>
<ul>
<li><p>인덱스 스캔 시에는 Single Block I/O 방식이 효율적이다. 인덱스 블록간 논리적 순서는 데이터 파일에 저장된 물리적인 순서와 다르기 때문이다.</p>
</li>
<li><p>대량의 데이터를  MultiBlock I/O 방식으로 읽을때 성능이 유리한 이유는 I/O Call 발생횟수를 줄여주기 때문이다.</p>
</li>
<li><p>Single Block I/O 방식으로 읽은 블록들은 LRU리스트 상 MRU 쪽(end)으로 위치하므로 한번 적재되면 버퍼캐시에 비교적 오래 머문다.</p>
</li>
<li><p>반대로 MultiBlock I/O 방식으로 읽은 블록들은 LRU리스트상 LRU쪽(end)으로 연결되므로 적재된지 얼마 지나지 않아 1순위로 버퍼캐시에서 밀려난다.</p>
</li>
</ul>
<hr>
<h3 id="io-효율화-원리">I/O 효율화 원리</h3>
<ul>
<li>논리적인 I/O 요청 횟수를 최소화 하는 것이 I/O 효율화 튜닝의 핵심원리다.</li>
<li>I/O때문에 시스템 성능이 낮게 측정될 때 하드웨어적인 방법을 통해 I/O성능을 향상 시킬 수도 있다. 하지만 SQL 튜닝을 통해 I/O 발생 횟수 자체를 줄이는 것이 더 근본적이고 확실한 해결방안이다.</li>
</ul>
<p>어플리케이션 측면에서의 I/O 효율화 원리는 다음과 같이 요약할 수 있다.</p>
<ul>
<li>필요한 최소 블록만 읽도록 SQL 작성</li>
<li>최적의 옵티마이징 팩터 제공</li>
<li>필요하다면 옵티마이저 힌트를 사용해 최적의 액세스 경로로 유도</li>
</ul>
<h4 id="1-필요한-최소블록만-읽도록-sql-작성">1. 필요한 최소블록만 읽도록 SQL 작성</h4>
<p>: 데이터베이스 성능은 I/O 효율에 달렸다. 이를 달성하려면 동일한 데이터를 중복 액세스하지않고 필요한 최소 블록만 읽도록 SQL을 작성해야 한다.</p>
<p>SQL명령을 사용자는 최소 일량을 요구하는 형태로 논리적인 집합을 정의하고, 효율적인 처리가 가능하도록 작성하는 것이 무엇보다 중요하다.</p>
<p>아래는 비효율적인 중복 액세스를 없애고 필요한 최소 블록만 액세스하도록 튜닝한 사례이다.
&lt;사진&gt;</p>
<p>위 SQL는 어제 거래가 있었던 카드에 대한 전일, 주간, 전월, 연중 거래 실적을 집계하고 있다. 논리적인 전체집합은 과거 1년치인데 전일,주간,전월데이터를 각각 액세스한후 조인한 것을 볼수 있다 .전일 데이터는 총 4번을 액세스한 셈이다.</p>
<p>SQL을 아래와 같이 작성하면 과거 1년치 데이터를 한번만 읽고 전일,주간,전월 결과를 구할 수 있다. 즉 논리적인 집합 재구성을 통해 액세스해야 할 데이터 양을 최소화할 수 있다.
&lt;사진&gt;</p>
<h4 id="2-최적의-옵티마이징-팩터-제공">2. 최적의 옵티마이징 팩터 제공</h4>
<ul>
<li>옵티마이저가 블록 액세스를 최소화하면서 효율적으로 처리할 수 있도록 하려면 최적의 옵티마이징 팩터를 제공해주어야 한다.</li>
</ul>
<blockquote>
<ul>
<li>전략적인 인덱스 구성
: 가장 기본적인 옵티마이징 팩터이다.</li>
</ul>
</blockquote>
<ul>
<li>DBMS가 제공하는 기능 활용
: 인덱스 외에도 DBMS가 제공하는 다양한 기능을 적극적으로 활용한다.
인덱스, 파티션, 클러스터, 윈도우함수등을 적극활용해 옵티마이저가 최적으로 선택할 수 있도록 한다.</li>
<li>옵티마이저 모드 설정
: 옵티마이저모드( 전체처리속도 최적화, 최초응답속도 최적화)와 그 외 옵티마이저 행동에 영향을 미치는 일부 파라미터를 변경해 주는 것이 도움이 될 수 있다.</li>
<li>통계정보
: 옵티마이저에게 정확한 정보를 제공한다.</li>
</ul>
<h4 id="3-옵티마이저-힌트를-사용해-최적의-액세스-경로로-유도">3. 옵티마이저 힌트를 사용해 최적의 액세스 경로로 유도</h4>
<ul>
<li></li>
<li>옵티마이저 힌트를 사용할 때는 의도한 실행계획으로 수행되는 지 반드시 확인해야 한다.</li>
</ul>
<hr>
<p>참고자료: SQL 전문가 가이드</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL- SQL 처리과정]]></title>
            <link>https://velog.io/@i_am_heeeun/SQL-SQL-%EC%B2%98%EB%A6%AC%EA%B3%BC%EC%A0%95</link>
            <guid>https://velog.io/@i_am_heeeun/SQL-SQL-%EC%B2%98%EB%A6%AC%EA%B3%BC%EC%A0%95</guid>
            <pubDate>Mon, 14 Nov 2022 11:38:51 GMT</pubDate>
            <description><![CDATA[<h3 id="구조적-집합적-선언적-질의-언어">구조적, 집합적, 선언적 질의 언어</h3>
<p>SQL은 Structured Query Language의 줄임말이다. 말 그래도 구조적 질의 언어다.
원하는 결과집합을 구조적,집합적으로 선언하지만 그 결과 집합을 만드는 과정은 절차적일 수 밖에 없다. 즉 프로시저가 필요한데 그런 프로시저를 만들어내는 DBMS내부엔진이 바로 SQL옵티마이저이다.</p>
<h3 id="sql처리과정">SQL처리과정</h3>
<p>Oracle 기준으로 자세히 표현하면 아래 그림과 같다.
<img src="https://velog.velcdn.com/images/i_am_heeeun/post/0db1e249-5fa6-478b-90d7-13a00e459b96/image.jpg" alt=""></p>
<p>아래의 표는 위의 사진에서 표현된 각 서브엔진의 역할을 요약한 것이다.
<img src="https://velog.velcdn.com/images/i_am_heeeun/post/fa0a00df-9b89-4c72-a187-3f2c9b852c3c/image.jpg" alt=""></p>
<p>쿼리 최적화 과정을 다음과 같이 설명하고 있다. Parser와 Optimizer역할에 해당하는 내용임을 알 수 있다.</p>
<ul>
<li>쿼리를 내부 표현방식으로 변환</li>
<li>표준적인 형태로 변환</li>
<li>후보군이 될 만한 프로시저를 선택</li>
<li>실행계획을 생성하고 가장 비용이 적은 것을 선택</li>
</ul>
<h3 id="sql-옵티마이저">SQL 옵티마이저</h3>
<p>: SQL 옵티마이저는 사용자가 원하는 작업을 가장 효율적이고 수행할 수 있는 최적의 데이터 액세스경로를 선택해 주는 DBMS의 핵심엔진이다. </p>
<ul>
<li>옵티마이저의 최적화 단계</li>
</ul>
<ol>
<li>사용자로부터 전달받은 쿼리를 수행하는 데 후보군이 될만한 실행계획들을 찾아낸다.</li>
<li>데이터 딕셔너리에 미리 수집해 둔 오브젝트 통계 및 시스템 통계정보를 이용해 각 실행계획의 예상비용을 산정한다.</li>
<li>최저 비용을 나타내는 실행계획을 선택한다.</li>
</ol>
<h3 id="실행계획과-비용">실행계획과 비용</h3>
<p>비용은 쿼리를 수행하는 동안 발생할 것으로 예상되는 I/O 횟수또는 예상소요시간을 표현한 값이다. 실행경로를 선택하기 위해 옵티마이저가 여러 통계정보를 활용해서 계산해 낸 값이다. 실측치가 아니므로 실제 수행할 때 발생하는 I/O 또는 시간과 많은 차이가 날 수 있다.</p>
<h3 id="옵티마이저-힌트">옵티마이저 힌트</h3>
<p>: 통계정보가 정확하지 않거나 기타 다른 이유로 옵티마이저가 잘못된 판단을 할 수 있다. 그럴 때 프로그램이나 데이터 특성 정보를 정확히 알고 있는 개발자가 직접 인덱스를 지정하거나 조인 방식을 변경함으로써 더 좋은 실행계획으로 유도하는 메커니즘이 필요한데  옵티마이저 힌트가 바로 그것이다.</p>
<h4 id="1-oracle-힌트">1. Oracle 힌트</h4>
<ul>
<li><p>힌트 기술방법</p>
<pre><code class="language-sql">SELECT /* LEADING(E2 E1) USE_NM(E1) INDEX(E1 EMP_EMP_ID_OK
        USE_MERGE(J) FULL(J)*/
     E1.FIRST_NAME, E1.LAST_NAME, J.JOB_ID, SUM(E2.SALARY) TOTAL_SAL
FROM EMPLOYEES E1, EMPLOYEES E2, JOB_HISTORY J
WHERE E1.EMPLOYEE_ID = E2.MANAGER_ID
 AND E1.EMPLOYEE_ID = J.EMPLOYEE_ID
 AND E1.HIRE_DATE = J.START_DATE
GROUP BY E1.FIRST_NAME, E1.LAST_NAME, J.JOB_ID
ORDER BY TOTAL_SAL;</code></pre>
<p>Index 힌트에는 인덱스명 대신 다음과 같이 컬럼명을 지정할 수 있다.</p>
<pre><code class="language-sql">SELECT /*LEADING(E2 E1) USE_NM(E1) INDEX(E1(EMPLOYEE_ID))*/</code></pre>
</li>
<li><p>힌트가 무시되는 경우
다음과 같은 경우에 Oracle 옵티마이저는 힌트를 무시하고 최적화를 진행한다.</p>
<ul>
<li>문법적으로 안 맞게 힌트를 기술</li>
<li>잘못된 참조 사용</li>
<li>논리적으로 불가능한 액세스 경로</li>
<li>의미적으로 안 맞게 힌트를 기술</li>
</ul>
</li>
<li><p>힌트 종류
Oracle은 공식적으로 다음과 같이 많은 힌트를 제공한다. 비공식 힌트까지 합치면 350여개에 이른다.
<img src="https://velog.velcdn.com/images/i_am_heeeun/post/6f772377-f585-41b6-8804-62b3a7819c91/image.jpg" alt=""></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL- 데이터베이스 아키텍처]]></title>
            <link>https://velog.io/@i_am_heeeun/SQL-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98</link>
            <guid>https://velog.io/@i_am_heeeun/SQL-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98</guid>
            <pubDate>Sat, 12 Nov 2022 17:24:48 GMT</pubDate>
            <description><![CDATA[<h3 id="데이터베이스-구조-oracle">데이터베이스 구조 (Oracle)</h3>
<p>: DBMS마다 데이터베이스에 대한 정의가 조금씩 다르다. Oracle에서는 디스크에 저장된 데이터 집합을 데이터베이스라고 부른다. 그리고 SGA공유메모리영역과 이를 액세스하는 프로세스 집합을 합쳐서 인스턴스라고 부른다.</p>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/39e75ec2-dfb0-4721-94ff-fdef843e2464/image.jpg" alt=""></p>
<p>기본적으로 하나의 인스턴스가 하나의 데이터베이스만 액세스하지만 RAC환경에서는 여러 인스턴스가 하나의 데이터베이스를 액세스할 수 있다. 하나의 인스턴스가 여러 데이터베이스를 액세스할 수는 없다.</p>
<hr>
<h3 id="프로세스">프로세스</h3>
<p>SQL Server는 쓰레드 기반 아키텍처이므로 프로세스 대신 쓰레드라는 표현을 써야 한다. Oracle도 윈도우 버전에선 쓰레드를 사용하지만, 프로세스와 일일이 구분하면서 설명하려면 복잡해지므로 프로세스로 통칭하기로 한다. </p>
<p>프로세스는 서버프로세스와 백그라운드 프로세스 집합으로 나뉜다. 서버프로세스는 전면에서 사용자로부터 전달받은 각종 명령을 처리하고, 백그라운드 프로세스는 뒤에서 묵묵히 할당받은 역할을 수행한다.</p>
<h4 id="1-서버프로세스">1. 서버프로세스</h4>
<p>: 서버프로세스는 사용자 프로세스와 통신하면서 사용자의 각종 명령을 처리한다. 좀 더 구체적으로 말하여 SQL을 파싱하고 필요하면 최적화를 수행한다.</p>
<ul>
<li>커서를 열어 SQL을 실행하면서 블록을 읽어 이 데이터를 정렬해 클라이언트가 요청한 결과 집합을 만들어 네트워크를 통해 전송하는 일련의 작업을 모두 서버프로세스가 처리해 준다.</li>
</ul>
<p>클라이언트가 서버프로세스와 연결하는 방식은 DBMS마다 다르지만 Oracle을 예로 들면 전용서버방식과 공유서버방식 두가지가 있다.</p>
<h4 id="1-전용서버-방식">1) 전용서버 방식</h4>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/a4301cb0-1a8c-46be-be79-0b625a7d942e/image.jpg" alt=""></p>
<p>위의 사진을 보면 전용서버방식으로 접속할 때 내부적으로 어떤 과정을 거쳐 세션을 수립하고 사용자 명령을 처리하는지 잘 보여준다.</p>
<p>처음 연결요청을 받는 리스너가 서버프로세스를 생성해주고 이 서버 프로세스가 단 하나의 사용자 프로세스를 위해 전용 서비스를 제공한다는 점이 특징이다.</p>
<p>만약 SQL을 수행할 때마다 연결요청을 반복하면 서버 프로세스의 생성과 해제도 반복하게 되므로 DBMS에 매우 큰 부담을 주고 성능을 크게 떨어뜨린다. 따라서 전용서버 방식을 사용하는 OLTP성 어플리케이션에선 Connection Pooling 기법을 필수적으로 사용해야 한다.</p>
<h4 id="2-공유서버-방식">2) 공유서버 방식</h4>
<p>공유서버방식은 말 그대로 하나의 서버 프로세스를 여러 사용자 세션이 공유하는 방식이다. 앞에서 설명한 Connection Pooling기법을 DBMS내부에 구현해놓은 것으로 생각하면 쉽다. 즉 미리 여러개의 서버프로세스를 띄어 놓고 이를 공유해 반복 재사용한다.
<img src="https://velog.velcdn.com/images/i_am_heeeun/post/559b3e39-4230-4807-b075-c8b8e3db490c/image.jpg" alt=""></p>
<h4 id="2-백그라운드-프로세스">2. 백그라운드 프로세스</h4>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/9701a2ca-6f0a-4b7c-82d6-492cc65a781c/image.jpg" alt=""></p>
<hr>
<h3 id="데이터-저장-구조">데이터 저장 구조</h3>
<h4 id="1-데이터-파일">1. 데이터 파일</h4>
<p><img src="https://velog.velcdn.com/images/i_am_heeeun/post/5e8cec83-d3b0-4565-8913-c23821708337/image.jpg" alt=""></p>
<p>Oracle과 SQL Server 모두 물리적으로는 데이터 파일에 데이터를 저장하고 관리한다. 공간을 할당하고 관리하기 위한 논리적인 구조도 크게 다르지 않지만 약간의 차이는 있다.</p>
<h4 id="1-블록--페이지">1) 블록 (= 페이지)</h4>
<p>대부분 DBMS에서 I/O는 블록단위로 이뤄진다. 데이터를 읽고 쓸 때의 논리적인 단위가 블록이다. Oracle은 2,4,8,16,32KB의 다양한 블록크기를 사용할 수 있다.
블록단위로 I/O한다는 것은, 하나의 레코드에서 하나의 컬럼만을 읽으려 할 때도 레코드가 속한 블록 전체를 읽게 됨을 뜻한다. SQL성능을 좌우하는 가장 중요한 성능지표는 액세스하는 블록개수이며 옵티마이저의 판단에 가장 큰 영향을 미치는 것도 액세스해야 할 블록개수이다.</p>
<h4 id="2-익스텐트extent">2) 익스텐트(Extent)</h4>
<p>테이블스페이스로부터 공간을 할당하는 단위를 익스텐트라고 한다.</p>
<h4 id="3-세그먼트">3) 세그먼트</h4>
<p>테이블, 인덱스, Undo처럼 저장공간을 필요로 하는 데이터베이스 오브젝트다. 저장공간을 필요로 한다는 것은 한개 이상의 익스텐트를 사용함을 뜻한다.
한 세그먼트는 자신이 속한 테이블스페이스 내 여러 데이터 파일에 걸쳐 저장될 수 있다. 즉 세그먼트에 할당된 익스텐트가 여러 데이터 파일에 흩어져 저장되는 것이며 그래야 디스크 경합을 줄이고 I/O 분산 효과를 얻을 수 있다.</p>
<h4 id="4-테이블스페이스">4) 테이블스페이스</h4>
<p>세그먼트를 담는 컨테이너로서, 여러 데이터 파일로 구성된다.
사용자는 세그먼트를 위한 테이블스페이스를 지정할 뿐, 실제 값을 저장할 데이터 파일을 선택하고 익스텐트를 할당하는 것은 DBMS의 몫이다.
각 세그먼트는 정확히 한 테이블스페이스에만 속하지만 한 테이블스페이스에는 여러 세그먼트가 존재할 수 있다. 특정 세그먼트에 할당된 모든 익스텐트는 해당 세그먼트와 관련된 테이블스페이스내에서만 찾아진다. 한 세그먼트가 여러 테이블 스페이스에 걸쳐 저장될 수는 없다.
하지만 앞서 말했듯이 한 세그먼트가 여러 데이터 파일에 걸쳐 저장될 수는 있다. 한 테이블스페이스가 여러 데이터파일로 구성되기 때문이다.
사진으로 요약하면 아래와 같다.
<img src="https://velog.velcdn.com/images/i_am_heeeun/post/76740c11-8527-44da-8e34-6d6d7379ab2e/image.jpg" alt=""></p>
<h4 id="2-임시데이터-파일">2. 임시데이터 파일</h4>
<p>임시데이터 파일은 특별한 용도로 사용된다. 대량의 정렬이나 해시작업을 수행하다가 메모리공간이 부족해지면 중간 결과 집합을 저장하는 용도다.
임시데이터파일에 저장되는 오브젝트는 말 그대로 임시로 저장했다가 자동으로 삭제된다. Redo 정보를 생성하지 않기 때문에 나중에 파일에 문제가 생겼을 때 복구되지 않는다. 따라서 백업할 필요도 없다.
Oracle에선 임시테이블스페이스를 여러개 생성해두고 사용자마다 별도의 임시 테이블스페이스를 지정해 줄 수도 있다.</p>
<h4 id="3-로그파일">3. 로그파일</h4>
<p>DB버퍼캐시에 가해지는 모든 변경사항을 기록하는 파일을 Oracle에서는 Redo로그 라고 부른다.
대부분 DBMS는 버퍼블록에 대한 변경사항을 건건이 데이터파일에 기록하기보다 우선 로그파일에 Append방식으로 빠르게 기록하는 방식을 사용한다. 그러고 나서 버퍼블록과 데이터파일간 동기화는 적절한 수단을 이용해 나중에 배치방식으로 일괄처리한다.</p>
<p>◽️ ONnline Redo 로그</p>
<ul>
<li>트랜잭션 데이터의 유실에 대비하기 위해 Oracle은 Online Redo로그를 사용한다. 마지막 체크포인트 이후부터 사고발생 직전까지 수행됐던 트랜잭션들을 Redo로그를 이용해 재현하는 것이며 이를 캐시복구라고한다.</li>
<li>Online Redo 로그는 최소 두개 이상의 파일로 구성된다. 현재 사용중인 파일이 꽉 차면 다음 파일로 로그스위칭이 발생하며 계속 로그를 써 나가다가 모든 파일이 꽉 차면 다시 첫번째 파일부터 재사용하는 라운드로빈방식을 사용한다.</li>
</ul>
<p>◽️ 트랜잭션 로그</p>
<ul>
<li>Oracle의 Online Redo 로그와 대응되는 SQL Server의 로그파일이다. 
트랜잭션 로그파일은 내부적으로 가상로그파일이라 불리는 더 작은 단위의 세그먼트로 나뉘며, 이 가상로그파일의 개수가 너무 많아지지 않도록 옵션을 지정하는 게 좋다.</li>
</ul>
<p>◽️ Archived(=Offline) Redo 로그</p>
<ul>
<li>Oracle에서 Online Redo 로그가 재사용되기 전에 다른 위치로 백업해 둔 파일을 말한다.</li>
<li>디스크가 깨지는 등 물리적인 저장매체에 문제가 생겼을때 데이터베이스 복구를 위해 사용된다.</li>
</ul>
<h3 id="메모리-구조">메모리 구조</h3>
<p>메모리 구조는 시스템 공유 메모리 영역과 프로세스 전용 메모리 영역으로 구분된다.</p>
<p>◽️ 시스템 공유 메모리 영역
말 그대로 여러 프로세스가 동시에 액세스할 수 있는 메모리 영역으로서, Oracle에선 SGA라고 부른다.</p>
<ul>
<li>여러프로세스에 공유되기 때문에 내부적으로 래치, 버퍼 LOCK, 라이브러리캐시 Lock/Pin 같은 액세스 직렬화 메커니즘이 사용된다.</li>
</ul>
<p>◽️ 프로세스 전용 메모리 영역</p>
<ul>
<li>Oracle은 프로세스 기반 아키텍처이므로 서버프로세스가 자신만의 전용 메모리 영역을 가질 수 있다. 이를 PGA라고 부르며 데이터를 정렬하고 세션과 커서에 관한 상태정보를 저장하는 용도로 사용한다.</li>
</ul>
<h4 id="1-db-버퍼-캐시">1. DB 버퍼 캐시</h4>
<p>: 데이터 파일로부터 읽어들인 데이터블록을 담는 캐시영역이다. 
인스턴스에 접속한 모든 사용자 프로세스는 서버 프로세스를 통해 DB 버퍼 캐시의 버퍼블록을 동시에 액세스할 수 있다.</p>
<p>1) 버퍼블록의 상태
모든 버퍼블록은 아래 세가지 중 하나의 상태에 놓인다.</p>
<ul>
<li><p>Free 버퍼
: 인스턴스 기동 후 아직 데이터가 읽히지 않아 비어 있는 상태이거나 데이터가 담겼지만 데이터 파일과 서로 동기화돼 있는 상태여서 언제든지 덮어 써도 무방한 버퍼블록을 말한다.</p>
</li>
<li><p>Dirty 버퍼
: 버퍼에 캐시된 이후 변경이 발생했지만 아직 디스크에 기록되지 않아 데이터 파일블록과 동기화가 필요한 버퍼블록을 말한다.</p>
</li>
<li><p>Pinned 버퍼
: 읽기 또는 쓰기 작업이 현재 진행중인 버퍼블록을 말한다.</p>
</li>
</ul>
<p>2) LRU 알고리즘
: 모든 DBMS는 사용빈도가 높은 데이터 블록 위주로 버퍼 캐시가 구성되도록 LRU알고리즘을 사용한다.</p>
<ul>
<li>모든 버퍼 블록 헤더를 LRU체인에 연결해 사용빈도 순으로 위치를 옮겨가다가, Free버퍼가 필요해질 때면 액세스 빈도가 낮은 쪽 데이터블록부터 밀어내는방식이다.</li>
</ul>
<h4 id="2-공유-풀">2. 공유 풀</h4>
<p>: 공유 풀은 딕셔너리 캐시와 라이브러리 캐시로 구성되며 버퍼 캐시처럼 LRU알고리즘을 사용한다.</p>
<ul>
<li><p>딕셔너리 캐시
: 테이블, 인덱스같은 오브젝트는 물론 테이블스페이스, 데이터파일, 세그먼트, 익스텐트, 사용자, 제약에 관한 메타정보를 저장하는 곳이다.
딕셔너리 정보를 캐싱하는 메모리 영역이다.</p>
</li>
<li><p>라이브러리 캐시
: 사용자가 수행한 SQL문과 실행계획, 저장프로시저를 저장해 두는 캐시영역이다.
같은 SQL에 대한 반복적인 하드파싱을 최소회하기 위한 캐시공간을 따로 두게 됐고 그것이 라이브러리캐시영역이다.
캐싱된 SQL과 그 실행계획의 재사용성을 높이는 것은 SQL 수행성능을 높이고 DBMS 부하를 최소화하는 핵심원리 중 한가지다.</p>
</li>
</ul>
<h4 id="3-로그-버퍼">3. 로그 버퍼</h4>
<p>로그 엔트리도 파일에 곧바로 기록하는 것이 아니라 먼저 로그버퍼에 기록한다.
서버프로세스가 데이터 블록버퍼에 변경을 가하기 전에 Redo 로그 버퍼에 먼저 기록해 두면 주기적으로 LGWR프로세스가 Redo로그파일에 기록한다. 
로그파일에 기록했음이 보장돼야 안심하고 커밋을 완료할 수 있다.</p>
<h4 id="4-pga">4. PGA</h4>
<p>각 Oracle서버프로세스는 자신만의 PGA메모리영역을 할당받고 이를 프로세스에 종속적인 고유 데이터를 저장하는 용도로 사용한다.
PGA는 다른프로세스와 공유되지 않는 독립적은 메모리 공간으로서, 래치메커니즘이 필요 없어 똑같은 개수의 블록을 읽더라도 SGA 버퍼 캐시에서 읽는 것보다 빠르다.</p>
<ul>
<li><p>User Global Area (UGA)
: 전용서버방식으로 연결할 때는 프로세스와 세션이 1:1 관계를 갖지만 공유서버방식으로 연결할때는 1:M관계를 갖는다.
각 세션을 위한 독립적인 메모리 공간이 필요한데 이를 UGA라고 한다.
UGA는 전용서버방식으로 연결할때는 PGA에 할당되고 공유서버방식으로 연결할때는 SGA에 할당된다.</p>
</li>
<li><p>Call Global Area (CGA)
: CGA는  Parse Call, Execute Call, Fetch Call마다 매번 할당받는다.  CGA에 할당된 공간은 하나의 Call이 끝나자마자 해제돼 PGA로 반환된다.</p>
</li>
<li><p>Sort Area
: 데이터 정렬을 위해 사용되는 Sort Area는 소트오퍼레이션이 진행되는 동안 공간이 부족해질 때마다 청크단위로 조금씩 할당된다.</p>
</li>
</ul>
<hr>
<p>참고자료 : SQL전문가가이드</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL - DCL]]></title>
            <link>https://velog.io/@i_am_heeeun/SQL-DCL</link>
            <guid>https://velog.io/@i_am_heeeun/SQL-DCL</guid>
            <pubDate>Tue, 08 Nov 2022 11:06:25 GMT</pubDate>
            <description><![CDATA[<p>DCL (Data Control Language)
: 유저를 생성하고 권한을 제어할 수 있는 명령어.</p>
<ul>
<li><p>유저와 권한을 관리하는 이유
: 데이터보호와 보안을 위해 관리한다.</p>
</li>
<li><p>Oracle은 유저를 통해 데이터베이스에 접속하는 형태이다. 
즉 아이디와 비밀번호 방식으로 인스턴스에 접속을 하고 그에 해당하는 스키마에 오브젝트 생성등의 권한을 부여받게 된다.</p>
</li>
</ul>
<h3 id="유저-생성과-시스템-권한-부여">유저 생성과 시스템 권한 부여</h3>
<p>사용자가 실행하는 모든 DDL문장은 그에 해당하는 적절한 권한이 있어야만 문장을 실행할 수 있다.</p>
<p>유저를 생성하고 권한을 부여해보도록 하자.
새로운 유저를 생성하려면 일단 유저생성권한이 있어야 한다.</p>
<pre><code class="language-sql">CONN SCOTT
//연결됐습니다.</code></pre>
<pre><code class="language-sql">CREATE USER SQLD IDENTIFIED BY DB2019;
//1행에 오류:
// ORA-01031: 권한이 불충분합니다.</code></pre>
<p>현재 scott는 유저를 생성할 권한이 없기 때문에 권한이 불충분하다는 오류가 발생한다.
권한을 부여하기 위해 DBA권한을 가지고 있는 SYSTEM유저로 접속하여 유저생성권한을 다른 유저에게 부여해보도록 하자.</p>
<pre><code class="language-sql">GRANT CREATE USER TO SCOTT;
//권한이 부여됐습니다.</code></pre>
<p>권한을 부여한 후 다시 새로운 사용자를 생성하면 오류가 발생하지 않고 생성이 완료된다.</p>
<p>유저가 생성됐지만 아무런 권한도 부여받지 못했기 때문에 로그인을 하면 CREATE SESSION 권한이 없다는 오류가 발생한다.</p>
<pre><code class="language-sql">GRANT CREATE SESSION TO SQLD;</code></pre>
<p>로그인 권한을 얻고 테이블을 생성하려고 하면 권한이 불충분하다는  오류가 발생한다. 이때 테이블생성 권한도 추가해주어야 한다.</p>
<pre><code class="language-sql">GRANT CREATE TABLE TO SQLD;</code></pre>
<h3 id="object에-대한-권한-부여">OBJECT에 대한 권한 부여</h3>
<p>특정 유저가 소유한 객체 권한에 대해 알아보도록 하자.
객체권한은 테이블, 뷰 등에 대한 SELECT,INSERT,DELETE,UPDATE작업 명령어를 의미한다.
<img src="https://velog.velcdn.com/images/i_am_heeeun/post/a9b0c839-2869-43b9-9479-cfeb0897acf8/image.jpg" alt=""></p>
<p>테이블을 생성하고 SELECT,INSERT,DELETE,UPDATE를 하려고 하면 오류가 발생한다. 권한을 따로 부여받아야 조회,삽입,삭제,업데이트가 가능하다.</p>
<pre><code class="language-sql">GRANT SELECT ON 테이블명 TO 유저;
GRANT INSERT ON 테이블명 TO 유저;
GRANT DELETE ON 테이블명 TO 유저;
GRANT UPDATE ON 테이블명 TO 유저;

GRANT SELECT,INSERT,DELETE,UPDATE ON 테이블명 TO 유저;</code></pre>
<h3 id="role을-이용한-권한-부여">ROLE을 이용한 권한 부여</h3>
<ul>
<li><p>관리해야 할 유저가 점점 늘어나고 자주 변경되는 상황에서 권한 관리하기 힘들기 때문에 데이터베이스에서 유저들과 권한들 사이에서 중개 역할을 하는 ROLE을 제공한다.</p>
</li>
<li><p>데이터베이스 관리자는 ROLE을 생성하고 ROLE에 각종 권한들을 부여 한 후, ROLE을 다른 ROLE이나 유저에게 부여할 수 있다.</p>
</li>
<li><p>ROLE에는 시스템권한과 객체권한을 모두 부여할 수 있다.</p>
</li>
<li><p>ROLE을 만들어 사용하는 것이 권한을 직접 부여하는 것보다 빠르고 안전하게 유저를 관리할 수 있는 방법이다.</p>
</li>
</ul>
<p>ROLE 생성하는 법</p>
<pre><code class="language-sql">CREATE ROLE 롤이름;</code></pre>
<p>ROLE에 권한 부여</p>
<pre><code class="language-sql">GRANT CREATE SESSION, CREATE TABLE TO 롤이름;</code></pre>
<p>오라클에서는 기본적으로 몇가지 ROLE을 제공한다. 그 중에서 가장 많이 사용하는 ROLE은 CONNECT와 RESOURCE이다.</p>
<p>CONNECT는 CREATE SESSION과 같은 로그인권한이 포함되어있고 
RESOURCE는 오브젝트의 생성권한이 포함되어있다.</p>
<p>아래의 표는 CONNECT와 RESOURCE ROLE에 부여된 권한목록을 정리한 것이다.
<img src="https://velog.velcdn.com/images/i_am_heeeun/post/149caf90-6b01-4dcf-bc7d-2fb5b991a9ce/image.jpg" alt=""></p>
<h3 id="revoke">REVOKE</h3>
<ul>
<li>권한을 취소하는 명령어<pre><code class="language-sql">REVOKE CREATE SESSION FROM 유저;</code></pre>
</li>
</ul>
<hr>
<p>참고자료 : SQL전문가가이드</p>
]]></description>
        </item>
    </channel>
</rss>