<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>solda-blue.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Thu, 18 May 2023 07:35:22 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>solda-blue.log</title>
            <url>https://velog.velcdn.com/images/solda-blue/profile/36b241fd-6073-4e54-a951-9216e4155072/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. solda-blue.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/solda-blue" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[구글 프로필 이미지주소 깨짐 현상]]></title>
            <link>https://velog.io/@solda-blue/%EA%B5%AC%EA%B8%80-%ED%94%84%EB%A1%9C%ED%95%84-%EC%9D%B4%EB%AF%B8%EC%A7%80%EC%A3%BC%EC%86%8C-%EA%B9%A8%EC%A7%90-%ED%98%84%EC%83%81</link>
            <guid>https://velog.io/@solda-blue/%EA%B5%AC%EA%B8%80-%ED%94%84%EB%A1%9C%ED%95%84-%EC%9D%B4%EB%AF%B8%EC%A7%80%EC%A3%BC%EC%86%8C-%EA%B9%A8%EC%A7%90-%ED%98%84%EC%83%81</guid>
            <pubDate>Thu, 18 May 2023 07:35:22 GMT</pubDate>
            <description><![CDATA[<p>현재 프로젝트에서 구글로그인API를 활용해서 프로필 이미지 주소를 가져와서 img 태그로 보여줄 때
잘 되다가 가끔씩 특정 계정의 이미지만 깨질 때가 있다</p>
<p><a href="https://stackoverflow.com/questions/40570117/http403-forbidden-error-when-trying-to-load-img-src-with-google-profile-pic">링크텍스트</a></p>
<p>img 태그에 referrerPolicy=&quot;no-referrer&quot; 이거 한줄 넣으니까 다시 잘 보인다 ㄷㄷ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React에서 Web Audio API 사용하여 mp3 파일 재생하기]]></title>
            <link>https://velog.io/@solda-blue/React%EC%97%90%EC%84%9C-Web-Audio-API-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-mp3-%ED%8C%8C%EC%9D%BC-%EC%9E%AC%EC%83%9D%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@solda-blue/React%EC%97%90%EC%84%9C-Web-Audio-API-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-mp3-%ED%8C%8C%EC%9D%BC-%EC%9E%AC%EC%83%9D%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 17 Apr 2023 01:34:30 GMT</pubDate>
            <description><![CDATA[<h3 id="intro">Intro</h3>
<p>음정이나 코드를 들려주고 맞추는 간단한 청음프로그램을 만들려고 했는데 처음엔 그냥 아무것도 모르고 HTML의 audio 태그를 이용해서 로컬에 있는 mp3파일을 note들로 사용했었는데 데스크탑 브라우저 환경에서는 별 무리없이 동작하였으나 모바일로 테스트 해본 결과 코드는 싱크가 밀린다던가 음정 같은 경우는 아예 첫음이 들리지 않는 등 문제가 많아서 구글링을 해본 결과 Web Audio API라고 audio파일을 전문적으로 다루는 자바스크립트 기술이 있었다.</p>
<p>그래서 기존의 음원 재생 방법을 Firebase Storage에 음원을 올려두고 거기서 http로 가져와서 Web Audio API를 통해서 재생하는 걸로 바꾸는 작업을 하였다.</p>
<h4 id="firebase-storage에-음원-업로드하고-url-가져오기">Firebase Storage에 음원 업로드하고 url 가져오기</h4>
<p>Firebase는 이번에 처음 써봤는데 직관적이고 깔끔하게 잘 되어 있는 것 같다. 프로젝트를 시작하고 스토리지에 파일 등록하는 건 간단하니 넘어가고 http 요청을 위해서 cors 설정을 해주어야 한다</p>
<p><a href="https://console.cloud.google.com/">https://console.cloud.google.com/</a></p>
<p>FB 콘솔이 아니라 구글 클라우드 플랫폼 콘솔로 가야 한다.</p>
<p>cors 설정은 이분의 포스트를 참고 했다</p>
<blockquote>
<p><a href="https://stove99.github.io/etc/2021/06/09/firebase-storage-cors-setting/">https://stove99.github.io/etc/2021/06/09/firebase-storage-cors-setting/</a></p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/eda5077f-5b42-4a59-bd27-3ce31daa0176/image.png" alt=""></p>
<p>그 뒤 파일들을 업로드 해주고 url 주소를 가져와야 하는데 오른쪽 아래에 엑세스 토큰 부분을 클릭하면 get 요청을 날렸을 때 재생이 가능한 전체 url 주소를 복사할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/b1d2dc54-ead9-4cd7-9852-e68ea12b4c65/image.png" alt=""></p>
<p>그렇게 복사한 주소와 note에 관한 정보를 json형식으로 저장했다.</p>
<h4 id="web-audio-api를-활용해서-가져온-음원-재생하기">Web Audio API를 활용해서 가져온 음원 재생하기</h4>
<p>어제 밤에 너무 늦게 자서 피곤한 관계로 일단 그냥 전체 코드를 통으로 올리고 나중에 시간되면 수정하기로...</p>
<p>코드가 길어서 그렇지 생각보다 별거 없다 AudioContext 인스턴스 만들고 버퍼에 음원들 가져와서 디코딩하고 다시 플레이 버튼 눌렀을 때 담아둔 음원들을 버퍼소스 노드에 집어넣고 AudioContext에 connect해서 순차적으로 재생해주면 됨</p>
<pre><code>import axios from &quot;axios&quot;;
import React, { useEffect, useState } from &quot;react&quot;;

const Answer1 = (props) =&gt; {
    const exChord = props.exChord;
    const [audios, setAudios] = useState([]);

    useEffect(() =&gt; {
        const fetchAudio = async () =&gt; {
            const audioContext = new (window.AudioContext || window.webkitAudioContext)();
            const buffers = [];
            for(let i = 0; i &lt; exChord.length; i++) {
                const res = await axios({
                    method : &quot;get&quot;,
                    url : exChord[i].url,
                    responseType : &quot;arraybuffer&quot;
                });
                const buffer = await audioContext.decodeAudioData(res.data);
                buffers.push(buffer);
            };
            setAudios(buffers);
        };
        fetchAudio();
    },[exChord]);

    useEffect(() =&gt; {
        const play = () =&gt; {
            console.log(audios);
            const audioContext = new (window.AudioContext || window.webkitAudioContext)();
            audios.forEach((audio) =&gt; {
                const source = audioContext.createBufferSource();
                source.buffer = audio;
                source.connect(audioContext.destination);
                source.start(0);
            })
        }
        if (audios.length &gt; 0) {
            play();
        }
    }, [audios])

    return (
        &lt;div&gt;
            &lt;h6&gt;answer&lt;/h6&gt;

            &lt;button onClick={() =&gt; setAudios([...audios])}&gt;재생&lt;/button&gt;
        &lt;/div&gt;
    )
}

export default Answer1;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[0403 - React Ref:DOM]]></title>
            <link>https://velog.io/@solda-blue/0403-React-RefDOM</link>
            <guid>https://velog.io/@solda-blue/0403-React-RefDOM</guid>
            <pubDate>Mon, 03 Apr 2023 02:41:12 GMT</pubDate>
            <description><![CDATA[<p>ref를 활용하여 input 태그에 콜백함수로 가져온 엘리먼트를 담은 변수를 사용하여 DOM에 접근하기</p>
<h4 id="1-constructor-안에-element를-할당할-변수를-선언">1. constructor 안에 element를 할당할 변수를 선언</h4>
<pre><code>constructor (props) {
    super(props);
    this.textInput = null;
}</code></pre><h4 id="2-ref를-통해-element를-들고올-콜백함수를-만든다">2. ref를 통해 element를 들고올 콜백함수를 만든다</h4>
<pre><code>constructor (props) {
    super(props);
    // 1. input 태그가 들어갈 공간(변수)
    this.textInput = null;
    // 2. ref 콜백함수를 통해 DOM에 접근
    // 1) ref에 들어갈 함수 작성
    this.setTextInputRef = (element) =&gt; {
        // 2) element를 ref를 통해 DOM 가져옴
        // 3) 저장해서 쓰기위해 만든 공간에 할당
        this.textInput = element;
        }
    }</code></pre><h4 id="3-가져올-태그의-속성에-ref를-추가하고-2에서-만든-콜백함수를-입력한다">3. 가져올 태그의 속성에 ref를 추가하고 2에서 만든 콜백함수를 입력한다</h4>
<pre><code>&lt;input
    type=&quot;text&quot;
    // 3. ref 속성을 이용해서 setTextInputRef를 호출
    ref={this.setTextInputRef}
/&gt;</code></pre><p><img src="https://velog.velcdn.com/images/solda-blue/post/b1b9cfc0-ab66-4870-926b-87f24bc514f3/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/d0d66c4f-0036-424c-a4a1-80adbc8f8793/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/e6db8949-bedf-47a7-a293-d60bfa3d77bc/image.png" alt=""></p>
<h4 id="4-가져온-element를-조작하기---input-태그에-focus주기">4. 가져온 element를 조작하기 -&gt; input 태그에 focus주기</h4>
<pre><code>textInputEvent = () =&gt; {
    if(this.textInput) {
           // ref를 통해서 DOM을 가져와서 그 안에 있는 내용에
        // JS에서 id를 통해 가져온것 처럼 접근할 수 있다
        this.textInput.focus();
    }
}</code></pre><h4 id="textinput을-배열로-만들고-push-나-concat-으로-할당하면-하나의-변수에-여러-element를-담을-수-있다">!textInput을 배열로 만들고 push() 나 concat() 으로 할당하면 하나의 변수에 여러 element를 담을 수 있다</h4>
<p>위의 방법은 콜백함수를 이용하여 DOM을 조작하는 것이고 </p>
<h4 id="react-163-버전-이상부터는-createref라는-내장-함수를-이용하여-변수에-할당-할-수-있다">React 16.3 버전 이상부터는 createRef()라는 내장 함수를 이용하여 변수에 할당 할 수 있다</h4>
<pre><code>constructor (props) {
    super(props);
    // 16.3 버전 이후 사용가능
    this.textInput = React.createRef();
}</code></pre><h4 id="-createref를-사용할-땐-해당-변수의-뒤에-current를-입력해야-사용할-수-있다-ex">! createRef를 사용할 땐 해당 변수의 뒤에 .current를 입력해야 사용할 수 있다 ex=&gt;</h4>
<pre><code>console.log(this.myRef.current);</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[게시판 글목록&PageNation (fetch, 이벤트버블링)- Vanilla JavaScript]]></title>
            <link>https://velog.io/@solda-blue/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EA%B8%80%EB%AA%A9%EB%A1%9DPageNation-fetch-%EC%9D%B4%EB%B2%A4%ED%8A%B8%EB%B2%84%EB%B8%94%EB%A7%81-Vanilla-JavaScript</link>
            <guid>https://velog.io/@solda-blue/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EA%B8%80%EB%AA%A9%EB%A1%9DPageNation-fetch-%EC%9D%B4%EB%B2%A4%ED%8A%B8%EB%B2%84%EB%B8%94%EB%A7%81-Vanilla-JavaScript</guid>
            <pubDate>Tue, 28 Feb 2023 04:14:35 GMT</pubDate>
            <description><![CDATA[<h3 id="intro">intro</h3>
<p>웹 개발 기본기 다지는데는 게시판 만한게 없는거 같다.
이전에는 학원에서 Vue.js로 게시판을 만들었었는데 그러다 보니까 순수 자바스크립트 실력은 많이 늘지도 않는것 같고 제대로 이해도 하지 못한채로 코드만 치는 것 같아서 이번에는 바닐라 자바스크립트로 게시판 목록과 페이지네이션을 구현해보았다.</p>
<h3 id="밴앤드-구성">밴앤드 구성</h3>
<p>어차피 프론트엔드 과정인지라 DB와 서버는 최대한 간단하게 MongoDB와 Express로 간단하게 구성했다.
백엔드 개발에 관해선 다음에 자세하게 다루기로하고 여기선 프론트에서 필요한 만큼만 코드를 살펴보자.</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/7b53189b-ab75-4581-a266-1eda8806754d/image.png" alt=""></p>
<p>최소한의 검색기능과 5개씩 페이지네이션을 만들어 보았다.</p>
<h3 id="get-요청-하기">Get 요청 하기</h3>
<p>일전에 XMLHttpRequest로 get요청을 보내봤었는데 이번에는 fetch함수를 사용해봤다.</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/316755c0-0124-4cbe-bb32-c0e67297f995/image.png" alt=""><img src="https://velog.velcdn.com/images/solda-blue/post/c39a4780-f6b2-44d5-b163-6611d895765a/image.png" alt=""></p>
<p>기본 fetch함수 예제와는 모양이 다른데 저런식으로 return 한 항목을 다시 비동기로 변수에 담아주면 응답 받은 내용을 전역변수에 넣어서 사용할 수 있다고 한다. </p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/93ef3829-6967-441a-90c9-0444cde7d9ed/image.png" alt=""></p>
<p>handleData 함수를 실행하고 list를 찍어보면 제대로 작동하는걸 볼 수 있다.</p>
<p>-Promise에 관해서는 몇개 찾아봤지만 아직 제대로 이해가 되지 않아서 좀 더 공부한 후에 따로 포스트하던지 해야겠다.</p>
<h3 id="데이터-테이블에-바인딩하기">데이터 테이블에 바인딩하기</h3>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/33c63d21-49f2-4292-aae3-14534ae66a1c/image.png" alt=""></p>
<p>위의 getList()로 가져온 데이터를 화면상에 뿌려주는데 정석(?)으로는 각각 element를 생성하고 안에 데이터를 집어넣는게 맞는것 같지만 그렇게하면 너무 코드가 길어질 것 같으니 tbody안에 반복문을 통하여 통째로 바인딩했다.</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/6a295085-74cb-443d-be04-89cd1eb2586d/image.png" alt=""></p>
<p>문제 없이 잘 나온다.</p>
<pre><code>        &lt;table&gt;
            &lt;thead&gt;
                &lt;tr&gt;
                    &lt;td&gt;번호&lt;/td&gt;
                    &lt;td&gt;제목&lt;/td&gt;
                    &lt;td&gt;작성자&lt;/td&gt;
                    &lt;td&gt;조회수&lt;/td&gt;
                    &lt;td&gt;등록일&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody id=&quot;tbody&quot;&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;</code></pre><p>참고용 table  전체 html</p>
<h3 id="페이지네이션-만들기">페이지네이션 만들기</h3>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/4302b3ae-f5ed-47ee-be04-ad12f0bf6f15/image.png" alt=""></p>
<p>페이지네이션은 이번에 공부하면서 새로 배운 DOM과 Nodes 조작을 통해서 전체 게시글의 숫자를 이용해서 필요한 만큼 element를 생성하고 필요한 attribute를 집어넣은 다음에 &quot;pagenation&quot; div안에 집어넣어보았다.</p>
<pre><code>&lt;div id=&quot;pagenation&quot;&gt;
    createElement로 생성된 버튼들이 들어오는 자리
&lt;/div&gt;
const pagenation = document.getElementById(&#39;pagenation&#39;);</code></pre><p><img src="https://velog.velcdn.com/images/solda-blue/post/1ea7fe98-b387-480d-8866-d47287920b35/image.png" alt="">여기서 data-id 를 이용하여 원하는 태그에 속성을 추가해주는걸 볼 수 있는데 </p>
<pre><code>data-데이터이름 = 값</code></pre><p>을 입력해 주면 해당태그안에 원하는 데이터를 집어넣을 수 있고</p>
<pre><code>해당태그 선택(ex.document.querySelector(&#39;...&#39;).dataset.데이터이름;</code></pre><p>dataset을 통하여 그 값을 불러올수 있게 된다.
간단한 기능이지만 여기저기 유용하게 써먹을 곳이 많은 것 같다.</p>
<h3 id="페이지네이션-버튼-click이벤트-구현">페이지네이션 버튼 click이벤트 구현</h3>
<p>위에서 생성된 버튼들에 click 이벤트를 추가하여 해당 페이지의 게시글 목록이 보여지도록 만들어보자</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/0f489d5e-9601-44bb-b3b1-57ee51c26e7c/image.png" alt=""></p>
<p>전체 코드인데 살펴보면 각각의 버튼들에 이벤트리스너를 생성하는 것이 아니라 상위의 pagenation div에 이벤트를 생성해 준것을 볼 수 있다. </p>
<p>이렇게 했을 때 몇가지 이점이 있는데
일단 이벤트가 많아질수록 성능저하가 일어나는데 저런식으로 상위 요소에서 하위요소를 제어하게 되면 이벤트리스너의 개수를 줄여서 성능도 향상되고</p>
<p>전체적인 코드도 줄어들게 되고 지금 내가 할 수 있는 선에선 최대한 함수들로 기능들을 나누어 놓았는데 버튼이 추가된다던지 이런저런 변화에 대해서 확장성도 좋아진다고 볼 수 있다.</p>
<p><strong>이런식으로 코드를 짤 때 한가지 주의할 점이 있는데</strong>
<img src="https://velog.velcdn.com/images/solda-blue/post/8e5db308-83bd-4491-bba3-518f04916a6e/image.png" alt=""></p>
<p>지금 버튼들을 감싸고 있는데 pagenation div를 살펴보면 저런식으로 버튼들 사이의 빈 공간들도 클릭했을 때 이벤트가 실행되게 된다.</p>
<p>이런 것을 <strong>이벤트 버블링(Event Bubbling)</strong>이라고 하는데 어떤 요소의 이벤트가 발생했을 때 상위요소의 이벤트도 같이 전파되는 것을 말한다.</p>
<p>이게 유용할 때도 많은데 반대로 예기치 못한 방법으로 코드가 실행 될 때도 있다.</p>
<p>이런 것을 방지하기 위해서 자바스크립트에 몇가지 기능이 있는데</p>
<pre><code>pagenation.addEventListener(&#39;click&#39;, function(e) {

}</code></pre><p>위의 이벤트 리스너 함수를 살펴보자.
콜백함수 부분에 e라는 파라미터가 들어가 있는것을 볼 수가 있는데 이것을 이벤트 객체(event object)라고 부른다. 
이벤트 객체에는 해당 이벤트에 대해 여러가지 정보를 담고 있는데 
<img src="https://velog.velcdn.com/images/solda-blue/post/e95755e3-d9ae-4ea0-988d-ebbb63e7b68c/image.png" alt=""></p>
<p>(console.log(e)로 이벤트리스너를 호출했을 때)</p>
<p>이때 <strong>target</strong> 이라는 항목이 있다.
target이란 해당이벤트가 발생한 html 요소 &quot;그 자체&quot; 를 의미한다.
그렇기에 위의 이미지를 보면 분명 이벤트리스너가 달린 곳은 pagenation div인데 target에는 내가 클릭한 button 이라는 요소가 출력되는 걸 볼 수 있다.</p>
<p>그래서 내가 상호작용한 요소 그 자체를 선택하고 싶으면 함수 내에서</p>
<pre><code>e.target</code></pre><p>으로 불러올 수 있다.
(앞의 e. 으로 붙이는건 함수에 파라미터로 e 를 넣었기 때문, event를 넣었다면 event.target)</p>
<p>그리고 해당 이벤트가 부착(?)된 요소를 지정하고 싶으면</p>
<pre><code>e.currentTarget</code></pre><p>을 사용하면 된다.</p>
<p>지금 만든 이벤트에서는 addEventListener가 달린 pagenation div 가 될 것이다.</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/beb32694-8d31-4380-aae0-d186aedd9ef6/image.png" alt=""></p>
<p>ex) 게시판 페이지네이션 2번 버튼을 눌렀을 때
e.target에는 내가 실제로 누른 버튼이 출력되고, e.currentTarget에는 이벤트가 만들어진 pagenation div가 나오는 걸 볼 수 있다.
(거기다 아까 전에 data- 방식으로 dataset에 집어넣은 값도 잘 보인다.)</p>
<p>그럼 위의 두가지를 포함하여 이벤트객체를 활용하여 쓸 수 있는 유용한 기능 몇가지를 살펴보면</p>
<p>e.target; // 유저가 실제로 누른거
e.currentTarget; // 이벤트리스너 달린 곳
e.preventDefault(); // 이벤트 기본동작 막아줌
e.stopPropagation(); // 내 상위요소로 이벤트 버블링 막아줌</p>
<p>지금 상황에서는 이정도만 알고 있어도 유용하게 쓸 수 있을 것이다.
-e.preventDefault()는 해당 요소가 기본적으로 제공하는 기능, (예를들면 a태그는 해당 href 주소로 이동한다던가 하는) 태그 원래의 기능들이 실행되는 것을 막아준다.</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/86193dd3-089b-487d-9739-4adbb6bc1506/image.png" alt=""></p>
<p>작성한 코드에서도 if 문을 통하여 e.target 과 e.currentTarget 이 다를 때만 코드가 실행되게 하여서 원치않는 작동을 막아주었다.</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/6b7b3d84-f5eb-4548-8a92-eb9894371b97/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/62b87587-b1d8-428a-a053-ccafd2de8a16/image.png" alt=""></p>
<p>이렇게 해서 허접하지만 바닐라 자바스크립트로 게시판 글목록과 페이지네이션 기능을 구현해 보았다.</p>
<h3 id="전체-코드">전체 코드</h3>
<pre><code>&lt;body&gt;
    &lt;a href=&quot;../index.html&quot;&gt;&lt;button&gt;뒤로&lt;/button&gt;&lt;/a&gt;
    &lt;a href=&quot;./boardInsert.html&quot;&gt;&lt;button&gt;글쓰기&lt;/button&gt;&lt;/a&gt;

    &lt;hr /&gt;

    &lt;div id=&quot;boardContent&quot;&gt;
        &lt;table&gt;
            &lt;thead&gt;
                &lt;tr&gt;
                    &lt;td&gt;번호&lt;/td&gt;
                    &lt;td&gt;제목&lt;/td&gt;
                    &lt;td&gt;작성자&lt;/td&gt;
                    &lt;td&gt;조회수&lt;/td&gt;
                    &lt;td&gt;등록일&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody id=&quot;tbody&quot;&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;

        &lt;hr /&gt;

        &lt;div id=&quot;pagenation&quot;&gt;&lt;/div&gt;
    &lt;/div&gt;

    &lt;script&gt;
        const tbody = document.getElementById(&#39;tbody&#39;);
        const pagenation = document.getElementById(&#39;pagenation&#39;);
        const boardContent = document.getElementById(&#39;boardContent&#39;);

        handleData();
        for(let i = 0; i &lt; tbody.childElementCount; i++) {
            tbody.children[i].setAttribute(&quot;class&quot;, &quot;board-one&quot;);
        }

        async function handleData(page) {
            // fetch로 요청한 response 를 전역변수에 저장 하는 법
            const list = await getData(page);
            boardList(list); // 게시글 목록
            pageList(list); // 페이지네이션
            console.log(&quot;최신 페이지 =&gt; &quot;, list);
        }

        // getData로부터 게시글 목록 생성
        function boardList(data) {
            for(let tmp of data.result) {
                tbody.innerHTML += 
                `&lt;tr&gt;` +
                    `&lt;td&gt;${tmp._id}&lt;/td&gt;` +
                    `&lt;td&gt;${tmp.title}&lt;/td&gt;` +
                    `&lt;td&gt;${tmp.writer}&lt;/td&gt;` +
                    `&lt;td&gt;${tmp.hit}&lt;/td&gt;` +
                    `&lt;td&gt;${tmp.regdate}&lt;/td&gt;` +
                `&lt;/td&gt;`;
            }
        }

        // getData로부터 페이지네이션 생성
        function pageList(data) {
            let page;
            // data.total에서 page개수 정하기
            if(data.total % 5 == 0) {
                // 5의 배수로 떨어지면 맨 뒤의 떨이페이지 필요x
                page = Math.floor((data.total / 5));
            } else {
                page = Math.floor((data.total / 5) +1);
            }
            // 페이지 버튼이 1부터 시작할 수 있도록 i와 page에 1을 더해준다
            for(let i = 1; i &lt; page + 1; i++) {
                // 페이지 개수만큼 버튼 생성
                let newButton = document.createElement(&#39;button&#39;);
                newButton.innerHTML = i;
                // 각 버튼 element에 dataset.id 넣기
                newButton.setAttribute(&quot;data-id&quot;, i);
                newButton.setAttribute(&quot;class&quot;, &quot;btn&quot;);
                // pagenation div에 생성한 버튼 추가
                pagenation.appendChild(newButton);
            }
        }

        // 이벤트 버블링 활용해서 버튼 상위 div에 클릭이벤트 하나만 만들기 =&gt; 성능에 좋다
        pagenation.addEventListener(&#39;click&#39;, async function(e) {
            // 실제 클릭한 요소(e.target)와 실제 이벤트가 만들어진 요소(e.currentTarget)가
            // 다를때만 동작하게 하여 이벤트 버블링을 막음
            if(e.target != e.currentTarget) {
                // e.target으로 클릭한 버튼 찾아내서 서버에서 정보가져오기
                let list = await getData(e.target.dataset.id);
                console.log(e.target);
                tbody.innerHTML = &quot;&quot;;
                boardList(list);
                console.log(&quot;페이지 번호 =&gt; &quot;, e.target.dataset.id, list);
            }
        })

        // fetch로 get요청
        function getData(page) {
            // 응답받은 데이터를 전역변수에 반환
            return new Promise((resolve, reject) =&gt; {
                fetch(`http://127.0.0.1:8088/board/select.json?page=${page}`)
                .then((response) =&gt; response.json())
                .then(data =&gt; {
                    resolve(data);
                });
            });
        }

    &lt;/script&gt;</code></pre><h3 id="outro">outro</h3>
<p>이 다음엔 검색기능과 특정 게시글을 열람할 수 있는 기능도 구현해 보자</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[MongoDB Atlas 와 Node.js - Express 연동]]></title>
            <link>https://velog.io/@solda-blue/MongoDB-Atlas-%EC%99%80-Node.js-Express-%EC%97%B0%EB%8F%99</link>
            <guid>https://velog.io/@solda-blue/MongoDB-Atlas-%EC%99%80-Node.js-Express-%EC%97%B0%EB%8F%99</guid>
            <pubDate>Wed, 22 Feb 2023 13:59:28 GMT</pubDate>
            <description><![CDATA[<p>풀스택 연습용 DB로 몽고db를 쓰려고 찾아보다가 mongodb atlas라고 클라우드 데이터베이스 서비스를 제공하고 있어서 그걸 써보려고 한다.</p>
<h3 id="mongodb-atlas-계정-생성">mongoDB Atlas 계정 생성</h3>
<p><a href="https://www.mongodb.com/ko-kr/cloud/atlas/register">https://www.mongodb.com/ko-kr/cloud/atlas/register</a>
<img src="https://velog.velcdn.com/images/solda-blue/post/c0ee5c9e-1ad4-4a83-a36e-25b6d4ffed13/image.png" alt="">위 사이트로 들어가서 계정을 생성한다. 구글 계정으로도 로그인 가능하다</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/40fc67f1-52d8-4070-a567-df68d2113235/image.png" alt="">아무거나 골라주면 된다.</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/27c66ed2-6137-49e0-8137-c18e7d5d347f/image.png" alt="">제일 오른쪽의 무료 cluster를 고르자 구글 클라우드 항목에 서울 서버가 있으니 선택해주자.</p>
<h3 id="db-유저네임비밀번호--ip주소-설정">DB 유저네임&amp;비밀번호 / IP주소 설정</h3>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/aa0d2755-adc7-4bae-9161-a96ab2012d4b/image.png" alt="">Autogenerate Secure Password를 누르면 자동으로 비밀번호를 생성해준다.
나중에 DB연결시에 필요하므로 다른 곳에 기록해 놓자.</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/13e15ac0-d3a5-4894-a757-21a5b9d45b13/image.png" alt="">add My Current IP Address 버튼을 누르고 엔트리를 추가하자.</p>
<p>여기까지 완료하면 계정생성과 기본 설정은 끝이다.</p>
<h3 id="express-서버와-mongodb-atlas-연결준비">Express 서버와 MongoDB Atlas 연결준비</h3>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/2f116ddc-9033-4f65-b724-b05955cd6e84/image.png" alt="">왼쪽의 Database Access 와 Network Access 탭에 들어가면 바로 위에서 설정한 유저정보와 IP를 언제든지 수정할 수 있다.</p>
<p>이제 Database탭에 Connect 버튼을 눌러보자.</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/9ffd448c-757d-4052-92ef-8cd671f83ced/image.png" alt="">터미널이나 Compass 앱 등 여러가지 방법으로 연결할 수 있는데 일단 해당 영역을 클릭하자</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/97fff718-109c-492e-858b-92413d425b7e/image.png" alt="">밑의 코드를 복사하는데 password 부분을 아까전에 기록 해놓은 비밀번호를 넣어주자.
<strong>&lt;, &gt; 부분도 지워줘야지 제대로 연결이 가능하다.</strong> (이것 때문에 여러번 뻘짓을 했다..)</p>
<h3 id="express-서버와-mongodb-atlas-연결하기">Express 서버와 MongoDB Atlas 연결하기</h3>
<p>express로 기본적인 서버 설정하는건 담에 알아보기로 하고 오늘은 DB연결부분 부터 시작해 보자.</p>
<p>터미널에 다음 명령어를 입력하고 몽고DB와 mongoose를 설치해 준다.</p>
<pre><code>npm install -s mongodb
npm install mongoose</code></pre><p>mongoose란 node.js와 mongoDB 맵핑을 도와주는 ODM(Object Data Mapping) 라이브러리 라고 한다.</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/12ccd68a-4e52-4feb-a742-9ebd8336368a/image.png" alt=""></p>
<pre><code>mongoose.connect(위의 Connect to Cluster코드입력) // 난 변수로 집어넣음</code></pre><p>초록색 박스는 username 이고(기본으로 들어가 있다) <strong>빨간색 박스 부분에 password를 적어넣는다 &lt;,&gt; 빼고!</strong></p>
<p>나머지 코드는 적당히 따라쳐서 넣어주자.</p>
<p>이제 서버를 돌려보자.</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/95b8d91f-d0e8-4861-94f5-aa65fc2fd6c7/image.png" alt="">연결완료 !</p>
<h3 id="마무리">마무리</h3>
<p>항상 느끼는 거지만 실제 인터넷 뒤지고 하는거보다 블로그에 글쓰는게 훨씬 힘들고 오래걸린다.
그래서 공부가 되나보다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SSH Key로 GitHub 원격저장소 와 Git 로컬 저장소 연결]]></title>
            <link>https://velog.io/@solda-blue/SSH-Key%EB%A1%9C-GitHub-Git-%EB%A1%9C%EC%BB%AC-%EC%A0%80%EC%9E%A5%EC%86%8C-%EC%97%B0%EA%B2%B0</link>
            <guid>https://velog.io/@solda-blue/SSH-Key%EB%A1%9C-GitHub-Git-%EB%A1%9C%EC%BB%AC-%EC%A0%80%EC%9E%A5%EC%86%8C-%EC%97%B0%EA%B2%B0</guid>
            <pubDate>Wed, 15 Feb 2023 12:53:42 GMT</pubDate>
            <description><![CDATA[<p>학원에서 공부한 HTML 작업 폴더를 Git으로 commit하고 내용을 GitHub Repository에 push 하려고 했는데</p>
<p><strong>remote: Support for password authentication was removed on August 13, 2021.
remote: Please see <a href="https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls">https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls</a> for information on currently recommended modes of authentication.
fatal: Authentication failed for &#39;<a href="https://github.com/solda-blue/~~~/&#39;">https://github.com/solda-blue/~~~/&#39;</a></strong></p>
<p>이런 메시지가 출력되었다
처음엔 또 맥북 문제인가 싶었지만 GitHub 비밀번호로 remote(원격제어)하는 방식이 만료되었다고 한다.</p>
<p>그래서 열심히 구글링을 한 결과 SSH Key를 이용하면 GitHub와 연동할 수 있다고 한다.</p>
<p>일단 ssh 디렉토리로 가서 생성해둔 키가 있는지 확인해보자.</p>
<pre><code>$ cd ~/.ssh
$ ls</code></pre><p>터미널에 해당 명령어를 입력하니
<img src="https://velog.velcdn.com/images/solda-blue/post/622b7c3b-9a4b-461d-a5b1-30a706a872a0/image.png" alt=""></p>
<p>이렇게 미리 생성해둔 키가 있었다.</p>
<p>아마 일전에 AWS를 이용하기 위해서 만들어놨던거 같지만 그 전에는 블로깅을 하지 않아서 지금은 기억이 전혀 나지 않았다.</p>
<p><a href="https://www.lainyzine.com/ko/article/how-to-link-github-remote-repository-and-local-git-repository/">https://www.lainyzine.com/ko/article/how-to-link-github-remote-repository-and-local-git-repository/</a></p>
<p><a href="https://hankyeolk.github.io/2021/08/15/githubSSH.html">https://hankyeolk.github.io/2021/08/15/githubSSH.html</a></p>
<p>그래서 이 두분의 포스트를 많이 참고 했는데 키 생성부분은 다음에 정리하기로 하고 오늘은 SSH Key를 내 Github 계정에 등록하고 SSH 방식으로 Git push 해보자</p>
<p>(아직 SSH Key가 없으신 분들은 위의 블로그로 가시면 아주 자세하고 친절하게 설명해 놓았다. 아주아주 고마우신 분들)</p>
<p>일단 id_rsa 와 id_rsa.pub 이렇게 두개의 key가 있는데 서로 완전히 다른 key가 아니라 저렇게 한쌍을 이루고 있는거라고 보면 된다. 그중에서 .pub이라고 되어있는 키는 public key(공개 키)로써 내가 접속하려는 서버에 등록하고 내 컴퓨터에 저장된 public key와 쌍을 이루는 private key(개인키, 비밀 키)를 서로 대조해서 일치 할 때에 인증이 된다고 볼 수 있다.</p>
<p>그러므로 public key는 공개해도 크게 상관이 없지만 private key는 절대 함부러 공개해선 안된다. </p>
<p>(체계적으로 공부한게 아니라 틀린부분이 다수 있을 수 있으니 주의)</p>
<p>자 그러면 일단 내 public key를 출력해보자.</p>
<pre><code>$ cat id_rsa.pub</code></pre><p><img src="https://velog.velcdn.com/images/solda-blue/post/f23e18f0-4856-45c0-b541-dae8aac9be93/image.png" alt=""></p>
<p>이렇게 나온 key를 복사한 다음</p>
<pre><code>pbcopy &lt; ~/.ssh/id_rsa.pub</code></pre><p>(그냥 복사해도 되지만 이렇게 복사하는게 낫다고 한다.)</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/245fe0dc-e81a-4246-ac7b-f99ea7f8b7f8/image.png" alt=""></p>
<p><a href="https://github.com/settings/ssh/new">https://github.com/settings/ssh/new</a>
위 주소로 들어가면 SSH Key등록 창이 나온다. (당연히 GitHub 계정이 필요하다.)</p>
<p>Title은 본인이 알아보기 편한대로 지으면 되고 아까 복사한 public key를 key 영역에 붙여넣기 한다. (key type은 뭔지 몰라서 건들지 않았는데 그래도 성공했다.)
<img src="https://velog.velcdn.com/images/solda-blue/post/3185f214-5133-4e18-9c59-0ddfc1296f14/image.png" alt=""></p>
<p>잘 등록 된걸 볼 수 있다.</p>
<p>그 후엔 https url 주소로 되어있는 세팅을 아래와 같이 바꿔준다.</p>
<pre><code>$ git remote set-url [origin name] git@github.com:[username]/[repository name].git</code></pre><p>이제 모든 설정이 끝이 났다. 이제 push를 해주면</p>
<pre><code>$ git push -u origin main</code></pre><p><img src="https://velog.velcdn.com/images/solda-blue/post/3a95e5ee-ffaf-4380-8426-4671e6872bd8/image.png" alt=""><img src="https://velog.velcdn.com/images/solda-blue/post/090f3d10-0ebd-472c-a111-2c347e40f8a3/image.png" alt=""></p>
<p>정상적으로 Repository에 파일들이 올라가는걸 볼 수 있다.</p>
<p><strong>느낀점 : 무엇이든 할 때 자료정리 잘하고 바로바로 기록해두자.
그리고 벨로그 글 작성할때도 좀 체계적으로 적자.</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[토글로 css변경하기 - JavaScript(classList)]]></title>
            <link>https://velog.io/@solda-blue/%ED%86%A0%EA%B8%80%EB%A1%9C-css%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0-JavaScriptclassList</link>
            <guid>https://velog.io/@solda-blue/%ED%86%A0%EA%B8%80%EB%A1%9C-css%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0-JavaScriptclassList</guid>
            <pubDate>Mon, 13 Feb 2023 02:20:04 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/solda-blue/post/12ec0655-17c9-4618-9aed-c5181e3703a7/image.png" alt=""></p>
<p><strong>파란색 영역을 클릭시에 하위 항목들이 열고 닫히는 기능을 구현해 보려고 한다</strong></p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/ee120102-f375-4dbb-839e-bdaae77c1388/image.png" alt=""></p>
<p>가장 먼저 생각나는건 if문으로 열렸을 때, 닫혔을 때 따로 조작할 수 있게 만들 수 있겠지만 그렇게 하면 코드도 복잡해지고 직관적이지 않은 것 같아서 다른 방법을 찾아보기로 했다</p>
<p><strong>MDN의 classList설명</strong>
<a href="https://developer.mozilla.org/ko/docs/Web/API/Element/classList">https://developer.mozilla.org/ko/docs/Web/API/Element/classList</a></p>
<p>역시나 어렵게 설명되어 있다
<img src="https://velog.velcdn.com/images/solda-blue/post/31469bca-bd9e-4f14-b0f6-199f08ff8080/image.png" alt=""></p>
<p>내가 필요한 건 요소를 클릭했을 때 열려있으면 닫고, 닫혀있으면 열면 되는 것이기에 class.toggle 을 쓰기로 했다.</p>
<pre><code>클릭하는 변수명.addEventListener(&#39;click&#39;, function() {
    변경될 변수명.classList.toggle(&#39;추가 클래스 명&#39;);
}</code></pre><p><img src="https://velog.velcdn.com/images/solda-blue/post/87c9673b-d65d-48ab-baef-2643611e3c23/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/c4d0a11b-9b48-452f-abeb-a2b7f36b1e72/image.png" alt=""></p>
<p>예를 들어 위의 id=&quot;btnHtml&quot;이라고 되어있는 영역을 클릭하면 
밑의 menuHtml div의 class명 에 &#39;toggle&#39; 이라는 추가 클래스명이 들어가게 된다
<img src="https://velog.velcdn.com/images/solda-blue/post/cf39e1cc-860f-4125-8589-957193083806/image.png" alt=""></p>
<p>이후에는 형식에 맞게 필요한 css를 작성 해주면 된다.
<img src="https://velog.velcdn.com/images/solda-blue/post/4bacb2b2-1529-4369-b883-514c628ddd0e/image.png" alt=""></p>
<hr/>

<p>classList.toggle 외에도 add, remove 등과 같은 프로퍼티도 많으니 필요할 때 찾아서 사용하면 된다.
메서드 역시 click외에 mouseover 같은 것을 사용할 수 있다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[로또 번호 생성기 만들기 - JavaScript ( set )]]></title>
            <link>https://velog.io/@solda-blue/%EB%A1%9C%EB%98%90-%EB%B2%88%ED%98%B8-%EC%83%9D%EC%84%B1%EA%B8%B0-%EB%A7%8C%EB%93%A4%EA%B8%B0-JavaScript-Set-Mathrandom</link>
            <guid>https://velog.io/@solda-blue/%EB%A1%9C%EB%98%90-%EB%B2%88%ED%98%B8-%EC%83%9D%EC%84%B1%EA%B8%B0-%EB%A7%8C%EB%93%A4%EA%B8%B0-JavaScript-Set-Mathrandom</guid>
            <pubDate>Sun, 12 Feb 2023 15:22:59 GMT</pubDate>
            <description><![CDATA[<p>자바스크립트 math.random을 배운 김에 로또 번호 생성기를 만들어 보고 싶어짐</p>
<p>math.random은 귀찮으니 다음에 작성</p>
<p>MDN 설명 =&gt;
<a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Set">https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Set</a></p>
<p>역시나 설명이 어렵다 
set은 array랑 비슷한데 중요한거만 이야기 하자면</p>
<ol>
<li>배열 내에서 같은 값을 하나만 가진다 (중복이 없다는 말)</li>
<li>index로 요소에 접근이 불가하다</li>
</ol>
<pre><code>const arr = [1, 5, 3, 8, 5, 3]</code></pre><p>이런 배열이 있다고 했을 때</p>
<pre><code>const set = new Set(arr)
console.log(set)</code></pre><p>해당 배열을 Set으로 변환 시키면 
<img src="https://velog.velcdn.com/images/solda-blue/post/e81e54ec-1303-4f2f-afd1-14f073814aa7/image.png" alt=""></p>
<p>중복되는 요소를 제거하고 저렇게 만들어 준다.</p>
<p>array 랑은 다르게 배열의 길이가 length가 아닌 size로 나타낸다.
(size 프로퍼티는 getter 함수만 존재하는 접근자 프로퍼티라서 size를 조작해서 개수를 바꾸려는 시도는 무시 된다고 한다)</p>
<p>그 외에 많이 쓰이는 메소드는 </p>
<h4 id="setprototypeaddvalue--요소-추가하기">Set.prototype.add(value) =&gt; 요소 추가하기</h4>
<pre><code>set.add(1).add(2);
console.log(set); // Set(2) {1, 2}</code></pre><h4 id="setprototypeclear--요소-다-지우기">Set.prototype.clear() =&gt; 요소 다 지우기</h4>
<pre><code>set.clear();
console.log(set); // Set(0) {}</code></pre><h4 id="setprototypedeletevalue--요소-지우기">Set.prototype.delete(value) =&gt; 요소 지우기</h4>
<pre><code>const set = new Set([1, 2, 3]);
set.delete(2);
console.log(set); //Set(2) {1, 3}</code></pre><h4 id="setprototypehasvalue--요소-찾기">Set.prototype.has(value) =&gt; 요소 찾기</h4>
<p>해당 요소가 있으면 =&gt; true, 없으면 =&gt; false;</p>
<p>그 외는 다음에 알아보자</p>
<h3 id="그래서-로또-번호-생성기는">그래서 로또 번호 생성기는?</h3>
<pre><code>        function handleLotto () {

            // 새로운 set 객체 생성
            const set = new Set();

            // for 문으로 작성하면 6번만 돌고 그냥 중복만 제거함
            // while로 길이가 6이 되기 전까지 돌린다
            while ( set.size &lt; 6) {
                let num = Math.floor(Math.random() * 45)+ 1;
                set.add(&quot; &quot; + num);
            }
            console.log(set);

            // 정렬을 위해 다시 배열로 변경
            const lotto = Array.from(set);

            // 오름차순 정렬
            lotto.sort(function compare(a, b) {
                return a - b;
            });

            content.innerHTML = lotto;
        };        </code></pre><p>일반 배열로 만드려고 하니까 중복 문제 처리하기 까다로워서 Set을 사용하여 로또 번호 생성기를 만들어 봤다
<img src="https://velog.velcdn.com/images/solda-blue/post/a4295e14-875e-4161-b5b3-83af41a0e49f/image.png" alt="">
잘 작동하는 모습이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[div 안에 html 넣는 법 - Ajax (XMLHttpRequest)]]></title>
            <link>https://velog.io/@solda-blue/div-%EC%95%88%EC%97%90-html-%EB%84%A3%EB%8A%94-%EB%B2%95-Ajax-XMLHttpRequest</link>
            <guid>https://velog.io/@solda-blue/div-%EC%95%88%EC%97%90-html-%EB%84%A3%EB%8A%94-%EB%B2%95-Ajax-XMLHttpRequest</guid>
            <pubDate>Thu, 09 Feb 2023 13:28:38 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/solda-blue/post/717506e8-e554-4523-8cf8-c2a6a2fe408c/image.png" alt=""></p>
<p>학원 예제들인데 html 문서 확인 할 때마다 일일히 live server 실행하기 귀찮기 때문에 일반 사이트들 처럼 SPA형식으로 만들어서 관리하기로 했다.</p>
<p>js연습도 하고 따로 뭐 깔기도 번거롭기 때문에 그냥 js 로만 만들 방법이 없는지 찾아보다가 XMLHttpRequest 라는게 있다고 한다.</p>
<p>Ajax 설명
<a href="http://www.tcpschool.com/ajax/intro">http://www.tcpschool.com/ajax/intro</a></p>
<p>XMLHttpRequest 설명
<a href="http://www.tcpschool.com/xml/xml_dom_xmlHttpRequest">http://www.tcpschool.com/xml/xml_dom_xmlHttpRequest</a></p>
<p>Ajax 나무위키 설명
<a href="https://namu.wiki/w/AJAX#s-2.5.1">https://namu.wiki/w/AJAX#s-2.5.1</a></p>
<p>핵심은 비동기적으로 서버에 요청을 하여 json, xml, html 등등의 데이터를 받아 올 수 있는데 요청하지 않은 정보는 받아 올 수 없기 때문에 푸시 알림 같은 기능은 X</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/25abdaff-bd59-406e-a8d3-f92050329ef0/image.png" alt=""></p>
<p>버튼을 눌렀을 때 해당하는 html 파일을 content div안에 불러오자</p>
<pre><code>&lt;html&gt;
 &lt;head&gt;
  &lt;script type=&quot;text/javascript&quot;&gt;
   var request = new XMLHttpRequest(); // XMLHttpRequest 생성
   request.open(&quot;GET&quot;, &quot;//namu.wiki/raw/틀:틀%20모음/&quot;); // 데이터를 GET Method로 요청
   request.send(); // 실제 Send
   request.onreadystatechange = function() {
    if ( request.readyState === 4 &amp;&amp; request.status === 200 ) { // request가 끝났으며(4), 성공적(200)인 경우. request.onload=()=&gt;{} 으로 교체해도 가능하다.
     document.getElementById(&quot;content&quot;).innerHTML = request.responseText; // #content 태그 내의 내용을 받아온 텍스트로 교체.
    }
   };
  &lt;/script&gt;
 &lt;/head&gt;
 &lt;body&gt;
  &lt;div id=&quot;content&quot;&gt;&lt;/div&gt;
 &lt;/body&gt;
&lt;/html&gt;
</code></pre><p>킹무위키 예제인데 거의 복붙해서 써도 작동이 잘된다</p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/cca64f08-e89f-4551-9e24-a04fe86db461/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/solda-blue/post/3868d700-0fc0-4107-b913-ff742ed5b853/image.png" alt=""></p>
<p>대충 잘 된다</p>
<p>다음 할일 : 문서가 앞으로 많아 질것 같으니 위의 버튼들을 사이드 햄버거 메뉴 만들어서 집어넣고 셀렉터랑 문서 url 코드가 너무 번잡하니 저것도 정리하자</p>
<hr />

<p><img src="https://velog.velcdn.com/images/solda-blue/post/62ce5633-e94f-4164-b29b-35cb465134a1/image.png" alt=""></p>
<p>일단 최대한 코드 줄인 것</p>
]]></description>
        </item>
    </channel>
</rss>