<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>eun_zii.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Mon, 03 Oct 2022 12:06:05 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>eun_zii.log</title>
            <url>https://velog.velcdn.com/images/eun_zii/profile/2fff3dea-ca09-4b31-8fb1-7ce3ef55c6de/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. eun_zii.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/eun_zii" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[ES2_IMAGE 이용해서 인스턴스만들기]]></title>
            <link>https://velog.io/@eun_zii/IMAGE-%EC%9D%B4%EC%9A%A9%ED%95%B4%EC%84%9C-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@eun_zii/IMAGE-%EC%9D%B4%EC%9A%A9%ED%95%B4%EC%84%9C-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Mon, 03 Oct 2022 12:06:05 GMT</pubDate>
            <description><![CDATA[<h1 id="es2-인스턴스-image-만들기">ES2 인스턴스 IMAGE 만들기</h1>
<ol>
<li><p>EC2 대시보드에서 인스턴스(실행중) 클릭
<img src="https://velog.velcdn.com/images/eun_zii/post/927b96cb-f14b-448b-afd8-c931bd8eb13a/image.png" alt=""></p>
</li>
<li><p>해당 인스턴스 클릭후 , 인스턴스 상태 에 <strong>&quot; 인스턴스 중지 &quot;</strong> (종료 ❌)
<img src="https://velog.velcdn.com/images/eun_zii/post/d878f25b-e482-47f0-922c-b2e8db4c0c96/image.png" alt=""></p>
</li>
<li><p>중지후, 작업 에 이미지 및 템플릿 -&gt; <strong>&quot; 이미지 생성 &quot;</strong>
<img src="https://velog.velcdn.com/images/eun_zii/post/6379313a-7be6-4161-ba6c-a25fdcc7cbe5/image.png" alt=""></p>
</li>
<li><p>이름만 적용후 우측 하단 이미지 생성 클릭
<img src="https://velog.velcdn.com/images/eun_zii/post/1d17e2e9-ff85-4845-b769-d3f7d2f2d7c0/image.png" alt=""></p>
</li>
<li><p>NavBar 에 AMI 클릭
<img src="https://velog.velcdn.com/images/eun_zii/post/5452344c-390d-403e-b18d-566fb46349a8/image.png" alt=""></p>
</li>
<li><p>IMAGE 만들면서 이름 적용
<img src="https://velog.velcdn.com/images/eun_zii/post/8a937a06-a10c-44f3-aff4-064b92aff9db/image.png" alt=""></p>
</li>
</ol>
<h1 id="image를-이용해서-인스턴스-만들기">IMAGE를 이용해서 인스턴스 만들기</h1>
<ol>
<li>최초 중지했던 인스턴스를 다시 시작 하기
<img src="https://velog.velcdn.com/images/eun_zii/post/35825a41-1b85-4348-8294-dbfeb88da399/image.png" alt=""></li>
</ol>
<p>1-1. 이름 변경
<img src="https://velog.velcdn.com/images/eun_zii/post/0c9c541d-6aac-4019-a51d-5bca5e828fc8/image.png" alt=""></p>
<ol start="2">
<li><p>다른 인스턴스에서 보다 편리하게 상호접속을 위해 보안그룹에 Tag 만들기
보안 -&gt;보안그룹 밑 url 클릭 
<img src="https://velog.velcdn.com/images/eun_zii/post/3b17d028-9999-4537-8a53-c8fdeede0faa/image.png" alt=""></p>
</li>
<li><p>태그관리 클릭
<img src="https://velog.velcdn.com/images/eun_zii/post/ec70bb79-2ee3-4881-a59b-fc41e6e47892/image.png" alt=""></p>
</li>
<li><p>새로운 태그 추가 후 key &amp; value 입력후 변경사항 저장
<img src="https://velog.velcdn.com/images/eun_zii/post/ed8f58e5-24f5-4936-8b7c-0e1a148bfde6/image.png" alt=""></p>
</li>
<li><p>Tag 가 만들어짐. 이 tag를 이용해서 검색하여 보안그룹을 선택할수 있음
<img src="https://velog.velcdn.com/images/eun_zii/post/4ba09ea5-1a2e-4568-b24e-f458040fef64/image.png" alt=""></p>
</li>
<li><p>다시 인스턴스 창으로 돌아와서 새로운 인스턴스 생성
<img src="https://velog.velcdn.com/images/eun_zii/post/b2f38594-8202-428d-b748-e6c3a06e1286/image.png" alt=""></p>
</li>
<li><p>내AMI 에서 내소유 만들어둔 image 선택
<img src="https://velog.velcdn.com/images/eun_zii/post/fe171a63-c6b3-4fda-9ec8-d6f612faefa5/image.png" alt=""></p>
</li>
<li><p>만들어 두었던 키페어 선택
<img src="https://velog.velcdn.com/images/eun_zii/post/87d9008b-9e09-482a-88c3-470d73ac6cb9/image.png" alt=""></p>
</li>
<li><p>기존 보안 그룹 선택 
<img src="https://velog.velcdn.com/images/eun_zii/post/1f39980a-1c8f-465e-a449-b36e550a71f1/image.png" alt=""></p>
</li>
<li><p>4개의 인스턴스 생성 -&gt; 인스턴스 시작
<img src="https://velog.velcdn.com/images/eun_zii/post/92bb3972-044d-4855-8f1a-b8f6e65074a1/image.png" alt=""></p>
</li>
<li><p>인스턴스는 총 5개 만들어진거 확인한후 , 각각 이름변경 해주기
<img src="https://velog.velcdn.com/images/eun_zii/post/7c22118c-dd6a-4b77-b63d-917fb84d0ec9/image.png" alt=""></p>
</li>
<li><p>SSH Client 에 각각의 인스턴스 등록- 키페어는 동일한 파일을 사용하기 때문에 따로 만들필요없이 각각 이름과 IP주소만 변경해서 등록
<img src="https://velog.velcdn.com/images/eun_zii/post/dd5a4611-3b41-4bb0-a1d1-666473626b1a/image.png" alt=""></p>
</li>
<li><p>모두 작동 잘하는지 체크
<img src="https://velog.velcdn.com/images/eun_zii/post/e4bb0ba0-336c-41e4-abb0-e121977179a8/image.png" alt=""></p>
</li>
<li><p>DOCKER 인스턴스에서 JENKINS 인스턴스에 ping test를 했지만 ping이 가지 않음
<img src="https://velog.velcdn.com/images/eun_zii/post/6df1004c-f7ed-4705-adf4-78318d4976a0/image.png" alt=""></p>
</li>
<li><p>아무 인스턴스 클릭후 보안 에 보안그룹 아래 url 클릭
<img src="https://velog.velcdn.com/images/eun_zii/post/11ff1ddd-2ab4-4a2a-a825-e7d86f013ac6/image.png" alt=""></p>
</li>
<li><p>인바운드 규칙 에서 <strong>&quot; 인바운드 규칙 편집 &quot;</strong> 클릭
<img src="https://velog.velcdn.com/images/eun_zii/post/e92d368c-ef44-4cce-9ddc-1f92dfafe217/image.png" alt=""></p>
</li>
<li><p>규칙 추가 ➡ 유형 에 &quot; 모든ICMP-IPv4 &quot; (ICMP= ping test 할때 사용하는 protocal 이름) 선택 ➡ 돋보기 모양 선택후 우리가 사용할 인스턴스들이 묶인 보안 그룹 선택 (되도록 0.0.0.0은 사용하지 않는게 좋음. 이는 어디서든 접근하겠다는 의미이기 때문) ➡ 설정 저장 클릭
<img src="https://velog.velcdn.com/images/eun_zii/post/796338bd-b2c3-4e90-afd4-20e123631d34/image.png" alt=""></p>
</li>
<li><p>ping 작동 잘됨
<img src="https://velog.velcdn.com/images/eun_zii/post/12e0a5b0-f114-4b9c-b593-89f7bac7fb02/image.png" alt=""></p>
</li>
</ol>
<p>도움주신분: <a href="https://junyharang.tistory.com/339">https://junyharang.tistory.com/339</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[ES2_인스턴스 생성 과 접속]]></title>
            <link>https://velog.io/@eun_zii/ES2-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EC%83%9D%EC%84%B1-%EA%B3%BC-%EC%A0%91%EC%86%8D</link>
            <guid>https://velog.io/@eun_zii/ES2-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EC%83%9D%EC%84%B1-%EA%B3%BC-%EC%A0%91%EC%86%8D</guid>
            <pubDate>Mon, 03 Oct 2022 08:11:15 GMT</pubDate>
            <description><![CDATA[<h1 id="인스턴스-생성">인스턴스 생성</h1>
<ol>
<li><p>AWS 가입</p>
</li>
<li><p>가입 후 홈에서 EC2로 들어가기
<img src="https://velog.velcdn.com/images/eun_zii/post/543b35ec-8bfd-41e6-ab91-2d17b385383d/image.png" alt=""></p>
</li>
<li><p>인스턴스 시작 (왼쪽 메뉴에도 있고 EC2 홈에도 있음)
<img src="https://velog.velcdn.com/images/eun_zii/post/c4c74294-4a26-469c-a53a-a9cb4ed18ad5/image.png" alt=""></p>
</li>
<li><p>AWS Resion 에서 서울 선택 (각각의 resion끼리는 공유가 되지 않는다)
<img src="https://velog.velcdn.com/images/eun_zii/post/a42dc87a-35a1-4fcd-8daf-84397fc6a8c5/image.png" alt=""></p>
</li>
<li><p>이름에 EC2의 용도나 이름적기 (나중에 변경 가능)
<img src="https://velog.velcdn.com/images/eun_zii/post/27f97771-4cd6-4a84-aefe-c8f3127a26b2/image.png" alt=""></p>
</li>
</ol>
<ol start="6">
<li>서버에 설치될 OS 선택
<img src="https://velog.velcdn.com/images/eun_zii/post/f7c16bfe-44ca-4aa5-ad68-82a69d571cc7/image.png" alt=""></li>
</ol>
<blockquote>
<p>💡 AWS 최초 가입시 프리티어 서비스 80~90개 이용 가능.
EC2는 한달 기준 750시간씩 무료로 가능- 단, EC2는 인스턴스 개 당이 아닌 만들어놓은 인스턴스 총 시간으로 적용.
ex) 10개읜 인스턴스를 사용할시 각 75시간씩 이용 가능 💡</p>
</blockquote>
<ol start="7">
<li>인스턴스 유형 선택 - 내가 갖고자 하는 컴퓨터의 CPU,Memory 를 선택하는것</li>
</ol>
<p><img src="https://velog.velcdn.com/images/eun_zii/post/7d0f3ad2-4049-4bd2-8972-41a6194cbe7b/image.png" alt=""></p>
<ol start="8">
<li>키페어- 인스턴스에 접속하기 위한 암호화된 토큰 혹은 암호화된 Key-file
<img src="https://velog.velcdn.com/images/eun_zii/post/f4087376-10f2-4890-9d19-d9d9ad597597/image.png" alt=""></li>
</ol>
<p>8-1. 키페어 새로 생성 - 키페어 생성하면 pem파일이 저장됨
<img src="https://velog.velcdn.com/images/eun_zii/post/a7484c52-7ed7-414a-bf82-6f492b4e96f2/image.png" alt=""></p>
<p>📌 Mac OS 사용자들은 Putty를 사용하지 않기 때문에 .pem / 
Window 사용자중 Putty,Xshell을 이용할 예정이라면 .ppk를 선택</p>
<ol start="9">
<li>스토리지, 고급세부정보 등등 자신에게 맞게 설정후,</li>
</ol>
<p><strong>인스턴스 시작</strong></p>
<h1 id="ec2-인스턴스-접속">EC2 인스턴스 접속</h1>
<ol>
<li><p>편리하게 인스턴스 접속하려면 SSH Client Tool 이용 - 다양한 tool이 있기때문에 자신에게 맞는것을 선택하면 됨 ( <a href="https://termius.com/mac-os">내가 사용한 Tool</a> )</p>
</li>
<li><p>설치후, 홈화면에 Add -&gt; New Host
<img src="https://velog.velcdn.com/images/eun_zii/post/6ece94eb-cef4-4b82-8d73-ec73b9383782/image.png" alt=""></p>
</li>
<li><p>서버이름(=Label) 입력후 , Adress 칸에 Ec2 인스턴스 Public IP4 주소 입력 (생성된 AWS 인스턴스에서 확인 가능)
<img src="https://velog.velcdn.com/images/eun_zii/post/196da3e5-c14d-466f-94c0-2c8de619d6f9/image.png" alt=""></p>
</li>
<li><p>EC2 인스턴스는 기본적으로 ec2-user 이라는 계정이 만들어 지고 로그인 방식은 ID,PW가 아닌 KEY (EC2 키페어할때 받은 .pem파일) 로 로그인을 함
<img src="https://velog.velcdn.com/images/eun_zii/post/abee97f7-77ab-42db-a09d-5a3e30a9c917/image.png" alt=""></p>
</li>
</ol>
<p>4-1. Password 옆 Keys 클릭후 등록키가 없다면 <strong>&quot; create a new key &quot;</strong> 
-&gt; 이름 등록후 Drag &amp; Drop 또는 import from keyfile 로 KEY-file(EC2 키페어할때 받은 .pem파일) 가져오기
-&gt; (암호화된 파일이 열렸다면) 오른쪽 상단 save
<img src="https://velog.velcdn.com/images/eun_zii/post/81c10da5-b4d8-4174-8890-038eaad2307e/image.png" alt=""></p>
<ol start="5">
<li>인스턴스 접속
<img src="https://velog.velcdn.com/images/eun_zii/post/ded7d2b1-22bf-4db8-ae12-04aa12edb62b/image.png" alt=""></li>
</ol>
<h1 id="ec2-인스턴스-java-설치">EC2 인스턴스 JAVA 설치</h1>
<ol>
<li>AWS 에서 제공하는 jdk11 version 내려받기
<img src="https://velog.velcdn.com/images/eun_zii/post/a8af0b19-44ef-4d4b-b6f1-74bf89ea84cd/image.png" alt="">
✏️ sudo curl -L <a href="https://corretto.aws/downloads/latest/amazon-corretto-11-x64-linux-jdk.rpm">https://corretto.aws/downloads/latest/amazon-corretto-11-x64-linux-jdk.rpm</a> -o aws_corretto_jdk11.rpm ✏️</li>
</ol>
<p><img src="https://velog.velcdn.com/images/eun_zii/post/c639fb71-cd6d-4565-9c8a-58cf583ca378/image.png" alt="">
✏️ sudo yum localinstall aws_corretto_jdk11.rpm ✏️</p>
<p><img src="https://velog.velcdn.com/images/eun_zii/post/73b76c73-bc6c-47e4-bd59-cf435a6e8a27/image.png" alt="">
✏️ java -version ✏️</p>
<p>내려받고, 설치 완료 ⭐️</p>
<ol start="2">
<li>서버에 설치 되어있는 JAVA 중 원하는  JAVA를 선택할수 있는 명령어
<img src="https://velog.velcdn.com/images/eun_zii/post/229c4e68-c0f4-46c6-9a0f-ce18c4d5f0fd/image.png" alt="">
✏️ sudo /usr/sbin/alternatives --config java ✏️</li>
</ol>
<p>도움주신분 : <a href="https://junyharang.tistory.com/339">https://junyharang.tistory.com/339</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[NextJS ( CSS )]]></title>
            <link>https://velog.io/@eun_zii/NextJS-CSS</link>
            <guid>https://velog.io/@eun_zii/NextJS-CSS</guid>
            <pubDate>Sat, 01 Oct 2022 04:25:13 GMT</pubDate>
            <description><![CDATA[<h3 id="modulecss-파일-생성">.module.css 파일 생성</h3>
<ol>
<li><p>CSS 를 적용할 파일과 같은 폴더에 파일명.module.css 파일 생성
ex) NavBar.js
 NavBar.module.css</p>
</li>
<li><p>코드를 css에 적고</p>
<pre><code class="language-javascript">.active {
color: tomato;
}
.link {
text-decoration: none;
}</code></pre>
</li>
<li><p>.컴포넌트 이름 {CSS 작성} 적용할 파일에</p>
<pre><code class="language-javascript">import styles from &quot;./NavBar.module.css&quot;; 📍import 해주기

             &lt;a
       className={`${styles.link} ${ 
         router.pathname === &quot;/&quot; ? styles.active : &quot;&quot;
       }`} 📍 백틱 사용
     &gt;
       Home
     &lt;/a&gt;

             &lt;a
           className={[ 📍 배열 사용
         styles.link,
         router.pathname === &quot;/about&quot; ? styles.active : &quot;&quot;,
       ].join(&quot; &quot;)} 📍 join은 배열내에 것들을 합쳐줌
     &gt;
       About
     &lt;/a&gt;
</code></pre>
</li>
</ol>
<p>📌 백틱으로 여러개의 스타일을 주는방법과 배열로 주는 방법 2가지가 존재.</p>
<pre><code>


### &lt; style jsx&gt;&lt; /style&gt;
```javascript
&lt;nav&gt;
      &lt;Link href=&quot;/&quot;&gt;
        &lt;a className={router.pathname === &quot;/&quot; ? &quot;active&quot; : &quot;&quot;}&gt;Home&lt;/a&gt;
      &lt;/Link&gt;
      &lt;Link href=&quot;/about&quot;&gt;
        &lt;a className={router.pathname === &quot;/about&quot; ? &quot;active&quot; : &quot;&quot;}&gt;About&lt;/a&gt;
      &lt;/Link&gt;
      &lt;style jsx&gt;{`
        nav {
          background-color: tomato;
        }
        a {
          text-decoration: none;
        }
        .active {
          color: white;
        }
      `}&lt;/style&gt;
    &lt;/nav&gt;</code></pre><ul>
<li><p>사용할 컴포넌트 안에서  style jsx를 열어주고 css를 적기만하면 끝난다.
→ import 하지 않아도되는 장점과 클래스네임을 일일히 기억할 필요가 없는 장점이 있음.</p>
</li>
<li><p>module.css와 마찬가지로 다른 컴포넌트에서 같은 이름을 사용해도 겹치지 않는다. 
→ 무작위로 추가적인 클래스네임이 생성되기때문 → 변수이름짓는데 자유로워지며 충돌을 피할 수 있는 장점이있다.</p>
</li>
</ul>
<h3 id="globals-style-와-custom-app">Globals Style 와 Custom App</h3>
<ul>
<li>NextJS에서 globalsStyle을 적용하려면 appComponent를 custom해줘야 한다.</li>
</ul>
<h4 id="⭐️-_appjs-파일을-수정하면-서버를-재시작-해야함-⭐️">⭐️ _app.js 파일을 수정하면 서버를 재시작 해야함 ⭐️</h4>
<p>기본적으로 숨어져있는 app을 수정하려면 </p>
<ol>
<li><p>pages에 <strong>_app.js</strong>를 만들어야한다.</p>
</li>
<li><p>_app.js에서 App component를 생성하고, Component와 pageProps를 parameter로 받은 후 불러와준다. </p>
<pre><code class="language-javascript">export default function App({ Component, pageProps }) {
return (
 &lt;&gt;
   &lt;Component {...pageProps} /&gt;
 &lt;/&gt;
);
}</code></pre>
</li>
<li><p>그후 styles폴더안의 globals.css 를 불러온다. (module이 아닌 css는 커스텀app에서만 불러올 수 있음)</p>
<pre><code class="language-javascript">import &quot;../styles/globals.css&quot;; 📌
export default function App({ Component, pageProps }) {
return (
 &lt;&gt;
   &lt;Component {...pageProps} /&gt;
 &lt;/&gt;
);
}</code></pre>
</li>
<li><p>여러 페이지에 공통으로 사용되는 navBar나 footer를 임포트해준다.</p>
<pre><code class="language-javascript">import NavBar from &quot;../components/NavBar&quot;;
import &quot;../styles/globals.css&quot;;
export default function App({ Component, pageProps }) {
return (
 &lt;&gt;
   &lt;NavBar /&gt;
   &lt;Component {...pageProps} /&gt;
 &lt;/&gt;
);
}</code></pre>
</li>
<li><p>style jsx global 을 통해 추가로 글로벌스타일을 주거나, globals.css를 수정하여 글로벌 스타일을 줄 수 있다.</p>
<pre><code class="language-javascript">import NavBar from &quot;../components/NavBar&quot;;
import &quot;../styles/globals.css&quot;;
export default function App({ Component, pageProps }) {
return (
 &lt;&gt;
   &lt;NavBar /&gt;
   &lt;Component {...pageProps} /&gt;
   &lt;style jsx global&gt;
     {`
       * {
         font-size: 18px;
       }
     `}
   &lt;/style&gt;
 &lt;/&gt;
);
}</code></pre>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[REST API]]></title>
            <link>https://velog.io/@eun_zii/REST-API</link>
            <guid>https://velog.io/@eun_zii/REST-API</guid>
            <pubDate>Thu, 29 Sep 2022 05:57:04 GMT</pubDate>
            <description><![CDATA[<h2 id="🎣-api-">🎣 API :</h2>
<p>소프트웨어가 다른 소프트웨어로 부터 지정된 형식으로 요청, 명령을 받을수 있는 수단 하지만 네트워크상에서만 있는건 아니다. </p>
<h2 id="🎣-rest-api-">🎣 REST API :</h2>
<p>프론트엔드 웹에서 서버에 데이터를 요청하거나 (배달앱에서 서버에 주문을 넣거나 등) 이런 서비스들에서 사용되는 것이 REST 란 형식의 API 이다.</p>
<ol>
<li>각 요청이 어떤 동작이나 정보를 위한것인지를 그 요청의 모습 자체로 추론이 가능하다. - 레스트풀하게 만든 API는 요청을 보내는 주소만으로도 대략 이게 뭘 하는 요청인지 파악이 가능하다.</li>
<li>서버에 REST API로 요청을 보낼때는 HTTP라는 규약에 따라 신호를 전송한다. </li>
</ol>
<h4 id="🎣-rest-api-에서-주로-사용하는-메소드-">🎣 REST API 에서 주로 사용하는 메소드 :</h4>
<ul>
<li>GET : 데이터를 Read, 조회</li>
<li>POST : Create, 새로운 정보 추가</li>
<li>DELETE : Delete, 정보 삭제</li>
<li>PUT : Update, 정보를 통째로 변경할때</li>
<li>PATCH : Update, 정보를 일부만 변경할때</li>
</ul>
<p>✏️ POST, PUT, PATCH 에는 BODY 가 있어 GET, DELETE 보다 많이, 비교적 안전하게 감춰서 정보를 보낼수 있음</p>
<p>메소드들의 기능이 특정 용도에 제한되어 있지는 않지만 (ex. POST 하나로도 CRUD가 가능함) 누구든 각 요청의 의도를 쉽게 파악할수 있도록 RESTful하게 API를 만들기 위해서는 목적에 따라 구분해서 사용해야 함.</p>
<h1 id="⭐️-rest-api-설계-⭐️">⭐️ REST API 설계 ⭐️</h1>
<p>📌 URL에서는 동사(verb)를 사용하지 않는다.</p>
<p>터미널 에서 새로운터미널 </p>
<pre><code class="language-javascript">npm install -g json server</code></pre>
<p>설치 후 ,</p>
<pre><code class="language-javascript">json-server --watch ./경로📍 --port 30xx</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Docker]]></title>
            <link>https://velog.io/@eun_zii/Docker</link>
            <guid>https://velog.io/@eun_zii/Docker</guid>
            <pubDate>Wed, 28 Sep 2022 08:09:58 GMT</pubDate>
            <description><![CDATA[<p>Docker : 
어플리케이션을 패키징 할수 있는 툴
컨테이너라 불리는 소프트웨어 유닛안에 어플리케이션과 그에 필요한 시스템 툴, 환경설정 모든 dependencies 를 하나로 묶어서 다른 서버 다른 pc 그 어떤곳에도 쉽게 배포하고 안정적으로 구동할수 있게 도와주는 툴 이다.</p>
<blockquote>
<p>✏️ Dependency ( 의존성 ): 서비스의 기술 스택이 업그레이드 되거나 확장으로 인해 아키텍쳐 구조를 바꿀 상황은 항상 온다. 무엇인가 바뀔때마다 각각의 기술스택의 라이브러리 호환성과 의존성 문제를 체크해주어야 하는데 도커는 각 기술스택들을  분리된 컨테이너에 고립시키고 얽혀있는 호환성과 의존성 문제를 분리 시켜준다.</p>
</blockquote>
<p>🔸 node.js 의 경우 우리의 소스파일만 서버에 배포하는것으로는 어플리케이션을 구동하는데 문제가 있을수 있다. 이런 외부 라이브러리를 사용하면 여러 dependencies 와 환경 설정, 환경 변수 등 모든것들을 설정해줘야 하는데, 모든것을 설치,설정하는것은 번거롭고 오류도 많이 생길수 있음. 
docker 컨테이너를 사용하면 런타임 환경에 필요한 모든것들을 어떤 pc에서도 언제든지 사용할수 있다.</p>
<p>컨테이너만들기</p>
<ol>
<li>Docker File 만들기 - 컨테이너를 어떻게 만들어야하는 설명서같은 것</li>
<li>Image 만들기 - 어플리케이션을 실행하는데 필요한 모든 세팅들이 포함되어 있는것 (변경 불가함)</li>
<li>Container - image(class)를 이용해서 어플리케이션 구동하게 함</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[jQuery 와 AJAX]]></title>
            <link>https://velog.io/@eun_zii/jQuery-%EC%99%80-AJAX</link>
            <guid>https://velog.io/@eun_zii/jQuery-%EC%99%80-AJAX</guid>
            <pubDate>Wed, 28 Sep 2022 07:30:45 GMT</pubDate>
            <description><![CDATA[<h2 id="jquery">jQuery</h2>
<p>: 여러 브라우저에서 작동하는 사용하기 쉬운 API를 사용하여 HTML 문서 탐색 및 조작, 이벤트 처리, 애니메이션 및 Ajax와 같은 작업을 훨씬 더 간단하게 만드는 JavaScript 라이브러리</p>
<p>Using jQuery with a CDN : </p>
<pre><code class="language-javascript">  &lt;script
      src=&quot;https://code.jquery.com/jquery-3.6.1.js&quot;
      integrity=&quot;sha256-3zlB5s2uwoUzrXK3BT7AX3FyvojsraNFxCc2vC/7pNI=&quot;
      crossorigin=&quot;anonymous&quot;
    &gt;&lt;/script&gt;</code></pre>
<h2 id="ajax--asynchronous-javascript-and-xml-">AJAX ( Asynchronous JavaScript and XML )</h2>
<p>: 서버와 통신하기 위해 XML Http Request 객체를 사용하는 것을 말한다.</p>
<ul>
<li>JSON </li>
<li>XML</li>
<li>HTML </li>
<li>일반 텍스트 형식 </li>
</ul>
<p>등을 포함한 다양한 포맷을 주고 받을 수 있다. 
AJAX는 빠르게 동작하는 동적인 웹 페이지를 만들기 위한 개발 기법의 하나이며, AJAX의 강력한 특징은 <strong>웹 페이지 전체를 리프레쉬 하지 않고도 웹 페이지의 일부분만을 갱신할 수 있습니다. 즉 Ajax를 이용하면 백그라운드 영역에서 서버와 통신하여, 그 결과를 웹 페이지의 일부분에만 표시할 수 있습니다.</strong></p>
<h4 id="ajax-의-주요-두가지-특징">AJAX 의 주요 두가지 특징</h4>
<ul>
<li>페이지 새로고침 없이 서버에 요청</li>
<li>서버로부터 데이터를 받고 작업을 수행</li>
</ul>
<pre><code class="language-javascript">&lt;script&gt;
      $.ajax({
  method: &quot;POST&quot;,
  url: &quot;some.php&quot;,
  data: { name: &quot;John&quot;, location: &quot;Boston&quot; }
})
  .done(function( msg ) {
    alert( &quot;Data Saved: &quot; + msg );
  });
    &lt;/script&gt;</code></pre>
<p>✏️</p>
<ul>
<li>method : 전송방식</li>
<li>url : 주소</li>
<li>data: 보낼 데이터 Object 형식</li>
<li>.done() : 전송 완료 후 실행되는 함수</li>
</ul>
<p>🔸 .append() HTML 요소를 추가하는 jQuery 함수
🔸 어떤 API는 보안상 Access-Control-Allow-Origin 오류가 날 수 있음 -&gt; Front-End용 서버(Node.js 등)를 만들어 해결 가능 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Homebrew]]></title>
            <link>https://velog.io/@eun_zii/Homebrew</link>
            <guid>https://velog.io/@eun_zii/Homebrew</guid>
            <pubDate>Tue, 27 Sep 2022 14:02:07 GMT</pubDate>
            <description><![CDATA[<ul>
<li>Homebrew 설치</li>
</ul>
<p><a href="https://www.lainyzine.com/ko/article/how-to-install-homebrew-for-m1-apple-silicon/#iterm2-terminal-%EC%95%B1%EC%9D%B4-%EC%95%A0%ED%94%8C-%EC%8B%A4%EB%A6%AC%EC%BD%98-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EB%A1%9C-%EC%8B%A4%ED%96%89%EC%A4%91%EC%9D%B8%EC%A7%80-%ED%99%95%EC%9D%B8">https://www.lainyzine.com/ko/article/how-to-install-homebrew-for-m1-apple-silicon/#iterm2-terminal-앱이-애플-실리콘-아키텍처로-실행중인지-확인</a></p>
<ul>
<li>설치시 오류
<a href="https://worldseawater.tistory.com/87">https://worldseawater.tistory.com/87</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[CRUD , CI/CD]]></title>
            <link>https://velog.io/@eun_zii/CRUD-CICD</link>
            <guid>https://velog.io/@eun_zii/CRUD-CICD</guid>
            <pubDate>Tue, 27 Sep 2022 11:59:50 GMT</pubDate>
            <description><![CDATA[<h2 id="crud">CRUD</h2>
<p>는 대부분의 컴퓨터 소프트웨어가 가지는 기본적인 데이터 처리 기능인 <strong>Create(생성), Read(읽기), Update(갱신), Delete(삭제)</strong> 를 묶어서 일컫는 말이다.  사용자 인터페이스가 갖추어야 할 기능(정보의 참조/검색/갱신)을 가리키는 용어로서도 사용된다.</p>
<h2 id="ci--cd">CI / CD</h2>
<p>CI 는 개발자를 위한 자동화 프로세스인  지속적인 통합 ( Continuous Integration ) 을 의미하고,</p>
<p>CD 는 지속적인 배포 ( Continuous Deployment ) or 지속적인 제공 ( Continuous Delivery ) 를       의미한다. </p>
<p>✏️ 어플리케이션 개발 단계 부터 배포 때 까지 모든 단계들을 자동화를 통해서 사용자에게 배포 할수있도록 만드는것 ✏️</p>
<ul>
<li>지속적인 통합 이란 어플리케이션의 새로운 코드 변경 사항이 정기적으로 빌드/ 테스트 되어 공유 Repository에 (ex. git,github) 통합하는것을 의미</li>
</ul>
<p>   🔸 다수의 개발자가 한 팀으로 작업할 경우, 공유 리포지토리에 많은 commit들이 쌓이게 되는데 그때마다 충돌 할수 있는 코드들을 자동화된 빌드&amp;테스트로 방지할수 있다.</p>
<ul>
<li>배포 단계에서 “수동적”으로 배포하는것이 지속적인 제공 ( Continuous Delivery ) 이고 “자동화” 로 배포하는것이 지속적인 배포 ( Continuous Deployment ) 이다.</li>
</ul>
<p>사용 툴: 젠킨스, 빌드카이트 등</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[플로우차트]]></title>
            <link>https://velog.io/@eun_zii/%ED%94%8C%EB%A1%9C%EC%9A%B0%EC%B0%A8%ED%8A%B8</link>
            <guid>https://velog.io/@eun_zii/%ED%94%8C%EB%A1%9C%EC%9A%B0%EC%B0%A8%ED%8A%B8</guid>
            <pubDate>Tue, 27 Sep 2022 09:27:32 GMT</pubDate>
            <description><![CDATA[<h2 id="📌-플로우-차트-작성-추천-사이트">📌 플로우 차트 작성 추천 사이트</h2>
<ul>
<li><a href="https://app.diagrams.net/">https://app.diagrams.net/</a></li>
<li><a href="https://go.gliffy.com/go/html5/launch">https://go.gliffy.com/go/html5/launch</a></li>
</ul>
<h2 id="📌-플로우차트-란">📌 플로우차트 란?</h2>
<p>프로세스를 수행하기 위해 필요한 일련의 단계와 결정을 시각적으로 표현한 자료이다. 
각각의 단계는 다이어그램 도형 안에 표현이 되며 진행 순서는 화살표를 이용하여 표현한다. 이러한 플로우차트는 복잡한 프로세스를 명확하고 이해하기 쉬운 다이어그램으로 문서화하기 위해 사용된다.</p>
<h2 id="📌-플로우차트-기호">📌 플로우차트 기호</h2>
<p><a href="https://www.smartdraw.com/flowchart/flowchart-symbols.htm">https://www.smartdraw.com/flowchart/flowchart-symbols.htm</a>
<img src="https://velog.velcdn.com/images/eun_zii/post/b72dae09-87f0-4ab7-9388-e219b12c612f/image.jpeg" alt=""></p>
<h2 id="📌-플로우차트-작성법">📌 플로우차트 작성법</h2>
<ol>
<li>일관된 디자인 요소를 사용한다</li>
</ol>
<ul>
<li>플로우차트의 다이어그램 모양, 선, 텍스트를 일관성 있게 작성하면 산만함을 제거할 수 있다. 색상을 이용하여 프로세스 단계를 더욱 명확하게 표현하는 것도 좋은 방법이다.</li>
</ul>
<ol start="2">
<li>모든 프로세스를 한 페이지에 보관하자</li>
</ol>
<ul>
<li>순서도를 단일 페이지에 넣도록 하고 텍스트를 읽을 수 있는지 확인하는 것이 좋다. 다이어그램이 너무 커져서 페이지에 맞지 않는다면 여러 차트로 나누어 하이퍼 링크로 연결하도록 한다.</li>
</ul>
<ol start="3">
<li>왼쪽에서 오른쪽으로의 데이터 흐름을 유지하자</li>
</ol>
<ul>
<li>정보를 더 쉽게 읽고 이해할 수 있도록 왼쪽에서 오른쪽으로 플로우차트를 구성하는 것이 좋다.</li>
</ul>
<ol start="4">
<li>전통적인 마름모 의사결정 기호 대신 분할 경로를 사용하자</li>
</ol>
<ul>
<li>기존의 마름모꼴의 결정 기호는 위 규칙(왼쪽에서 오른쪽으로)을 위반하게 되므로 플로우차트를 읽기 어렵게 만든다.</li>
</ul>
<ol start="5">
<li>리턴라인은 아래 쪽에 배치하도록 하자</li>
</ol>
<ul>
<li>페이지 상단에서 아래로 이동하며 텍스트를 읽기 때문에 리턴 라인은 아래쪽에 위치하는 것이 좋다. 두 개의 리턴 라인이 필요한 경우 겹치지 않도록 유의한다.</li>
</ul>
<blockquote>
<p>출처: <a href="https://gongbu-ing.tistory.com/92">https://gongbu-ing.tistory.com/92</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[NextJS]]></title>
            <link>https://velog.io/@eun_zii/NEXT.JS</link>
            <guid>https://velog.io/@eun_zii/NEXT.JS</guid>
            <pubDate>Mon, 26 Sep 2022 13:37:33 GMT</pubDate>
            <description><![CDATA[<h3 id="설치">설치</h3>
<pre><code>npm create-next-app .  / npm create-next-app —typescript .</code></pre><p>✏️</p>
<pre><code> * name can no longer contain capital letters </code></pre><p>라는 에러가 뜨면 폴더명에 &quot; 대문자 &quot; 가 있어서 뜨는것. &quot; 소문자 &quot;로 변경.</p>
<h3 id="nextjs-와-react">NextJS 와 React</h3>
<p>react = library , CSR(client-side-rendering)
Nextjs = framework , SSR(server-side-rendering)
✏️ CSR : 클라이언트 사이드 렌더링 이란 사용자의 요청에 따라 필요한 부분만 응답 받아 렌더링 하는 방식 
SSR : 서버사이드 렌더링의 약자로 서버로부터 완전하게 만들어진 html파일을 받아와 페이지 전체를 렌더링 하는 방식 ✏️</p>
<ul>
<li>React에서는 Router,render 등 환경적인 것들을 직접 코드 작성해서 실행시켜줘야 한다면, NextJS는 규칙에 맞춰 코드만 잘 작성하면 자동으로 코드를 불러옴 </li>
<li>React 처럼 자유로운 수정은 불가함</li>
<li>유저에게 보여주고 싶은것이 있으면 pages 폴더내에 파일 시작은 <pre><code class="language-javascript">📌 export default function 으로 한다.</code></pre>
</li>
<li>React는 오류페이지 (404 등)을 작성해야하지만 NextJS는 default 페이지가 존재함 - 수정 가능</li>
<li>NextJS에서 npm run start 는 개발 환경을 실행 하는것이 아니라 &quot; 실 서버 &quot;를 실행하는것이다. 왜냐하면 NextJS는 서버까지 내장되어 있는 all-in-one 이기 때문이다.</li>
<li>API를 구현해서 React와 결합하면 간단하게 서버기능과 프론트엔드 기능을 사용할수있는 어플리케이션을 구축할수 있다.</li>
</ul>
<h3 id="장점">장점</h3>
<ul>
<li>앱에 있는 페이지들이 미리 렌더링 됨 - 정적으로 생성
React는 유저가 보는 모든 UI를 만들어야 한다. 브라우저가 js를 가져와서 그 js가 모든 UI를 만든다. html은 비어있는 &lt; div &gt; 하나뿐이다. (느린 연결에서 큰 단점이 생김- 빈 화면만 보인다 등 )
NextJs의 소스코드는 초기상태로(HTML) pre-rendering을 함 ( 느린연결에서도 HTML은 볼수있다. - API를 제외한 다른것들은 볼수있음)<br>그후에 React.js가 클라이언트로 전송되었을때 react app이 실행 된다.
React.js를 프론트엔드 안에서 실행하는 것을 hydration 이라 부른다.</li>
</ul>
<ul>
<li>NextJS는 ReactJS를 백엔드에서 동작시켜서 이 페이지를 미리 만드는데(ssr) 이게 component를 미리 렌더를하고, 렌더링이끝나면 HTML이 되고,
그 HTML을 소스코드에 넣어준다. 
그럼 유저는 로딩이 되지않았을때 미리 HTML을 볼수 있다.
그래서 SEO에 좋은것. (로딩이 되기전에 소스코드가 이미 있기 때문에)
✏️ 검색엔진최적화 (<strong>S</strong>earch <strong>E</strong>ngine <strong>O</strong>ptimization) : 검색을 하면 검색엔진은 인덱싱해둔 수많은 웹 페이지 중 가장 적합한 순서대로 결과를 노출하는데 그중 <strong>자신의 웹 페이지가 더 많이 노출되도록 최적화된 컨텐츠를 만드는 것</strong></li>
</ul>
<h3 id="rules">RULES</h3>
<h4 id="⭐️--page-폴더내에-파일명이-url이-됨-소문자로-작성--파일내에-component-이름은-중요하지-않음-⭐️"><strong>⭐️ ( page 폴더내에 파일명이 url이 됨 (소문자로 작성) / 파일내에 component 이름은 중요하지 않음!) ⭐️</strong></h4>
<ul>
<li>함수형 컴포넌트에서 jsx 를 리턴하는 default export 함수는 함수선언문으로 정의한다.(= export default function ) 그 외 함수들은 화살표 함수를 사용한다.</li>
<li>nextjs에서는 anchor태그( &lt; a &gt; )를 사용하지않는다. 
→ React의 Link와 같음.(새로고침방지) 
→ next/link의 Link href를 사용 
→ clinet side rendering이 가능하지만 className, style 등을 넣어줄때는 &lt; Link &gt;&lt; /Link&gt; 안에 a태그에서 해줘야한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/eun_zii/post/307be822-a2f7-44d7-a04e-4a7b3426d86c/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Instagram-로그인]]></title>
            <link>https://velog.io/@eun_zii/Instagram-%EB%A1%9C%EA%B7%B8%EC%9D%B8</link>
            <guid>https://velog.io/@eun_zii/Instagram-%EB%A1%9C%EA%B7%B8%EC%9D%B8</guid>
            <pubDate>Fri, 16 Sep 2022 08:48:48 GMT</pubDate>
            <description><![CDATA[<h2 id="🎣-1-routerjs-생성">🎣 1. Router.js 생성</h2>
<pre><code class="language-javascript">import { BrowserRouter, Routes, Route } from &#39;react-router-dom&#39;
import { Login, Main, Signup } from &#39;./Components/Pages&#39;

const Router = () =&gt; {
  return (
    &lt;BrowserRouter&gt;
      &lt;Routes&gt;
        &lt;Route path=&quot;/&quot; element={&lt;Main /&gt;} /&gt;
        &lt;Route path=&quot;/login&quot; element={&lt;Login /&gt;} /&gt;.
        &lt;Route path=&quot;/signup&quot; element={&lt;Signup /&gt;} /&gt;.
      &lt;/Routes&gt;
    &lt;/BrowserRouter&gt;
  )
}

export default Router</code></pre>
<h2 id="🎣-2-indexjs">🎣 2. index.js</h2>
<pre><code class="language-javascript">export { default as Login } from &#39;./Login&#39;
export { default as Main } from &#39;./Main&#39;
export { default as Signup } from &#39;./Signup&#39;</code></pre>
<h2 id="🎣-2-1-appjs-에-router-➡--import">🎣 2-1. App.js 에 Router ➡  import</h2>
<pre><code class="language-javascript">import Router from &#39;./Router&#39;

function App() {
  return &lt;Router /&gt;
}

export default App</code></pre>
<h2 id="🎣-3-loginjsx-생성">🎣 3. Login.jsx 생성</h2>
<pre><code class="language-javascript">import styled from &#39;styled-components&#39;
import { Link } from &#39;react-router-dom&#39;
import {
  PageWrapper,
  Main,
  Box,
  Logo,
  BtnSubmit,
  Form,
  InputText,
  SignupWrapper,
  CustomLink,
} from &#39;../atoms/login&#39;
import { FaFacebook } from &#39;react-icons/fa&#39;

const Login = () =&gt; {
  return (
    &lt;PageWrapper&gt;
      &lt;Main&gt;
        &lt;Box&gt;
          &lt;Logo src=&quot;https://cdn.apple-economy.com/news/photo/201612/30523_15394_5059.png&quot; /&gt;
          &lt;Form&gt;
            &lt;InputText placeholder=&quot;전화번호, 사용자 이름 또는 이메일&quot; /&gt;
            &lt;InputText placeholder=&quot;비밀번호&quot; type=&quot;password&quot; /&gt;
            &lt;BtnSubmit&gt;로그인&lt;/BtnSubmit&gt;
          &lt;/Form&gt;
          &lt;FBLogin&gt;
            &lt;FaFacebook&gt;&lt;/FaFacebook&gt;Facebook으로 로그인
          &lt;/FBLogin&gt;
          &lt;ForgotPassword&gt;비밀번호를 잊으셨나요?&lt;/ForgotPassword&gt;
        &lt;/Box&gt;
        &lt;Box&gt;
          &lt;SignupWrapper&gt;
            계정이 없으신가요? &lt;CustomLink to=&quot;/Signup&quot;&gt;가입하기&lt;/CustomLink&gt;
          &lt;/SignupWrapper&gt;
        &lt;/Box&gt;
      &lt;/Main&gt;
    &lt;/PageWrapper&gt;
  )
}

const FBLogin = styled.div`
  color: #385185;
  font-weight: bold;
  font-size: 14px;
  margin-top: 30px;
`
const ForgotPassword = styled.div`
  font-size: 12px;
  margin-top: 20px;
`
export default Login</code></pre>
<h2 id="🎣-4-signupjsx-생성">🎣 4. Signup.jsx 생성</h2>
<pre><code class="language-javascript">import styled from &#39;styled-components&#39;
import { Link } from &#39;react-router-dom&#39;
import {
  PageWrapper,
  Main,
  Box,
  Logo,
  BtnSubmit,
  Form,
  InputText,
  SignupWrapper,
  CustomLink,
} from &#39;../atoms/login&#39;
import { FaFacebook } from &#39;react-icons/fa&#39;

const Signup = () =&gt; {
  return (
    &lt;PageWrapper&gt;
      &lt;Main&gt;
        &lt;Box&gt;
          &lt;Logo src=&quot;https://cdn.apple-economy.com/news/photo/201612/30523_15394_5059.png&quot; /&gt;
          &lt;Welcom&gt;친구들의 사진과 동영상을 보려면 가입하세요.&lt;/Welcom&gt;
          &lt;BtnSubmit&gt;
            &lt;FaFacebook&gt;&lt;/FaFacebook&gt;Facebook으로 로그인
          &lt;/BtnSubmit&gt;
          &lt;Form&gt;
            &lt;InputText placeholder=&quot;성명&quot; /&gt;
            &lt;InputText placeholder=&quot;사용자 이름&quot; /&gt;
            &lt;InputText placeholder=&quot;비밀번호&quot; type=&quot;password&quot; /&gt;
            &lt;BtnSubmit&gt;가입&lt;/BtnSubmit&gt;
          &lt;/Form&gt;
        &lt;/Box&gt;
        &lt;Box&gt;
          &lt;SignupWrapper&gt;
            계정이 있으신가요? &lt;CustomLink to=&quot;/Login&quot;&gt;로그인&lt;/CustomLink&gt;
          &lt;/SignupWrapper&gt;
        &lt;/Box&gt;
      &lt;/Main&gt;
    &lt;/PageWrapper&gt;
  )
}

const Welcom = styled.div`
  display: flex;
  flex-direction: column;
`

export default Signup</code></pre>
<h2 id="🎣-5-atoms-폴더-생성-후-loginjs-생성">🎣 5. atoms 폴더 생성 후 Login.js 생성</h2>
<pre><code class="language-javascript">import styled from &#39;styled-components&#39;
import { Link } from &#39;react-router-dom&#39;

export const PageWrapper = styled.div`
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fafafa;
`
export const Main = styled.div`
  width: 350px;
`
export const Box = styled.div`
  background: #fff;
  border: 1px solid #dbdbdb;
  padding: 10px 0;
  text-align: center;
  margin-bottom: 10px;
`
export const Logo = styled.img`
  width: 230px;
`
export const Form = styled.form`
  display: flex;
  flex-direction: column;
  padding: 0 40px;
  margin-top: 24px;
`
export const InputText = styled.input`
  height: 36px;
  background: #fafafa;
  border: 1px solid #dbdbdb;
  border-radius: 3px;
  padding-left: 8px;
  &amp; + &amp; {
    margin-top: 6px;
  }
`
export const BtnSubmit = styled.button`
  background: #0095f6;
  color: #fff;
  border: none;
  border-radius: 4px;
  padding: 5px 9px;
  font-weight: bold;
  margin: 8px 0;
`
export const SignupWrapper = styled.div`
  padding: 15px 0;
  font-size: 14px;
`
export const CustomLink = styled(Link)`
  text-decoration: none;
  font-weight: bold;
  color: #0095f6;
`</code></pre>
<h4 id="📌-loginjsx-와-signupjsx-에서-중복되는-styled-components들을-하나로-묶은후-각-각-import-해주기">📌 Login.jsx 와 Signup.jsx 에서 중복되는 styled-components들을 하나로 묶은후 각 각 import 해주기</h4>
<pre><code class="language-javascript">import {
  PageWrapper,
  Main,
  Box,
  Logo,
  BtnSubmit,
  Form,
  InputText,
  SignupWrapper,
  CustomLink,
} from &#39;../atoms/login&#39;</code></pre>
<p><img src="https://velog.velcdn.com/images/eun_zii/post/a5103fa1-faf3-44ba-abab-7c990888456c/image.png" alt="">
<img src="https://velog.velcdn.com/images/eun_zii/post/591ecfc8-f01a-4dee-b59a-4b965b5aea63/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Pagination, Querystring]]></title>
            <link>https://velog.io/@eun_zii/Pagination-Querystring</link>
            <guid>https://velog.io/@eun_zii/Pagination-Querystring</guid>
            <pubDate>Thu, 15 Sep 2022 09:11:34 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/eun_zii/post/fbb59d5c-0582-4562-be3c-8a6fcd737681/image.png" alt=""></p>
<h2 id="🎣-paginationjsx-생성">🎣 Pagination.jsx 생성</h2>
<pre><code class="language-javascript">import styled from &#39;styled-components&#39;

const Pagination = ({ nowPage, total, onPageChange }) =&gt; {
  const lastPage = Math.ceil(total / 10)
  const startPage = Math.ceil(nowPage / 10) * 10 - 9
  const endPage = startPage + 9 &gt; lastPage ? lastPage : startPage + 9

  const pageList = []
  for (let i = startPage; i &lt;= endPage; i++) {
    pageList.push(i)
  }
  return (
    &lt;List&gt;
      {nowPage &gt; 1 &amp;&amp; (
        &lt;Page onClick={() =&gt; onPageChange(nowPage - 1)}&gt;{&#39;&lt;&#39;}&lt;/Page&gt;
      )}
      {pageList.map((page) =&gt; (
        &lt;Page
          isActive={page === nowPage}
          key={page}
          onClick={() =&gt; onPageChange(page)}
        &gt;
          {page}
        &lt;/Page&gt;
      ))}
      {nowPage &lt; lastPage &amp;&amp; (
        &lt;Page onClick={() =&gt; onPageChange(nowPage + 1)}&gt;{&#39;&gt;&#39;}&lt;/Page&gt;
      )}
    &lt;/List&gt;
  )
}

const List = styled.div`
  display: flex;
  justify-content: center;
`
const Page = styled.button`
  background: ${({ isActive }) =&gt; isActive &amp;&amp; &#39;#000&#39;};
  color: ${({ isActive }) =&gt; isActive &amp;&amp; &#39;#fff&#39;};
`

export default Pagination</code></pre>
<h2 id="🎣-moviejsx">🎣 Movie.jsx</h2>
<pre><code class="language-javascript">import { useEffect, useState } from &#39;react&#39;
import styled from &#39;styled-components&#39;
import { getMovieList } from &#39;../../apis&#39;
import MovieList from &#39;../organisms/MovieList&#39;
import { countryList, genreList } from &#39;../../datas&#39;
import Pagination from &#39;../organisms/Pagination&#39;

const Movie = () =&gt; {
  const [total, setTotal] = useState(0)
  const [page, setPage] = useState(1)
  const [text, setText] = useState(&#39;&#39;)
  const [country, setCountry] = useState(&#39;ALL&#39;)
  const [genre, setGenre] = useState(&#39;ALL&#39;)
  const [movieList, setMovieList] = useState([])

  useEffect(() =&gt; {
    searchMovieList()
  }, [country, genre, page])

  const handleSubmit = async (e) =&gt; {
    e.preventDefault()
    setPage(1)

    searchMovieList()
  }
  const searchMovieList = async () =&gt; {
    if (text === &#39;&#39;) return
    // const params = { query: text, country }
    // if(country === &quot;ALL&quot;) delete params.country;

    const start = page * 10 - 9

    const params = { query: text, start }
    if (country !== &#39;ALL&#39;) params.country = country
    if (genre !== &#39;ALL&#39;) params.genre = genre
    const { items, total } = await getMovieList(params)
    setMovieList(items)
    setTotal(total)
  }

  return (
    &lt;Wrapper&gt;
      &lt;PageTitle&gt;🎬 MOVIE 🎬&lt;/PageTitle&gt;
      &lt;Form onSubmit={handleSubmit}&gt;
        &lt;select onChange={(e) =&gt; setCountry(e.target.value)} value={country}&gt;
          &lt;option value=&quot;ALL&quot;&gt;전체&lt;/option&gt;
          {countryList.map(({ code, name }) =&gt; (
            &lt;option value={code} key={code}&gt;
              {name}
            &lt;/option&gt;
          ))}
        &lt;/select&gt;
        &lt;select onChange={(e) =&gt; setGenre(e.target.value)} value={genre}&gt;
          &lt;option value=&quot;ALL&quot;&gt;전체&lt;/option&gt;
          {genreList.map(({ code, name }) =&gt; (
            &lt;option value={code} key={code}&gt;
              {name}
            &lt;/option&gt;
          ))}
        &lt;/select&gt;
        &lt;InputText
          placeholder=&quot;search&quot;
          onChange={(e) =&gt; setText(e.target.value)}
        /&gt;
        &lt;BtnSubmit&gt;검색&lt;/BtnSubmit&gt;
      &lt;/Form&gt;
      &lt;MovieList data={movieList} /&gt;
      &lt;Pagination
        nowPage={page}
        total={total}
        onPageChange={(page) =&gt; setPage(page)}
      /&gt;
    &lt;/Wrapper&gt;
  )
}

const Wrapper = styled.div``
const PageTitle = styled.h2``
const Form = styled.form`
  display: flex;
  padding: 15px;
`
const InputText = styled.input`
  flex: 1;
  margin-right: 15px;
`
const BtnSubmit = styled.button``

export default Movie</code></pre>
<h2 id="🎣-bookjsx">🎣 Book.jsx</h2>
<pre><code class="language-javascript">import { useEffect, useState } from &#39;react&#39;
import styled from &#39;styled-components&#39;
import { getBookList } from &#39;../../apis&#39;
import BookList from &#39;../organisms/BookList&#39;
import Pagination from &#39;../organisms/Pagination&#39;
import { useLocation, useNavigate } from &#39;react-router-dom&#39;
import qs from &#39;qs&#39;

const Book = () =&gt; {
  const navigate = useNavigate()
  const { search } = useLocation()

  const [text, setText] = useState(&#39;&#39;)
  const [query, setQuery] = useState(&#39;&#39;)
  const [bookList, setBookList] = useState([])
  const [page, setPage] = useState(1)
  const [total, setTotal] = useState(0)

  useEffect(() =&gt; {
    const reset = () =&gt; {
      setText(&#39;&#39;)
      setQuery(&#39;&#39;)
      setPage(1)
      setTotal(0)
      setBookList([])
    }
    const { query, page } = qs.parse(search.slice(1))
    if (query) {
      setQuery(query)
      setText(query)
      if (page) setPage(+page)
    } else {
      reset()
    }
  }, [search])

  useEffect(() =&gt; {
    searchList()
  }, [page, query])
  const handleSubmit = (e) =&gt; {
    e.preventDefault()
    setPage(1)
    setQuery(text)
  }
  const searchList = async () =&gt; {
    if (query === &#39;&#39;) return
    const start = page * 10 - 9
    const { items, total } = await getBookList({ query, start })
    setBookList(items)
    setTotal(total)

    const search = qs.stringify({ query, page })
    navigate({ search })
  }

  return (
    &lt;Wrapper&gt;
      &lt;PageTitle&gt;📚 BOOK 📚&lt;/PageTitle&gt;
      &lt;Form onSubmit={handleSubmit}&gt;
        &lt;InputText
          placeholder=&quot;search&quot;
          value={text}
          onChange={(e) =&gt; setText(e.target.value)}
        /&gt;
        &lt;BtnSubmit&gt;검색&lt;/BtnSubmit&gt;
      &lt;/Form&gt;
      &lt;BookList data={bookList} /&gt;
      &lt;Pagination
        nowPage={page}
        total={total}
        onPageChange={(page) =&gt; setPage(page)}
      /&gt;
    &lt;/Wrapper&gt;
  )
}

const Wrapper = styled.div``
const PageTitle = styled.h2``
const Form = styled.form`
  display: flex;
  padding: 15px;
`
const InputText = styled.input`
  flex: 1;
  margin-right: 15px;
`
const BtnSubmit = styled.button``

export default Book</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[TopNav]]></title>
            <link>https://velog.io/@eun_zii/TopNav</link>
            <guid>https://velog.io/@eun_zii/TopNav</guid>
            <pubDate>Mon, 22 Aug 2022 08:19:51 GMT</pubDate>
            <description><![CDATA[<h2 id="🎣-1-organisms--topnavjsx-생성">🎣 1. organisms &gt; TopNav.jsx 생성</h2>
<pre><code class="language-javascript">import { Link, useLocation } from &#39;react-router-dom&#39;
import styled from &#39;styled-components&#39;

const linkList = [
  {
    link: &#39;/&#39;,
    name: &#39;Main&#39;,
  },
  {
    link: &#39;/movie&#39;,
    name: &#39;Movie&#39;,
  },
  {
    link: &#39;/book&#39;,
    name: &#39;Book&#39;,
  },
]

const TopNav = () =&gt; {
  const { pathname } = useLocation()

  if (pathname === &#39;/&#39;) return &lt;&gt;&lt;/&gt;

  return (
    &lt;Container&gt;
      &lt;Nav&gt;
        {linkList.map(({ link, name }) =&gt; (
          &lt;Link to={link} key={link}&gt;
            &lt;Button isActive={pathname === link}&gt;{name}&lt;/Button&gt;
          &lt;/Link&gt;
        ))}
      &lt;/Nav&gt;
    &lt;/Container&gt;
  )
}

const Container = styled.header`
  height: 60px;
  background: #fff;
  border-bottom: 1px solid #ddd;
  display: flex;
  align-items: center;
`
const Nav = styled.nav``
const Button = styled.button`
  padding: 10px 15px;
  background: ${({ isActive }) =&gt; (isActive ? &#39;#000&#39; : &#39;#fff&#39;)};
  color: ${({ isActive }) =&gt; isActive &amp;&amp; &#39;#fff&#39;};
  border: 1px solid #ddd;
  border-radius: 4px;
  margin: 0 5px;
`

export default TopNav</code></pre>
<h2 id="🎣-2-routerjs-에-추가">🎣 2. Router.js 에 추가</h2>
<pre><code class="language-javascript">const Router = () =&gt; {
  return (
    &lt;BrowserRouter&gt;
      &lt;TopNav /&gt; 📌
      &lt;Routes&gt;
        &lt;Route path=&quot;/&quot; element={&lt;Main /&gt;} /&gt;
        &lt;Route path=&quot;/movie&quot; element={&lt;Movie /&gt;} /&gt;
        &lt;Route path=&quot;/book&quot; element={&lt;Book /&gt;} /&gt;
        &lt;Route path=&quot;/book/:isbn&quot; element={&lt;BookDetail /&gt;} /&gt;
      &lt;/Routes&gt;
    &lt;/BrowserRouter&gt;
  )
}</code></pre>
<p><img src="https://velog.velcdn.com/images/eun_zii/post/a2e63ac4-b5c3-4d9d-8ddc-28699ae0e8b5/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Naver 책 검색]]></title>
            <link>https://velog.io/@eun_zii/Naver-%EC%B1%85-%EA%B2%80%EC%83%89</link>
            <guid>https://velog.io/@eun_zii/Naver-%EC%B1%85-%EA%B2%80%EC%83%89</guid>
            <pubDate>Thu, 11 Aug 2022 07:20:48 GMT</pubDate>
            <description><![CDATA[<h2 id="🎣-1-routerjs-생성">🎣 1. Router.js 생성</h2>
<pre><code class="language-javascript">import { BrowserRouter, Routes, Route } from &#39;react-router-dom&#39;
import Main from &#39;./components/pages/Main&#39;
import Movie from &#39;./components/pages/Movie&#39;
import Book from &#39;./components/pages/Book&#39;

const Router = () =&gt; {
  return (
    &lt;BrowserRouter&gt;
      &lt;Routes&gt;
        &lt;Route path=&quot;/&quot; element={&lt;Main /&gt;} /&gt;
        &lt;Route path=&quot;/movie&quot; element={&lt;Movie /&gt;} /&gt;
        &lt;Route path=&quot;/book&quot; element={&lt;Book /&gt;} /&gt;
      &lt;/Routes&gt;
    &lt;/BrowserRouter&gt;
  )
}

export default Router</code></pre>
<h2 id="🎣-2-mainjsx">🎣 2. Main.jsx</h2>
<pre><code class="language-javascript">import { Link } from &#39;react-router-dom&#39;
import styled from &#39;styled-components&#39;

const Main = () =&gt; {
  return (
    &lt;Wrapper&gt;
      &lt;PageTitle&gt;영화 🎬 &amp; 책 📚 검색&lt;/PageTitle&gt;
      &lt;Link to=&quot;/Movie&quot;&gt;
        &lt;Button&gt;영화 🎬&lt;/Button&gt;
      &lt;/Link&gt;
      &lt;Link to=&quot;/Book&quot;&gt;
        &lt;Button&gt;책 📚&lt;/Button&gt;
      &lt;/Link&gt;
    &lt;/Wrapper&gt;
  )
}

const Wrapper = styled.div`
  padding: 15px;
`
const PageTitle = styled.h2`
  text-align: center;
`
const Button = styled.button`
  width: 100%;
  margin: 10px 0;
  height: 100px;
  font-size: 24px;
  border: none;
  border-radius: 4px;
`

export default Main</code></pre>
<p><img src="https://velog.velcdn.com/images/eun_zii/post/9a4a5e97-cbc8-4ff2-893f-1f978c151fc9/image.png" alt=""></p>
<h2 id="🎣-3-bookjsx">🎣 3. Book.jsx</h2>
<pre><code class="language-javascript">import { useState } from &#39;react&#39;
import styled from &#39;styled-components&#39;
import { getBookList } from &#39;../../apis&#39;
import BookList from &#39;../organisms/BookList&#39;

const Book = () =&gt; {
  const [text, setText] = useState(&#39;&#39;)
  const [bookList, setBookList] = useState([])

  const handleSubmit = async (e) =&gt; {
    e.preventDefault()

    const { items } = await getBookList({ query: text })
    setBookList(items)
  }

  return (
    &lt;Wrapper&gt;
      &lt;PageTitle&gt;📚 BOOK 📚&lt;/PageTitle&gt;
      &lt;Form onSubmit={handleSubmit}&gt;
        &lt;InputText
          placeholder=&quot;search&quot;
          value={text}
          onChange={(e) =&gt; setText(e.target.value)}
        /&gt;
        &lt;BtnSubmit&gt;검색&lt;/BtnSubmit&gt;
      &lt;/Form&gt;
      &lt;BookList data={bookList} /&gt;
    &lt;/Wrapper&gt;
  )
}

const Wrapper = styled.div``
const PageTitle = styled.h2``
const Form = styled.form`
  display: flex;
  padding: 15px;
`
const InputText = styled.input`
  flex: 1;
  margin-right: 15px;
`
const BtnSubmit = styled.button``

export default Book</code></pre>
<h2 id="🎣-3-1-booklistjsx">🎣 3-1. BookList.jsx</h2>
<pre><code class="language-javascript">import styled from &#39;styled-components&#39;

const BookList = ({ data }) =&gt; {
  return (
    &lt;List&gt;
      {data.map(({ image, title }) =&gt; (
        &lt;Item key={image}&gt;
          &lt;Thumbnail src={image} /&gt;
          &lt;Title dangerouslySetInnerHTML={{ __html: title }} /&gt;
        &lt;/Item&gt;
      ))}
    &lt;/List&gt;
  )
}

const List = styled.div`
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 10px;
  padding: 15px;
`
const Item = styled.div``
const Thumbnail = styled.img`
  width: 100%;
`
const Title = styled.span``

export default BookList</code></pre>
<h2 id="🎣-3-2-srcapisindexjs-파일생성">🎣 3-2. src&gt;apis&gt;index.js 파일생성</h2>
<pre><code class="language-javascript">import axios from &#39;axios&#39;

export const getBookList = async (params) =&gt; {
  const { data } = await axios.get(&#39;/v1/search/book.json&#39;, {
    headers: {
      &#39;X-Naver-Client-Id&#39;: &#39;ID&#39;,
      &#39;X-Naver-Client-Secret&#39;: &#39;PW&#39;,
    },
    params,
  })

  return data
}</code></pre>
<p><img src="https://velog.velcdn.com/images/eun_zii/post/397ac5d9-2265-41c7-8d96-afb717442d15/image.png" alt=""></p>
<blockquote>
<p>📌 서버를 만들수 없으니 package.json 에서 
&quot;proxy&quot;: &quot;<a href="https://openapi.naver.com&quot;">https://openapi.naver.com&quot;</a> 추가해주기</p>
</blockquote>
<ul>
<li>proxy 는 개발과정에서만 사용가능. 배포 할때는 서버 필요함. 
(즉, 연습때만 사용할수 있음) 📌</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Naver 영화 검색]]></title>
            <link>https://velog.io/@eun_zii/Naver-%EC%98%81%ED%99%94-%EA%B2%80%EC%83%89</link>
            <guid>https://velog.io/@eun_zii/Naver-%EC%98%81%ED%99%94-%EA%B2%80%EC%83%89</guid>
            <pubDate>Wed, 10 Aug 2022 08:28:34 GMT</pubDate>
            <description><![CDATA[<h2 id="🎣-1-routerjs-생성">🎣 1. Router.js 생성</h2>
<pre><code class="language-javascript">import { BrowserRouter, Routes, Route } from &#39;react-router-dom&#39;
import Main from &#39;./components/pages/Main&#39;
import Movie from &#39;./components/pages/Movie&#39;
import Book from &#39;./components/pages/Book&#39;

const Router = () =&gt; {
  return (
    &lt;BrowserRouter&gt;
      &lt;Routes&gt;
        &lt;Route path=&quot;/&quot; element={&lt;Main /&gt;} /&gt;
        &lt;Route path=&quot;/movie&quot; element={&lt;Movie /&gt;} /&gt;
        &lt;Route path=&quot;/book&quot; element={&lt;Book /&gt;} /&gt;
      &lt;/Routes&gt;
    &lt;/BrowserRouter&gt;
  )
}

export default Router</code></pre>
<h2 id="🎣-2-mainjsx">🎣 2. Main.jsx</h2>
<pre><code class="language-javascript">import { Link } from &#39;react-router-dom&#39;
import styled from &#39;styled-components&#39;

const Main = () =&gt; {
  return (
    &lt;Wrapper&gt;
      &lt;PageTitle&gt;영화 🎬 &amp; 책 📚 검색&lt;/PageTitle&gt;
      &lt;Link to=&quot;/Movie&quot;&gt;
        &lt;Button&gt;영화 🎬&lt;/Button&gt;
      &lt;/Link&gt;
      &lt;Link to=&quot;/Book&quot;&gt;
        &lt;Button&gt;책 📚&lt;/Button&gt;
      &lt;/Link&gt;
    &lt;/Wrapper&gt;
  )
}

const Wrapper = styled.div`
  padding: 15px;
`
const PageTitle = styled.h2`
  text-align: center;
`
const Button = styled.button`
  width: 100%;
  margin: 10px 0;
  height: 100px;
  font-size: 24px;
  border: none;
  border-radius: 4px;
`

export default Main</code></pre>
<p><img src="https://velog.velcdn.com/images/eun_zii/post/9a4a5e97-cbc8-4ff2-893f-1f978c151fc9/image.png" alt=""></p>
<h2 id="🎣-3-moviejsx">🎣 3. Movie.jsx</h2>
<pre><code class="language-javascript">import { useState } from &#39;react&#39;
import styled from &#39;styled-components&#39;
import { getMovieList } from &#39;../../apis&#39;
import MovieList from &#39;../organisms/MovieList&#39;

const Movie = () =&gt; {
  const [text, setText] = useState(&#39;&#39;)
  const [movieList, setMovieList] = useState([])

 const handleSubmit = async (e) =&gt; {
    e.preventDefault()

    const { items } = await getMovieList({ query: text })
    setMovieList(items)
  }

  return (
    &lt;Wrapper&gt;
      &lt;PageTitle&gt;🎬 Movie 🎬&lt;/PageTitle&gt;
      &lt;Form onSubmit={handleSubmit}&gt;
        &lt;InputText
          placeholder=&quot;search&quot;
          value={text}
          onChange={(e) =&gt; setText(e.target.value)}
        /&gt;
        &lt;BtnSubmit&gt;검색&lt;/BtnSubmit&gt;
      &lt;/Form&gt;
      &lt;MovieList data={movieList} /&gt;
    &lt;/Wrapper&gt;
  )
}

const Wrapper = styled.div``
const PageTitle = styled.h2``
const Form = styled.form`
  display: flex;
  padding: 15px;
`
const InputText = styled.input`
  flex: 1;
  margin-right: 15px;
`
const BtnSubmit = styled.button``

export default Movie</code></pre>
<h2 id="🎣-3-1-movielistjsx">🎣 3-1. MovieList.jsx</h2>
<pre><code class="language-javascript">import styled from &#39;styled-components&#39;

const MovieList = ({ data }) =&gt; {
  return (
    &lt;List&gt;
      {data.map(({ image, title }) =&gt; (
        &lt;Item key={image}&gt;
          &lt;Thumbnail src={image} /&gt;
          &lt;Title dangerouslySetInnerHTML={{ __html: title }} /&gt;
        &lt;/Item&gt;
      ))}
    &lt;/List&gt;
  )
}

const List = styled.div`
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 10px;
  padding: 15px;
`
const Item = styled.div``
const Thumbnail = styled.img`
  width: 100%;
`
const Title = styled.span``

export default MovieList</code></pre>
<h2 id="🎣-3-2-srcapisindexjs-파일생성">🎣 3-2. src&gt;apis&gt;index.js 파일생성</h2>
<pre><code class="language-javascript">import axios from &#39;axios&#39;

export const getMovieList = async (params) =&gt; {
  const { data } = await axios.get(&#39;/v1/search/movie.json&#39;, {
    headers: {
      &#39;X-Naver-Client-Id&#39;: &#39;ID&#39;,
      &#39;X-Naver-Client-Secret&#39;: &#39;PW&#39;,
    },
    params,
  })

  return data
}</code></pre>
<p><img src="https://velog.velcdn.com/images/eun_zii/post/d19a01b4-2041-4c57-b2b1-8352a4c7e07a/image.png" alt=""></p>
<blockquote>
<p>📌 서버를 만들수 없으니 package.json 에서 
&quot;proxy&quot;: &quot;<a href="https://openapi.naver.com&quot;">https://openapi.naver.com&quot;</a> 추가해주기</p>
</blockquote>
<ul>
<li>proxy 는 개발과정에서만 사용가능. 배포 할때는 서버 필요함. 
(즉, 연습때만 사용할수 있음) 📌</li>
</ul>
<hr>
<h1 id="🔫-검색에-국가장르-넣기-🔫">🔫 검색에 국가,장르 넣기 🔫</h1>
<h3 id="1-srcdatasindexjs-파일-생성">1. src&gt;datas&gt;index.js 파일 생성</h3>
<pre><code class="language-javascript">export const countryList = [
  {
    code: &#39;KR&#39;,
    name: &#39;한국&#39;,
  },
  {
    code: &#39;JP&#39;,
    name: &#39;일본&#39;,
  },
  {
    code: &#39;US&#39;,
    name: &#39;미국&#39;,
  },
  {
    code: &#39;HK&#39;,
    name: &#39;홍콩&#39;,
  },
  {
    code: &#39;GB&#39;,
    name: &#39;영국&#39;,
  },
  {
    code: &#39;FR&#39;,
    name: &#39;프랑스&#39;,
  },
  {
    code: &#39;ETC&#39;,
    name: &#39;기타&#39;,
  },
]

export const genreList = [
  {
    code: &#39;1&#39;,
    name: &#39;드라마&#39;,
  },
  {
    code: &#39;2&#39;,
    name: &#39;판타지&#39;,
  },
  {
    code: &#39;3&#39;,
    name: &#39;공포&#39;,
  },
  {
    code: &#39;4&#39;,
    name: &#39;로맨스&#39;,
  },
  {
    code: &#39;5&#39;,
    name: &#39;미스터리&#39;,
  },
  {
    code: &#39;6&#39;,
    name: &#39;느와르&#39;,
  },
  {
    code: &#39;7&#39;,
    name: &#39;애니메이션&#39;,
  },
]
</code></pre>
<h3 id="2-moviejsx">2. Movie.jsx</h3>
<pre><code class="language-javascript">import { useEffect, useState } from &#39;react&#39;
import styled from &#39;styled-components&#39;
import { getMovieList } from &#39;../../apis&#39;
import MovieList from &#39;../organisms/MovieList&#39;
📍import { countryList, genreList } from &#39;../../datas&#39;

const Movie = () =&gt; {
  const [text, setText] = useState(&#39;&#39;)
  📍const [country, setCountry] = useState(&#39;ALL&#39;)
  📍const [genre, setGenre] = useState(&#39;ALL&#39;)
  const [movieList, setMovieList] = useState([])

  📍useEffect(() =&gt; {
    searchMovieList()
  }, [country, genre])

  const handleSubmit = async (e) =&gt; {
    e.preventDefault()

    searchMovieList()
  }
  📍const searchMovieList = async () =&gt; {
    if (text === &#39;&#39;) return
    // const params = { query: text, country }
    // if(country === &quot;ALL&quot;) delete params.country;
    const params = { query: text }
    if (country !== &#39;ALL&#39;) params.country = country
    if (genre !== &#39;ALL&#39;) params.genre = genre
    const { items } = await getMovieList(params)
    setMovieList(items)
  }

  return (
    &lt;Wrapper&gt;
      &lt;PageTitle&gt;🎬 Movie 🎬&lt;/PageTitle&gt;
      &lt;Form onSubmit={handleSubmit}&gt;
       📍 &lt;select onChange={(e) =&gt; setCountry(e.target.value)} value={country}&gt;
          &lt;option value=&quot;ALL&quot;&gt;전체&lt;/option&gt;
          {countryList.map(({ code, name }) =&gt; (
            &lt;option value={code} key={code}&gt;
              {name}
            &lt;/option&gt;
          ))}
        &lt;/select&gt;
       📍 &lt;select onChange={(e) =&gt; setGenre(e.target.value)} value={genre}&gt;
          &lt;option value=&quot;ALL&quot;&gt;전체&lt;/option&gt;
          {genreList.map(({ code, name }) =&gt; (
            &lt;option value={code} key={code}&gt;
              {name}
            &lt;/option&gt;
          ))}
        &lt;/select&gt;
        &lt;InputText
          placeholder=&quot;search&quot;
          onChange={(e) =&gt; setText(e.target.value)}
        /&gt;
        &lt;BtnSubmit&gt;검색&lt;/BtnSubmit&gt;
      &lt;/Form&gt;
      &lt;MovieList data={movieList} /&gt;
    &lt;/Wrapper&gt;
  )
}

export default Movie</code></pre>
<p><img src="https://velog.velcdn.com/images/eun_zii/post/9ca5637c-5275-45e8-99b1-665ce58e16e5/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Modal]]></title>
            <link>https://velog.io/@eun_zii/Modal</link>
            <guid>https://velog.io/@eun_zii/Modal</guid>
            <pubDate>Thu, 28 Jul 2022 08:04:39 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>⛳️ React Bootstrap - component </p>
</blockquote>
<ul>
<li>Accoordion</li>
<li>Dropdowns</li>
<li>Carousel</li>
<li>Modal</li>
</ul>
<h2 id="modal-🔫">Modal 🔫</h2>
<h3 id="🎣-1-modal-background-css-기본적인">🎣 1. Modal Background CSS (기본적인)</h3>
<pre><code class="language-javascript">import styled from &#39;styled-components&#39;

const Modal = () =&gt; {
  return (
    &lt;&gt;
      &lt;Backdrop /&gt;
      &lt;Container&gt;Modal&lt;/Container&gt;
    &lt;/&gt;
  )
}

const Backdrop = styled.div`
  width: 100vw;
  height: 100vh;
  position: fixed;
  top: 0;
  left: 0;
  background: rgba(0, 0, 0, 0.7);
`
const Container = styled.div`
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: #fff;
  min-width: 300px;
  border-radius: 4px;
`

export default Modal</code></pre>
<h3 id="🎣-2-bootstrap-컴포넌트-생성">🎣 2. Bootstrap 컴포넌트 생성</h3>
<pre><code class="language-javascript">import { useState } from &#39;react&#39;
import Modal from &#39;./Modal&#39;

const Bootstrap = () =&gt; {
  const [showModal, setShowModal] = useState(false)
  const onClose = () =&gt; {
    setShowModal(false)
  }
  return (
    &lt;div&gt;
      &lt;button onClick={() =&gt; setShowModal(true)}&gt;모달&lt;/button&gt;
      {showModal &amp;&amp; &lt;Modal onClose={onClose} /&gt;}
    &lt;/div&gt;
  )
}
export default Bootstrap</code></pre>
<h3 id="🎣-3-modal-컴포넌트-생성">🎣 3. Modal 컴포넌트 생성</h3>
<pre><code class="language-javascript">import styled from &#39;styled-components&#39;

const Modal = ({ onClose }) =&gt; {
  return (
    &lt;&gt;
      &lt;Backdrop onClick={onClose} /&gt;
      &lt;Container&gt;
        &lt;Header&gt;Modal heading&lt;/Header&gt;
        &lt;Body&gt;Woohoo, you&#39;re reading this text in a modal!&lt;/Body&gt;
        &lt;Footer&gt;
          &lt;BtnClose onClick={onClose}&gt;Close&lt;/BtnClose&gt;
          &lt;BtnSave&gt;Save Changes&lt;/BtnSave&gt;
        &lt;/Footer&gt;
      &lt;/Container&gt;
    &lt;/&gt;
  )
}

const Backdrop = styled.div`
  width: 100vw;
  height: 100vh;
  position: fixed;
  top: 0;
  left: 0;
  background: rgba(0, 0, 0, 0.7);
`
const Container = styled.div`
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: #fff;
  min-width: 300px;
  border-radius: 4px;
`

const Header = styled.div`
  font-size: 24px;
  padding: 15px;
  border-bottom: 1px solid #ddd;
`
const Body = styled.div`
  padding: 15px;
`
const Footer = styled.div`
  padding: 5px;
  border-top: 1px solid #ddd;
  display: flex;
  justify-content: flex-end;
`
const Btn = styled.button`
  padding: 10px;
  border-radius: 4px;
  border: none;
  cursor: pointer;
  color: #fff;
  margin: 5px;
  font-size: 16px;
`

const BtnClose = styled(Btn)`
  background: gray;
`
const BtnSave = styled(Btn)`
  background: blue;
`
export default Modal</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Carousel]]></title>
            <link>https://velog.io/@eun_zii/Carousel</link>
            <guid>https://velog.io/@eun_zii/Carousel</guid>
            <pubDate>Tue, 26 Jul 2022 09:18:29 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>⛳️ React Bootstrap - component </p>
</blockquote>
<ul>
<li>Accoordion</li>
<li>Dropdowns</li>
<li>Carousel</li>
<li>Modal</li>
</ul>
<h2 id="carousel-🔫">Carousel 🔫</h2>
<h3 id="🎣-1-crossfade">🎣 1. Crossfade</h3>
<pre><code class="language-javascript">import { useState } from &#39;react&#39;
import styled from &#39;styled-components&#39;

const Carousel = ({ data }) =&gt; {
  const [activeIndex, setActiveIndex] = useState(0)
  const handleChange = (i) =&gt; {
    if (i === -1 &amp;&amp; activeIndex === 0) {
      setActiveIndex(data.length - 1)
    } else if (i === 1 &amp;&amp; activeIndex === data.length - 1) {
      setActiveIndex(0)
    } else {
      setActiveIndex((prev) =&gt; prev + i)
    }
  }

  return (
    &lt;Wrapper&gt;
      &lt;List&gt;
        {data.map((image, index) =&gt; (
          &lt;Item src={image} active={activeIndex === index} key={index} /&gt;
        ))}
      &lt;/List&gt;
      &lt;BtnPrev onClick={() =&gt; handleChange(-1)}&gt;이전&lt;/BtnPrev&gt;
      &lt;BtnNext onClick={() =&gt; handleChange(1)}&gt;다음&lt;/BtnNext&gt;
    &lt;/Wrapper&gt;
  )
}

const Wrapper = styled.div`
  position: relative;
  width: 800px;
  height: 600px;
`
const List = styled.div``
const Item = styled.img`
📌  position: absolute;
  top: 0;
  left: 0;
  width: 800px;
  height: 600px;
  opacity: ${({ active }) =&gt; !active &amp;&amp; &#39;0&#39;};
  transition: opacity 1s; 📌
`
const Btn = styled.button`
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
`
const BtnPrev = styled(Btn)`
  left: 50px;
`
const BtnNext = styled(Btn)`
  right: 50px;
`

export default Carousel</code></pre>
<h3 id="🎣-1-1-data-컴포넌트">🎣 1-1. Data 컴포넌트</h3>
<pre><code class="language-javascript">export const CarouselData = [
  &#39;https://i.pinimg.com/564x/55/52/27/555227cd235ab58f4c14b0743f6423c5.jpg&#39;,
  &#39;https://i.pinimg.com/564x/ac/97/26/ac9726f62afd84ab6e319685bc103f07.jpg&#39;,
  &#39;https://i.pinimg.com/564x/57/e0/30/57e030b4ceb9355554fa42e679c1555b.jpg&#39;,
  &#39;https://i.pinimg.com/564x/78/84/74/788474bacd29ab0da76ac26969760b84.jpg&#39;,
]</code></pre>
<h3 id="🎣-2-controlled">🎣 2. Controlled</h3>
<pre><code class="language-javascript">import { useState } from &#39;react&#39;
import styled from &#39;styled-components&#39;

const Carousel = ({ data }) =&gt; {
  const [activeIndex, setActiveIndex] = useState(0)
  const handleChange = (i) =&gt; {
    if (i === -1 &amp;&amp; activeIndex === 0) {
      setActiveIndex(data.length - 1)
    } else if (i === 1 &amp;&amp; activeIndex === data.length - 1) {
      setActiveIndex(0)
    } else {
      setActiveIndex((prev) =&gt; prev + i)
    }
  }

  return (
    &lt;Wrapper&gt;
      &lt;List activeIndex={activeIndex}&gt;
        {data.map((image, index) =&gt; (
          &lt;Item src={image} active={activeIndex === index} key={index} /&gt;
        ))}
      &lt;/List&gt;
      &lt;BtnPrev onClick={() =&gt; handleChange(-1)}&gt;이전&lt;/BtnPrev&gt;
      &lt;BtnNext onClick={() =&gt; handleChange(1)}&gt;다음&lt;/BtnNext&gt;

      &lt;ButtonList&gt;
        {data.map((image, index) =&gt; (
          &lt;BtnIndex
            onClick={() =&gt; setActiveIndex(index)}
            active={activeIndex === index}
            key={index}
          &gt;
            {index + 1}
          &lt;/BtnIndex&gt;
        ))}
      &lt;/ButtonList&gt;
    &lt;/Wrapper&gt;
  )
}

const Wrapper = styled.div`
  position: relative;
  width: 800px;
  height: 600px;
 📌 overflow: hidden;
`
const List = styled.div`
  display: flex;
  transform: ${({ activeIndex }) =&gt; `translateX(${-800 * activeIndex}px)`};
  transition: transform 1s;
  width: 100%; 📌
`
const Item = styled.img`
  min-width: 800px;
  height: 600px;
`
const Btn = styled.button`
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
`
const BtnPrev = styled(Btn)`
  left: 50px;
`
const BtnNext = styled(Btn)`
  right: 50px;
`
const ButtonList = styled.div`
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
`
const BtnIndex = styled.button`
  background: ${({ active }) =&gt; active &amp;&amp; &#39;pink&#39;};
`

export default Carousel
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[DropDown]]></title>
            <link>https://velog.io/@eun_zii/DropDown</link>
            <guid>https://velog.io/@eun_zii/DropDown</guid>
            <pubDate>Tue, 26 Jul 2022 03:44:33 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>⛳️ React Bootstrap - component </p>
</blockquote>
<ul>
<li>Accoordion</li>
<li>Dropdowns</li>
<li>Carousel</li>
<li>Modal</li>
</ul>
<h2 id="dropdown-🔫">Dropdown 🔫</h2>
<h3 id="🎣-1-bootstrapjsx-컴포넌트-생성">🎣 1. Bootstrap.jsx 컴포넌트 생성</h3>
<pre><code class="language-javascript">import Dropdown from &#39;./Dropdown&#39;

const Bootstrap = () =&gt; {
  return (
    &lt;div&gt;
      &lt;Dropdown /&gt;
    &lt;/div&gt;
  )
}
export default Bootstrap</code></pre>
<h3 id="🎣-2dropdownjsx-컴포넌트-생성">🎣 2.Dropdown.jsx 컴포넌트 생성</h3>
<pre><code class="language-javascript">import { useEffect, useState, useRef } from &#39;react&#39;
import styled from &#39;styled-components&#39;

const Dropdown = () =&gt; {
  const [showList, setShowList] = useState(false)
  const btnEl = useRef(null)

  useEffect(() =&gt; {
    const onClick = (e) =&gt; {
      if (btnEl.current !== e.target) setShowList(false)
    }
    document.body.addEventListener(&#39;click&#39;, onClick)
    return () =&gt; {
      document.body.removeEventListener(&#39;click&#39;, onClick)
    }
  }, [])

  return (
    &lt;Wrapper&gt;
      &lt;Button ref={btnEl} onClick={() =&gt; setShowList(!showList)}&gt;
        Dropdown
      &lt;/Button&gt;
      {showList &amp;&amp; (
        &lt;List&gt;
          &lt;Item&gt;Item #1&lt;/Item&gt;
          &lt;Item&gt;Item #2&lt;/Item&gt;
          &lt;Item&gt;Item #3&lt;/Item&gt;
          &lt;Item&gt;Item #4&lt;/Item&gt;
        &lt;/List&gt;
      )}
    &lt;/Wrapper&gt;
  )
}

const Wrapper = styled.div`
  position: relative;
`
const Button = styled.button``
const List = styled.ul`
  list-style: none;
  margin: 0;
  padding: 0;
  background: #fff;
  border: 1px solid #ddd;
  border-radius: 4px;
  min-width: 200px;
  position: absolute;
`
const Item = styled.li`
  padding: 5px 15px;
  &amp; + &amp; {
    border-top: 1px solid #ddd;
  }
  :hover {
    background: #efefef;
  }
`

export default Dropdown</code></pre>
<p>⭐️ Drop down 을 열고 drop down 을 제외한 부분을 클릭했을때 (body라던가..) drop down이 닫히고, </p>
<p>닫힌다는 것은 drop down 내에 show List가 false가 되는것이고, </p>
<p>false가 되려면 전체 body에 Event Listener을 붙여서 body가 클릭될때마다 false를 만드는것. </p>
<p>하지만 Btn도 body라서 절대 true가 될수없다. 
그래서 btn과 클릭한 target을 비교해서 
btn을 누른상황이면 show List를 false로 만들지 않는것.</p>
<p>body에 remove Event Listener를 붙이지 않으면 console.log가 여러번 찍히게 되니 remove를 붙이는게 좋다. ⭐️</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[useEffect가 2번실행될때]]></title>
            <link>https://velog.io/@eun_zii/useEffect-2%EB%B2%88%EC%8B%A4%ED%96%89%EB%90%A0%EB%95%8C</link>
            <guid>https://velog.io/@eun_zii/useEffect-2%EB%B2%88%EC%8B%A4%ED%96%89%EB%90%A0%EB%95%8C</guid>
            <pubDate>Tue, 26 Jul 2022 03:21:52 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-javascript">useEffect(() =&gt; {},[])</code></pre>
<p>useEffect 2번째 인자에 빈 배열을 넣어주게 되면 컴포넌트가 처음 렌더링 될때만 실행된다.</p>
<p>하지만 !!!</p>
<h2 id="📌-useeffect-오류로-2번-실행-될때-📌">📌 useEffect 오류로 2번 실행 될때 📌</h2>
<p>src/index.js에서
&lt;React.StrictMode&gt; 태그로 <app/>이 감싸져있으면
개발모드에서 두 번씩 렌더링된다.</p>
<pre><code class="language-javascript">import React from &#39;react&#39;
import ReactDOM from &#39;react-dom/client&#39;
import App from &#39;./App&#39;
import reportWebVitals from &#39;./reportWebVitals&#39;
import &#39;./index.css&#39;

const root = ReactDOM.createRoot(document.getElementById(&#39;root&#39;))
root.render(
  &lt;React.StrictMode&gt; ⬅ 지우기
    &lt;App /&gt;
  &lt;/React.StrictMode&gt;, ⬅ 지우기
)</code></pre>
<p>참고: <a href="https://velog.io/@hyes-y-tag/React-useEffect%EA%B0%80-%EB%91%90%EB%B2%88-%EC%8B%A4%ED%96%89%EB%90%9C%EB%8B%A4%EA%B3%A0">https://velog.io/@hyes-y-tag/React-useEffect%EA%B0%80-%EB%91%90%EB%B2%88-%EC%8B%A4%ED%96%89%EB%90%9C%EB%8B%A4%EA%B3%A0</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Accordion]]></title>
            <link>https://velog.io/@eun_zii/Accordion</link>
            <guid>https://velog.io/@eun_zii/Accordion</guid>
            <pubDate>Tue, 26 Jul 2022 02:12:22 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>⛳️ React Bootstrap - component </p>
</blockquote>
<ul>
<li>Accoordion</li>
<li>Dropdowns</li>
<li>Carousel</li>
<li>Modal</li>
</ul>
<h3 id="✏️-flex">✏️ Flex</h3>
<p>부모 요소인 div.container를 Flex Container(플렉스 컨테이너)라고 부르고,
자식 요소인 div.item들을 Flex Item(플렉스 아이템)이라고 부릅니다.</p>
<p>“컨테이너가 Flex의 영향을 받는 전체 공간이고, 설정된 속성에 따라 각각의 아이템들이 어떤 형태로 배치되는 것”이라고 생각하시면 됩니다.</p>
<pre><code class="language-javascript">const Container = styled.div`
  display: flex;
`</code></pre>
<p>: <a href="https://studiomeal.com/archives/197">https://studiomeal.com/archives/197</a></p>
<h2 id="accordion-🔫">Accordion 🔫</h2>
<h3 id="🎣-1-bootstrapjsx-컴포넌트-생성">🎣 1. Bootstrap.jsx 컴포넌트 생성</h3>
<pre><code class="language-javascript">import Accordion from &#39;./Accordion&#39;
import { accordionData } from &#39;../../datas/bootstrap&#39;

const Bootstrap = () =&gt; {
  return (
    &lt;div&gt;
      &lt;Accordion data={accordionData} /&gt;
    &lt;/div&gt;
  )
}
// 아코디언컴포넌트를 데이터만 갈아끼우면 안에 내용을 교체하면서 재활용가능
export default Bootstrap</code></pre>
<h3 id="🎣-2accordionjsx-컴포넌트-생성">🎣 2.Accordion.jsx 컴포넌트 생성</h3>
<pre><code class="language-javascript">import { useState } from &#39;react&#39;
import styled from &#39;styled-components&#39;
import { ReactComponent as Arrow } from &#39;./arrow.svg&#39;

const Accordion = ({ data }) =&gt; {
  const [activeIndex, setActiveIndex] = useState(0)
  const handleClick = (index) =&gt; {
    /* if (index === activeIndex) {
      setActiveIndex(-1)
    } else {
      setActiveIndex(index)
    } */
    const nextIndex = index === activeIndex ? -1 : index
    setActiveIndex(nextIndex)
  }
  return (
    &lt;List&gt;
      {data.map(({ title, content }, index) =&gt; (
        &lt;Item active={activeIndex === index} key={index}&gt;
          &lt;Header onClick={() =&gt; handleClick(index)}&gt;
            {title}
            &lt;BtnArrow&gt;
              &lt;Arrow /&gt;
            &lt;/BtnArrow&gt;
          &lt;/Header&gt;
          &lt;Body&gt;{content}&lt;/Body&gt;
        &lt;/Item&gt;
      ))}
    &lt;/List&gt;
  )
}

const List = styled.ul`
  list-style: none;
  padding: 0;
  margin: 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
`
const Body = styled.div`
  padding: 15px;
  border-top: 1px solid #ddd;
  display: none;
`
const BtnArrow = styled.button`
  transition: transform 0.5s;
  cursor: pointer;
  background-color: transparent;
  width: 20px;
  height: 20px;
  border: none;
  margin-left: 10px;
  svg {
    transform: rotate(90deg);
  }
`
const Item = styled.li`
  &amp; + &amp; {
    border-top: 1px solid #ddd;
  }

  ${Body} {
    display: ${({ active }) =&gt; active &amp;&amp; &#39;block&#39;};
  }
  ${BtnArrow} {
    transform: ${({ active }) =&gt; active &amp;&amp; &#39;rotate(-180deg)&#39;};
  }
`
const Header = styled.div`
  padding: 10px;
  display: flex;
  justify-content: space-between;
  cursor: pointer;
`

export default Accordion</code></pre>
<h3 id="🎣-3datajsx-컴포넌트-생성">🎣 3.Data.jsx 컴포넌트 생성</h3>
<pre><code class="language-javascript">export const accordionData = [
  {
    title: &#39;Accordion Item #1&#39;,
    content: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
    eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad`,
  },
  {
    title: &#39;Accordion Item #2&#39;,
    content: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
    eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad`,
  },
  {
    title: &#39;Accordion Item #3&#39;,
    content: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
    eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad`,
  },
]</code></pre>
]]></description>
        </item>
    </channel>
</rss>