<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>april.log</title>
        <link>https://velog.io/</link>
        <description>Slowly but surely</description>
        <lastBuildDate>Wed, 29 Nov 2023 05:53:34 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>april.log</title>
            <url>https://velog.velcdn.com/images/dev-april/profile/8e261654-3317-400f-9ff1-6bc7ef24bdc1/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. april.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dev-april" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[React 댓글 목록 무한 스크롤]]></title>
            <link>https://velog.io/@dev-april/React-%EB%8C%93%EA%B8%80-%EB%AA%A9%EB%A1%9D-%EB%AC%B4%ED%95%9C-%EC%8A%A4%ED%81%AC%EB%A1%A4</link>
            <guid>https://velog.io/@dev-april/React-%EB%8C%93%EA%B8%80-%EB%AA%A9%EB%A1%9D-%EB%AC%B4%ED%95%9C-%EC%8A%A4%ED%81%AC%EB%A1%A4</guid>
            <pubDate>Wed, 29 Nov 2023 05:53:34 GMT</pubDate>
            <description><![CDATA[<p>댓글이 만약 1만개라면...? 아니면 이미지가 포함된 댓글이라면?
한번에 가져올때 로딩이 걸리거나 속도가 느려질게 뻔하다</p>
<h1 id="라이브러리-사용">라이브러리 사용</h1>
<h2 id="react-intersection-observer">react intersection-observer</h2>
<p>특정 컴포넌트(요소,태그) viewport 안에 발견되어있는지를 감지하는 라이브러리
(이외에도 react window, react infinite scroll 등 여러가지가 있다)</p>
<h2 id="1-설치">1. 설치</h2>
<p><code>npm install react-intersection-observer --save</code></p>
<h2 id="2-관찰대상-알려주기빨간-div">2. 관찰대상 알려주기(빨간 div)</h2>
<p><img src="https://velog.velcdn.com/images/dev-april/post/6440f200-7747-4734-a39d-0d25ef0cdf54/image.png" alt=""></p>
<h3 id="activitycommentsectionjs">activityCommentSection.js</h3>
<pre><code class="language-jsx">import {useInView} from &quot;react-intersection-observer&quot;;

const ActivityCommentSection = (props)=&gt;{
.
.
.
    // 앞에있는 ref는 우리가 관찰할 요소를 알려주는데 사용
    // 뒤에있는 inView는 우리가 관찰할 요소가 화면에 나타나면 true
    // 안나타나면 false가 들어있는 변수
    const [ref, inView] = useInView();

     &lt;CommentListWrap&gt;
                {
                    commentList.map((comment)=&gt; &lt;CommentBlock
                        key={comment.id} 
                        onDeleteClick={onDeleteClick} 
                        comment={comment}
                        /&gt;)
                }
                &lt;div ref={ref} style={{backgroundColor:&#39;red&#39;}}&gt;ddd&lt;/div&gt;
     &lt;/CommentListWrap&gt;</code></pre>
<h2 id="3-몇개씩-가져올껀지-무슨-페이지를-가져올껀지-수량-알려주기">3. 몇개씩 가져올껀지, 무슨 페이지를 가져올껀지 수량 알려주기</h2>
<h3 id="activitycommentsectionjsstate-변수-만들기">activityCommentSection.js(State 변수 만들기)</h3>
<pre><code class="language-jsx">const [currentPage, setCurrentPage] = useState(1);
const [isEnd, setIsEnd] = useState(false); // 댓글을 끝까지 다 가져왔다면 true 아니면 false가 들어있음
.
.
.

    // 댓글 목록 가져오기
    useEffect(()=&gt;{
        let tmp = async ()=&gt;{
            if(accessToken === null) return;
            if(inView === false) return;
            if(isEnd === true) return;
            try{
                let res = await axios.get(`/api/comments?activityId=${props.activityId}&amp;limit=${3}&amp;page=${currentPage}`, {
                    headers:{Authorization:`Bearer ${accessToken}`}
                })
                setCurrentPage(currentPage + 1); // 2페이지로 바꿔놓고
                if(res.data.length === 0){
                    setIsEnd(true);
                }
                setCommentList([...commentList, ...res.data]); // 기존에 3개가 있었으면 +3개를 추가해서 배열로 붙여줘야 함
            }catch(err){
                alert(&#39;댓글목록 오류&#39;);
            }
        }

        tmp();

    }, [props.activityId, accessToken, inView]); // 의존성배열(바뀌면 다시 실행해줘)

const onCommentClick = async ()=&gt;{
        try{
            let res = await axios.post(&#39;/api/comments&#39;, {
                    content, 
                    activityId: props.activityId 
                },
                {headers:{Authorization:`Bearer ${accessToken}`}}
            );
            // 댓글목록을 끝까지 다 가져온 상태라면 직접 화면에도 보이게 추가
            if(isEnd === true){
                setCommentList( [...commentList , res.data] )
            }
            alert(&#39;댓글 추가 성공!!&#39;);

        }catch(err){
            alert(&#39;댓글 추가 중 오류 발생..!&#39;);
        }
    }
</code></pre>
<h3 id="appjs">app.js</h3>
<pre><code class="language-jsx">app.get(&#39;/api/comments&#39;, async(req, res)=&gt;{
    const activityId = Number(req.query.activityId);
    const limit = Number(req.query.limit); // 몇개?
    const page = Number(req.query.page); // 몇페이지?
    const offset = (page-1) * limit;
    let sql=`
        select * from tbl_comments
        where activity_id = ?
        order by created_date asc
        limit ? offset ?;
    `;

  try{
        const token = req.headers.authorization.replace(&#39;Bearer &#39;, &#39;&#39;);
        let user = jwt.verify(token, process.env.JWT_SECRET);
        let [results] = await pool.query(sql, [activityId, limit, offset])    
.
.
.

    }catch(err){
        res.status(500).json(&#39;오류발생&#39;);
    }
})</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript 전개 연산자(...)]]></title>
            <link>https://velog.io/@dev-april/javaScript-%EC%A0%84%EA%B0%9C-%EC%97%B0%EC%82%B0%EC%9E%90</link>
            <guid>https://velog.io/@dev-april/javaScript-%EC%A0%84%EA%B0%9C-%EC%97%B0%EC%82%B0%EC%9E%90</guid>
            <pubDate>Fri, 17 Nov 2023 03:50:17 GMT</pubDate>
            <description><![CDATA[<h2 id="전개연산자-">전개연산자 ...</h2>
<p>   배열에서 사용 가능,
   객체에서 사용 가능</p>
<h3 id="배열-예시">배열 예시</h3>
<pre><code class="language-jsx">    let ar = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];

    let ar2 = ar; (얉은 복사 - 주소(위치)만 복사)

    let ar2 = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]; (깊은 복사)
    배열 새롭게 하나 만들기. 모양, 내용물은 똑같지만 완전 다른 위치에 넣어둠
    근데 좀 귀찮네...? 안에 뭐가 들어있을지 모른다면?

    let ar2 = [];
    for(let i = 0 ; i &lt; ar.length; i++){
        ar2.push(ar[i]);
    }

    복잡하네..? 그래서 나온게 바로
    전개 연산자!!
    let ar = [ 10, 20, 30 ];

    let ar2 = [ ...ar ]; 완전 똑같은 배열을 똑같이 만들 수 있다</code></pre>
<h3 id="객체-예시">객체 예시</h3>
<pre><code class="language-jsx">    let book = { title:&#39;대모험&#39;, page:20, author:&#39;홍길동&#39; } 주소 A00 
    let book2 = book; 주소 A00

    book2.title = &quot;홍길동전&quot;
    그럼 둘다 바뀜. 주소가 똑같으니까

    let book2 = {title:book.title, page:book.page, author:book.author} 이렇게 해도되는데 귀찮;;
    let book2 = { ...book , price:100 , title:&#39;홍길동전&#39;};  주소 B00
    let book2 = { title:&#39;대모험&#39;, page:20, author:&#39;홍길동&#39;, price:100 , title:&#39;홍길동전&#39;}
    객체 안에서 key값은 중복될 수 없기때문에 뒷쪽에 있는 title이 덮어 써버린다.(title:&#39;홍길동전&#39;)



    let ar2[0] = 100;
    // ar2 : [100, 20, 30, 40, 50, 60, 70, 80, 90, 100]
    // ar : [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]</code></pre>
<h3 id="예시2">예시2</h3>
<pre><code class="language-jsx">let ar = []
let ar2 = JSON.parse(JSON.stringify(fr))</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[AI 재프리 무어의 캐즘 이론]]></title>
            <link>https://velog.io/@dev-april/AI-%EC%9E%AC%ED%94%84%EB%A6%AC-%EB%AC%B4%EC%96%B4%EC%9D%98-%EC%BA%90%EC%A6%98-%EC%9D%B4%EB%A1%A0</link>
            <guid>https://velog.io/@dev-april/AI-%EC%9E%AC%ED%94%84%EB%A6%AC-%EB%AC%B4%EC%96%B4%EC%9D%98-%EC%BA%90%EC%A6%98-%EC%9D%B4%EB%A1%A0</guid>
            <pubDate>Thu, 19 Oct 2023 07:35:18 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/dev-april/post/19254c29-ec3b-46cf-907e-7063c45fdc29/image.png" alt="">
출처 <a href="https://channel.io/ko/blog/chasm">https://channel.io/ko/blog/chasm</a></p>
<p>사용자 기술수용주기를 검색하니 재프리 무어의 캐즘 이론이 무수히 나왔다. 그 중 &lt;제프리 무어의 캐즘 마케팅: 스타트업을 메인마켓으로 이끄는 마케팅 바이블&gt; 북리뷰가 잘 되어있는 것 같아 발췌 해왔다(thanks to 제니 Zeni)</p>
<p><img src="https://velog.velcdn.com/images/dev-april/post/d07b86ee-59f0-42ba-8909-62d02740b1a6/image.jpg" alt=""></p>
<p>출처 <a href="https://blog.naver.com/aaajiya/222842002293">https://blog.naver.com/aaajiya/222842002293</a></p>
<h2 id="1부-캐즘을-발견하라">1부 캐즘을 발견하라</h2>
<blockquote>
<p>1.구체적으로 첨단기술 시장의 개발에서 가장 위험한 시점은 &#39;실험적인&#39; 소수의 고객들에 의해 지배되는 &#39;초기시장&#39;에서 &#39;실용적인&#39; 성향을 지닌 다수의 고객들에 의해 지배되는 &#39;주류시장&#39;으로 전환이 이루어지는 시기이다. 흔히들 간과하지만 이 두 시장의 간극은 &#39;캐즘&#39;이라고 불릴 만큼 심대하다. 
따라서 이 캐즘을 뛰어넘는 것은 모든 장기적인 첨단기술 마케팅 계획에서 주안점이 되어야 한다. 캐즘 뛰어넘기에 성공하면 첨단기술을 통해 부가 창출되고, 캐즘 뛰어넘기에 실패하면 그 부가 사라진다.
<br/>
2. 모든 혁신적인 첨단기술 제품은 처음에 시장 가치나 용도가 전혀 드러나지 않다가 &#39;조기 사용자(early adopter) 집단&#39;에서 많은 관심을 이끌어내는 &#39;엄청난 특성&#39;을 지닌 일시적 유행으로 시작된다. 그것이 초기시장이다.
<br/>
3.초기시장이 조성된 후에 나머지 사람들이 그 제품으로 다른 무언가를 창출할 수 있을지 관망하는 시기가 찾아온다. 그것이 캐즘이다.
만약 그 제품에서 실제 무언가가 창출된다면(잠재 고객층에게 합리적인 가격에 제공될 수 있는 어떤 가치 제안이 발견된다면) 새로운 주류시장이 형성되는데, 대체로 그 속도가 매우 빨라 초기의 선도자들은 엄청난 성공을 거둘 수 있다.
이 모든 과정에서 결정적인 요소는 캐즘을 뛰어넘는 것이다. 다시 말해, 주류시장의 새싹이 돋아날 수 있도록 이끌어야 한다.
<br/>
4. 마니아 수준을 초월하고 환상을 극복하기 위한 핵심적인 요소는 새로운 기술이 과거에는 불가능했던 전략적인 도약을 이끌어낼 수 있음을 입증하는 것이다. 따라서 그 기술은 고유한 가치를 지녀야하며, 일반인들의 호응을 얻어야한다.그런 장점은 특히 신제품의 성능과 가치를 나타내는 독보적이고 인상적인 &#39;주력 제품 용도 (Hagship application)&#39; 를 통해 구축된다.
<br/>
5. 첨단기술 제품의 판매자들이 실험적인 조기 수용자들로 이루어진 시장기반에서 다음 수용 단계인 실용적인 초기 대중으로 전환을 시도할 때, 그들은 &#39;적극적으로 참고자료와 지원 체제를 요구하는 시장에서 참고기반과 지원기반 없이도&#39; 효과적으로 운영할 것이라고 생각한다.
그러나 이것이 바로 &#39;캐즘&#39;이며, 많은 부주의한 신생 벤처들이 이에 빠져들고 말았다.</p>
</blockquote>
<h2 id="2부-캐즘을-뛰어넘어라">2부 캐즘을 뛰어넘어라</h2>
<h3 id="3장-디데이-전략--전략적-표적이-될-시장부문을-선택하라">3장 디데이 전략 : 전략적 표적이 될 &#39;시장부문&#39;을 선택하라.</h3>
<blockquote>
<p>1.주류시장의 열매를 수확하려면 단계별 성공적으로 대응할 수 있는 시장전략을 수립해야 한다. 각 단계마다 성공의 열쇠는 현재 시장에서 지배적인 &#39;수용 유형&#39;에 집중하고, 그 계층의 심리통계를 이해하는 요령을 터득하여 그에 따라 마케팅 전략과 전술을 조정하는 것이다.
<br/>
2.실용주의자 시장 부문에서 보수주의자 시장 부문으로 유연한 전환을 이루기 위한 핵심적인 사항은 실용주의자들에게 새로운 패러다임을 추구할 수 있도록 문호를 개방하면서 그들과 탄탄한 관계를 유지하는 한편, 기존의 기반시설에 가치를 추가하면서 보수주의자들을 계속 만족시키는 것이다. 일종의 균형조절인 셈인데, 적절히 관리된다면 충성도 높고 성숙한 시장 부문의 잠재적인 수익은 대단히 크다.
<br/>
3. 디데이 전략을 차용해 주류시장에 진입하라. 여러분이 처음부터 장악할 수 있는 특정한 틈새시장을 겨냥해 경쟁자들을 몰아낸 후에 그곳을 폭넓은 운영을 위한 기반으로 활용하면서 캐즘을 뛰어넘어라. 최대한 범위를 좁힌 표적에 압도적인 힘을 집중하라.한정된 틈새시장에 진출하기 위해 많은 지원을 이끌어내는 것이다. 
<br/>
초기의 과제를 단순화시켜야 기업의 시장변수를 제한할 수 있다. 경계가 명확할수록 메세지를 고안하고 전달하기 쉬우며 그 메세지는 입소문을 통해 빠르게 전파된다.
<br/>
즉, 디데이전략은 모두를 한 지점에 집중하도록 이끈다.</p>
</blockquote>
<h3 id="4장-공략-지점을-겨냥하라--표적-고객-선정--시장-세분화-정책">4장 공략 지점을 겨냥하라 : 표적 고객 선정 , 시장 세분화 정책</h3>
<blockquote>
<p>1.캐즘 뛰어넘기에서 성패를 좌우하는 우선적인 네가지 요소는 표적고객, 구매를 자극하는 이유, 완비제품, 경쟁에 대한 부분이며 이 네가지 요소 중 어느 하나도 다른 요소들에 비해 너무 낮은 점수가 나온다면 그 시장 시나리오는 활용될 수 없다.
<br/>
2.캐즘 뛰어넘기에서 성패를 좌우하는 기대 요소에는 제휴사 및 협력사, 유통, 가격정책, 경쟁, 포지셔닝, 다음 표적고객이 검토된다.</p>
</blockquote>
<h3 id="5장-침투-부대를-결성하라--시장-개발-전략---완비-제품-새로운-rd-인수-제휴-협력-등">5장 침투 부대를 결성하라 : 시장 개발 전략 - 완비 제품 (새로운 R&amp;D, 인수, 제휴, 협력 등)</h3>
<blockquote>
<p>1.제휴활동의 최종적인 결과는 &#39;시장의 창출&#39;이다. 시장은 단순한 구매자와 판매자 이상을 의미한다. 그것은 소위 &#39;가치사슬&#39;이라고 불리는 것을 창출하기 위해 연동하는 이해관계로 얽혀 있는 환경이다.
<br/>
2. 캐즘을 뛰어넘으려는 모든 기업에게 완비제품을 창출하기 위해 제휴관계를 체결하는 것은 가치 사슬을 형성하고 활성화하는 일이다.
<br/>
일단 가치가 창출되면 자유시장 체제가 이를 저절로 강화하기에 완비 제품 관리자는 그저 굿이나 보고 떡이나 먹으면 된다.
<br/>
요약하자면 완비제품 인프라 개발을 가속화하기 위해 전술적인 제휴에 의해 완비제품을 구체화하는 일은 캐즘을 뛰어넘기 위한 침투 부대를 구축하는 과정의 핵심이다. 
<br/>
3. 완비제품 전략을 원활히 수행하는 기업은 주류 시장에서 성공을 거둘 가능성이 매우 높다.</p>
</blockquote>
<h3 id="6장-전투를-규정하라--주류시장-경쟁환경을-구축하라">6장 전투를 규정하라 : 주류시장 경쟁환경을 구축하라</h3>
<blockquote>
<p>1.경쟁 포지셔닝 나침반을 개념 모델로 활용할 수 있다.
<br/>
2. 경쟁을 창출하기 위해서는 &#39;시장 대안&#39; 및 &#39;제품 대안&#39;을 경쟁자 지표로 활용할 수 있다.</p>
</blockquote>
<h3 id="7장-침투를-시작하라--유통과-가격정책">7장 침투를 시작하라 : 유통과 가격정책</h3>
<blockquote>
<p>1.캐즘을 뛰어넘는 시기에 기업의 최우선 목표는 주류시장에 진입할 유통경로를 확보하는 것이며, 그 경로는 실용주의자 고객들에게 편해야 한다.
<br/>
2.캐즘을 뛰어넘는 시기에 우리는 &#39;고객 지향적인 유통경로&#39;를 찾으면서 &#39;유통 지향적인 가격정책&#39;을 실행할 것이다.
<br/>
3. 각각의 계층마다의 선호 유통경로가 있다. 각각의 유통경로는 다른 유형의 표적고객들과 연계되는데 캐즘을 뛰어넘으려는 기업가들은 자신들의 표적시장 전략에 가장 적합한 유통경로를 선택해야 한다. 즉, 유통경로와 전략의 조화가 좋아야 한다.
<br/>
4. 시장 선도자의 기준가격에서 가격을 책정하면서 그에 따라 시장 선도력에 대한 주장을 강화하라. 그리고 유통경로에서 가격이윤을 남길 수 있도록 아주 높은 보상을 제공하라. 그 보상은 제품이 주류시장에 정착하고 제품의 판매권에 대한 경쟁이 치열해지면 단계적으로 축소될 것이다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[AI 산업 경쟁 분석 이론/방법론 Gartner's Hype Cycle(하이프 사이클)]]></title>
            <link>https://velog.io/@dev-april/AI-%EC%82%B0%EC%97%85-%EA%B2%BD%EC%9F%81-%EB%B6%84%EC%84%9D-%EC%9D%B4%EB%A1%A0%EB%B0%A9%EB%B2%95%EB%A1%A0-Gartners-Hype-Cycle%ED%95%98%EC%9D%B4%ED%94%84-%EC%82%AC%EC%9D%B4%ED%81%B4</link>
            <guid>https://velog.io/@dev-april/AI-%EC%82%B0%EC%97%85-%EA%B2%BD%EC%9F%81-%EB%B6%84%EC%84%9D-%EC%9D%B4%EB%A1%A0%EB%B0%A9%EB%B2%95%EB%A1%A0-Gartners-Hype-Cycle%ED%95%98%EC%9D%B4%ED%94%84-%EC%82%AC%EC%9D%B4%ED%81%B4</guid>
            <pubDate>Thu, 19 Oct 2023 06:11:23 GMT</pubDate>
            <description><![CDATA[<h1 id="hype-cycle">Hype Cycle</h1>
<p>하이프 사이클(Hype Cycle)은 기술의 성숙도를 표현하기 위한 시각적 도구이다. 과대광고 주기라고도 한다. 미국의 정보 기술 연구 및 자문 회사인 가트너에서 개발하였다.
<img src="https://velog.velcdn.com/images/dev-april/post/7c97b21f-0fca-418d-b9db-c22f470c5e34/image.jpg" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dev-april/post/df87a450-0a1d-4a60-954d-3ccc554a61e2/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dev-april/post/cbfafed4-e7d0-40d5-b6e5-1675fb5c248d/image.png" alt=""></p>
<blockquote>
<p>비판
하이프 사이클은 여러 가지 측면에서 많은 비판을 받았다. 주요 비판으로는 결과물이 기술 자체의 특성을 반영하지 못한다는 점, 과학적이지 못하다는 점, 기술이 개발되는 속도에 따른 변화를 반영하지 못한다는 점 등이 있다. 또 다른 것으로는, ‘사이클’ 자체는 신기술의 마케팅에 아무런 실질적인 이득을 줄 수 없으며 단지 기존에 이미 존재하는 트렌드를 설명할 수 있을 뿐이라는 비판도 있다. 또, 유사한 성격의 방법론인 기술 준비 지수와 비교했을 때 나타나는 문제점은 다음과 같다.
<br />
‘환멸’, ‘계몽’, ‘기대’와 같은 주관적인 용어로는 대상을 객관적으로 설명하거나 기술의 현재 위치를 제대로 나타낼 수 없다.
용어가 잘못된 이해를 불러 오는 면이 있다. 사용자는 실망하기를 원치 않으므로 계몽 단계에는 해당 기술을 멀리 해야 하는 것인가?
다음 단계로 넘어 가기 위해 어떤 것이 충족되어야 하는지에 대한 설명이 없다.</p>
</blockquote>
<p>출처: 위키백과 <a href="https://ko.wikipedia.org/wiki/%ED%95%98%EC%9D%B4%ED%94%84_%EC%82%AC%EC%9D%B4%ED%81%B4">https://ko.wikipedia.org/wiki/%ED%95%98%EC%9D%B4%ED%94%84_%EC%82%AC%EC%9D%B4%ED%81%B4</a></p>
<hr>
<h3 id="gartner-2023년-인공-지능-분야의-gartner-hype-cycle의-새로운-점-whats-new-in-artificial-intelligence-from-the-2023-gartner-hype-cycle">[Gartner] 2023년 인공 지능 분야의 Gartner Hype Cycle의 새로운 점 (What’s New in Artificial Intelligence from the 2023 Gartner Hype Cycle)</h3>
<blockquote>
<p>소개
2023 Gartner Hype Cycle™은 인공지능(AI)의 중요한 혁신과 기법들을 식별하며, 변혁적 혜택을 제공하면서 동시에 불완전한 시스템의 한계와 위험을 해결하려고 합니다. 특히, 인공지능 분야에서 향후 2~5년 동안 주목해야 할 기술로 생성형 AI와 의사 결정 인텔리전스를 꼽으며 상당한 이점을 제공할 것으로 전망했습니다. 이 중 생성형 AI는 개발자와 지식 근로자의 생산성에 미치는 영향으로 인해 다양한 비즈니스 프로세스와 인적 자원의 가치가 재고될 것으로 예상합니다.
<br/>
주요 내용
Gartner는 더 강력한 AI 시스템으로 향하는 생성형 AI의 움직임에 2가지 측면이 있다고 보고 있습니다.</p>
</blockquote>
<ol>
<li>생성형 AI에 의해 촉진될 혁신 (be fueled by GenAI)</li>
<li>생성형 AI의 발전을 촉진할 혁신 (fuel advances in GenAI)</li>
</ol>
<p><img src="https://velog.velcdn.com/images/dev-april/post/cd0fc92f-5c16-45c4-bee9-ae88f730f692/image.png" alt="">
출처 <a href="https://discuss.pytorch.kr/t/gartner-2023-gartner-hype-cycle-what-s-new-in-artificial-intelligence-from-the-2023-gartner-hype-cycle/2327/1">https://discuss.pytorch.kr/t/gartner-2023-gartner-hype-cycle-what-s-new-in-artificial-intelligence-from-the-2023-gartner-hype-cycle/2327/1</a></p>
<h4 id="synthetic-data">Synthetic data</h4>
<p>Synthetic data(합성 데이터)는 실제 데이터를 모방하거나 재현하기 위해 생성된 가상의 데이터입니다. 이러한 데이터는 실제 데이터의 특성과 분포를 시뮬레이션하거나 모방함으로써 데이터 분석, 기계 학습 모델 훈련, 프라이버시 보호 등 다양한 목적으로 사용됩니다. Synthetic data를 생성하는 주요 이유와 방법은 다음과 같습니다:</p>
<ol>
<li><p>프라이버시 보호: 실제 개인 정보를 포함하는 데이터를 대중에 노출하지 않으면서 데이터 분석 및 모델 훈련을 위한 안전한 대안으로 Synthetic data가 사용됩니다. 이렇게 하면 민감한 정보의 노출을 방지하면서도 데이터 분석 및 연구를 수행할 수 있습니다.</p>
</li>
<li><p>데이터 부족 문제 해결: 특정 작업 또는 분석을 위해 충분한 양의 실제 데이터가 없는 경우, Synthetic data를 생성하여 데이터 부족 문제를 해결할 수 있습니다. 이를 통해 모델을 훈련하고 테스트할 수 있으며, 예측 및 의사 결정을 개선할 수 있습니다.</p>
</li>
<li><p>데이터 분포 조작: Synthetic data를 사용하면 원하는 데이터 분포를 조작하거나 조정할 수 있습니다. 이를 통해 데이터 분석 또는 모델 훈련에 필요한 특정 분포를 시뮬레이션할 수 있습니다.</p>
</li>
</ol>
<p>Synthetic data는 다양한 방법을 사용하여 생성됩니다. 이러한 방법에는 확률 분포 모델, 생성적 적대 신경망(GANs), 잡음(노이즈) 추가, 데이터 증강 및 가상 시나리오 생성 등이 포함됩니다. Synthetic data를 생성할 때 핵심은 실제 데이터와 비슷한 특성 및 패턴을 유지하는 것이며, 이를 통해 모델이나 분석 결과가 실제 데이터에 대해 일반화될 수 있도록 보장하는 것입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[accessToken & Hooks🪝]]></title>
            <link>https://velog.io/@dev-april/accessToken-Hooks</link>
            <guid>https://velog.io/@dev-april/accessToken-Hooks</guid>
            <pubDate>Wed, 18 Oct 2023 14:24:58 GMT</pubDate>
            <description><![CDATA[<p>사실은 accessToken을 쓰려면
먼저 검사를 해줘야함
뭐를? accessToken이 null 인지 아닌지</p>
<h2 id="상황-1-로그인을-안해서-null">상황 1) 로그인을 안해서 null</h2>
<p>-&gt; localStorage에도 없음</p>
<h2 id="상황-2-로그인을-했는데-새로고침-했음">상황 2) 로그인을 했는데 새로고침 했음</h2>
<p>-&gt; localStorage에는 있는데 accessToken에는 없음</p>
<p>=&gt; useEffect( ) 를 써야한다</p>
<p><strong>그래서 우리는 hooks(hook 함수)를 직접 만들 수 있다!!</strong></p>
<hr>
<p>&lt;강사님 설명&gt;
Dashboardheader
CareerViewTable
...
로그인을 해야지만 볼 수 있는 컴포넌트들이 존재
    --&gt; accessToken을 사용하는 컴포넌트 들
    항상 accessToken이 잘 존재하는지를 검사
    --&gt; 즉 useEffect 에다가 accessToken이 있는지 없는지 확인 필요하다
매번 useEffect를 길게 쓰기 귀찮으니까 custom hook을 만들 수 있다</p>
<hr>
<p>Hook 함수는 
일반 함수에서 사용 X
콜백 함수에서 사용 X
Q. 그럼 어디서 사용하면 될까?
-useEffect 나 다른 use훅함수가 그려질때 사용</p>
<h3 id="hooksjs">hooks.js</h3>
<pre><code class="language-jsx">import { useContext, useEffect } from &quot;react&quot;;
import { UserContext } from &quot;../App&quot;;
import { useNavigate } from &quot;react-router-dom&quot;;

// accessToken이 있는지 없는지 검사하는 훅함수
export const useAuth = ()=&gt;{
    const {accessToken, setAccessToken} = useContext(UserContext);
    const navigate = useNavigate();
    useEffect(()=&gt;{
        //  1. 로그인이 안된 상태 localStorage의 accessToken null,
        //  전역 상태변수 accessToken null
        if(localStorage.getItem(&#39;accessToken&#39;) === null){
            alert(&#39;로그인이 필요한 페이지 입니다&#39;);
            navigate(&#39;/login&#39;, {replace : true});
            return;
        }

        //  2. 로그인은 되었으나 새로고침한 상태 accessToken 있음,
        //  전역 상태변수 accessToken null
        if(accessToken === null){
            setAccessToken(localStorage.getItem(&#39;accessToken&#39;));
            return;
        }

        //  3. 로그인 되었고, 새로고침도 안함
        //  localStorage accessToken 있음,
        //  전역 상태변수 accessToken 있음
        // =&gt; 뭔가를 실행시켜줄 필요가 없다

    }, [accessToken, setAccessToken, navigate]);
}

// 우리가 accessToken을 사용하는 모든 곳에다가 이걸 써줘야 한다(career.js에 적기)


// 페이지 이동을 위한 hook 함수
export const useMove = (dir)=&gt;{
    const navigate = useNavigate();
    return ()=&gt;{navigate(dir)}
}

// 페이지 이동인데 뒤로가기 못하게 이동하는 hook 함수
export const useReplace = (dir)=&gt;{
    const navigate = useNavigate();
    navigate(dir, {replace : true});
}</code></pre>
<p>엇...CareerPage 자체가 로그인 해야지만 볼 수 있는 페이지네? 그럼 저기다 바로 써주면 되겠다</p>
<h3 id="careerjs">career.js</h3>
<pre><code class="language-jsx">import CareerViewTable from &quot;../../components/career/careerViewTable&quot;;
import DashboardLayout from &quot;../../components/common/layout&quot;;
import { useAuth } from &quot;../../hooks/hooks&quot;;
import { Title } from &quot;../../styles/dashboard/career.styles&quot;;


const CareerPage = ()=&gt;{
  useAuth(); // 이 페이지 자체가 로그인 해야지만 볼 수 있는 페이지네..?

  return(
    &lt;DashboardLayout&gt;
      &lt;Title&gt;나의 경력을 관리하세요&lt;/Title&gt;
      &lt;p&gt;회사, 직위, 일자를 입력한 후 경력을 추가해 보세요!&lt;/p&gt;
      &lt;CareerViewTable/&gt;
    &lt;/DashboardLayout&gt;
  );
}

export default CareerPage;</code></pre>
<p>그럼 이제 accessToken 객체를 바로 사용할 수 있게된다</p>
<pre><code>{ headers : {Authorization : `Bearer ${localStorage.getItem(&#39;accessToken&#39;)}`}}
=&gt; {headers : {Authorization:`Bearer ${accessToken}`}}</code></pre><h3 id="headersjs">headers.js</h3>
<pre><code class="language-jsx">import { useContext, useEffect, useState } from &quot;react&quot;;
import { UserText } from &quot;../../styles/common/aside.styles&quot;;
import { Header } from &quot;../../styles/common/header.styles&quot;;
import axios from &quot;axios&quot;;
import { UserContext } from &quot;../../App&quot;;
import { useNavigate } from &quot;react-router-dom&quot;;
import MenuIcon from &#39;@mui/icons-material/Menu&#39;;
import MenuOpenIcon from &#39;@mui/icons-material/MenuOpen&#39;;
import { Popover } from &quot;@mui/material&quot;;

const DashboardHeader = ()=&gt;{

  const navigate = useNavigate();
  // 전역state변수에 있는 토큰 값 가져오기
  const {accessToken, setAccessToken} = useContext(UserContext);
  const [loggedInUser, setLoggedInUser] = useState( { 
    email:&#39;로그인후 이용해주세요&#39;,
    created_date:&#39;&#39;,
    updated_date:&#39;&#39;
  } );
  // const [loggedInEmail , setLoggedInEmail] = useState(&#39;로그인후 이용해주세요&#39;);

  // popOver 창의 기준 element 요소
  const [anchorEl, setAnchorEl] = useState(null);
  let open = Boolean(anchorEl);

  // 헤더가 그려지면 db가서 로그인 한 사람 정보 가져오기
  useEffect(()=&gt;{

    let tmp = async ()=&gt;{
      if(accessToken === null) return;
      try{
        let res = await axios.get(&#39;/api/loggedInEmail&#39;, 
          {headers : {Authorization : `Bearer ${accessToken}`}}
        );
        console.log(&#39;res&#39;, res);
    .
    .
    .
</code></pre>
<h3 id="careerviewtablejs">careerViewTable.js</h3>
<pre><code class="language-jsx">import { useContext, useEffect, useState } from &quot;react&quot;;
import { AddBox } from &quot;../../styles/dashboard/career.styles&quot;;
import DeleteOutlineIcon from &#39;@mui/icons-material/DeleteOutline&#39;;
import axios from &quot;axios&quot;;
import { UserContext } from &quot;../../App&quot;;

const CareerViewTable = ()=&gt;{
  const [careerList, setCareerList] = useState([]);
  // 토큰이 저장되어있는 전역 상태변수 가져오기
  const {accessToken , setAccessToken} = useContext(UserContext);

  useEffect( ()=&gt;{
    // CareerViewTable이 최초 렌더링 될때
    // express한테 career목록좀 가져다줘 라고 요청
    const fetchCareerList = async ()=&gt;{
      if(accessToken === null) return;
      try{
        let res = await axios.get(&#39;/api/career&#39;, 
          {headers : {Authorization:`Bearer ${accessToken}`}}
        );
        setCareerList(res.data);
      }catch(err){
        console.log(err);
      }
    }

    fetchCareerList();

  }, [accessToken]); // accessToken이 바뀌면 다시 한번 실행시켜줘

  .
  .
  .
</code></pre>
<p><img src="https://velog.velcdn.com/images/dev-april/post/1de9825f-db59-4231-9158-b519dd9a8c31/image.png" alt=""></p>
<p>React가 점점 복잡해진다...원래 프론트를 가장 좋아했는데..윽
머리에 쥐가 날것 같다...🐭🐭🐭</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React useRef( ) VS useState( )]]></title>
            <link>https://velog.io/@dev-april/React-useRef-%ED%95%A8%EC%88%98-jhj2xjso</link>
            <guid>https://velog.io/@dev-april/React-useRef-%ED%95%A8%EC%88%98-jhj2xjso</guid>
            <pubDate>Wed, 18 Oct 2023 13:14:35 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/dev-april/post/96201e5d-22be-4b2b-ba96-d055bbf91f32/image.webp" alt="">
출처 <a href="https://betterprogramming.pub/react-v18-demystifying-useref-forwardref-and-useimperativehandle-feec2fc5b2f6">https://betterprogramming.pub/react-v18-demystifying-useref-forwardref-and-useimperativehandle-feec2fc5b2f6</a></p>
<h1 id="리액트에서-변수는-크게-세가지">리액트에서 변수는 크게 세가지</h1>
<h2 id="1-일반변수">1. 일반변수</h2>
<p>값이 변경되어도 re-rendering되지 않음
re-rendering 될때 초기값이 대입됨</p>
<h2 id="2-state변수">2. state변수</h2>
<p>값이 변경되면 re-rendering을 함
re-rendering 되더라도 초기값이 대입되지 않음(자기값을 기억)</p>
<h2 id="3-ref-객체">3. ref 객체</h2>
<p>값이 변경되더라도 re-rendering 되지 않음
re-rendering되더라도 초기값이 대입되지 않음(자기 값을 기억)</p>
<pre><code class="language-jsx">const MyComponent = ()=&gt;{
    let a = 10; // 일반변수
      // re-rendering되어도 자기자신 값을 기억
      // 자기자신이 변하면 re-rendering 시키는것
      let [b , setB] = useState(10);

      // re-rendering될때 자기 자신의 값을 기억
      // 자기자신의 값이 수정되어도
      // re-rendering은 안시키고 싶음
      let c = useRef(null);
      // 객체가 만들어진다(current라는 키값) c.current

   return (
     &lt;&gt;
       {a}
       {b}
       {c.current}
       &lt;input ref={c} /&gt;
       &lt;button&gt;a버튼 클릭시 a를 1더한값으로 변경해줌&lt;/button&gt;
       &lt;button&gt;b버튼 클릭시 b를 1더한값으로 변경해줌&lt;/button&gt;
       &lt;button&gt;c버튼 클릭시 c를 1더한값으로 변경해줌&lt;/button&gt;
       &lt;h1&gt;안녕&lt;/h1&gt;
     &lt;/&gt;
    );
}</code></pre>
<pre><code>a는 re-rendering이 안되는데,
b는 re-rendering이 된다(state변수가 바뀌니까)
MyComponent( ); 함수의 재실행

a = 10
b = 11(변경되기 전 값을 기억하고 있음)
추가적으로 state변수(자기값이) 변하면 re-rendering 해주는것까지</code></pre><p><img src="https://velog.velcdn.com/images/dev-april/post/19aa1bda-1d9d-4a42-a1fc-f2d0f01b1c21/image.png" alt="">
&lt;MyComponent 컴포넌트가 리렌더링 될 때 다시 그려지는 모습&gt;</p>
<p>근데 이게 불편한점이...
리렌더링되도 값을 기억하고 싶어서 state변수를 사용하는데 
리렌더링하기는 싫은데?</p>
<p>그럴때 사용하는 함수가 useRef()
화면상에서 보여주고 싶으면 useState()
내부적으로만 값을 바꾸고 싶으면 useRef() - 하이브리드</p>
<p><strong>텍스트ref={ } React에만 있는 요소(HTML에는 없다)</strong>
input 태그 안에는 value 나 checked를 가져와서 사용할 수 있다</p>
<h3 id="결론">결론</h3>
<p><em>useRef는 꼭 사용하지 않아도 된다</em>
어떻게보면 useState의 상위호환..? 단점을 보완한 함수다</p>
<p>비어있는 배열에 넣어주고 싶으면 ref={(el)=&gt;{b.current.push(el)}} 함수를 사용</p>
<hr>
<h3 id="ref-객체의-current에-태그-객체를-대입하는-방법">Ref 객체의 current에 태그 객체를 대입하는 방법</h3>
<pre><code class="language-jsx">const ref객체이름 = useRef(null);

&lt;h1 ref={ref객체이름}&gt;안녕&lt;/h1&gt;

--&gt; ref객체이름.current에는 h1태그객체가 들어있다

Ref 객체의 current에다 배열을 만들고, 그 배열 속에 여러개의 태그 객체를 대입하는 방법

const ref객체이름 = useRef([]); // ref객체이름.current에는 비어있는배열

&lt;h1 ref={(el)=&gt;{ref객체이름.current.push(el)}}&gt;안녕&lt;/h1&gt;
&lt;p ref={(el)=&gt;{ref객체이름.current.push(el)}}&gt;반가워&lt;/p&gt;
&lt;input ref={(el)=&gt;{ref객체이름.current.push(el)}} /&gt;

--&gt; ref객체이름.current에는 [ h1태그객체, p태그객체, input태그객체 ] </code></pre>
<p>자, generous하게 full file을 보여주겠다</p>
<h3 id="reftestjs">refTest.js</h3>
<pre><code class="language-jsx">// useRef 익혀보기

import { useRef, useState } from &quot;react&quot;;

const RefTestComponent = ()=&gt;{
  const [a , setA] = useState(0);
  const b = useRef([]);
  let c = 0;

  const showAll = ()=&gt;{
    console.log(&#39;state변수 a : &#39;, a);
    console.log(&#39;b.current : &#39;, b.current);
    console.log(&#39;일반변수 c : &#39;, c);
  }

  return(
    &lt;&gt;
      &lt;h1&gt;RefTest 컴포넌트입니다&lt;/h1&gt;
      &lt;h1&gt;State변수 a 의 값: {a}&lt;/h1&gt;
      &lt;input ref={(el)=&gt;{b.current.push(el)}} type=&quot;checkbox&quot;/&gt;
      &lt;input ref={(el)=&gt;{b.current.push(el)}} type=&quot;checkbox&quot;/&gt;
      &lt;input ref={(el)=&gt;{b.current.push(el)}} type=&quot;checkbox&quot;/&gt;
      &lt;input ref={(el)=&gt;{b.current.push(el)}} type=&quot;checkbox&quot;/&gt;
      &lt;input ref={(el)=&gt;{b.current.push(el)}} type=&quot;checkbox&quot;/&gt;
      &lt;input ref={(el)=&gt;{b.current.push(el)}} type=&quot;checkbox&quot;/&gt;
      &lt;button onClick={()=&gt;{setA(a + 1)}}&gt;state변수 변경&lt;/button&gt;
      &lt;button onClick={()=&gt;{ b.current++; }}&gt;Ref객체 속 current변경&lt;/button&gt;
      &lt;button onClick={()=&gt;{ c++ }}&gt;일반 변수 변경&lt;/button&gt;
      &lt;br/&gt;
      &lt;button onClick={showAll}&gt;변수들 속의 값 보기&lt;/button&gt;
    &lt;/&gt;
  );
}

export default RefTestComponent;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[AI 산업 경쟁 분석 이론/방법론 Quinn 모델]]></title>
            <link>https://velog.io/@dev-april/%EC%82%B0%EC%97%85-%EA%B2%BD%EC%9F%81-%EB%B6%84%EC%84%9D-%EC%9D%B4%EB%A1%A0%EB%B0%A9%EB%B2%95%EB%A1%A0-Quinn-%EB%AA%A8%EB%8D%B8</link>
            <guid>https://velog.io/@dev-april/%EC%82%B0%EC%97%85-%EA%B2%BD%EC%9F%81-%EB%B6%84%EC%84%9D-%EC%9D%B4%EB%A1%A0%EB%B0%A9%EB%B2%95%EB%A1%A0-Quinn-%EB%AA%A8%EB%8D%B8</guid>
            <pubDate>Tue, 17 Oct 2023 14:10:29 GMT</pubDate>
            <description><![CDATA[<h1 id="퀸모델">퀸모델</h1>
<p><img src="https://velog.velcdn.com/images/dev-april/post/6a2c1673-c9dd-4e34-8de0-f2ac2ed37455/image.jpeg" alt="">
&quot;Quinn&#39;s Managerial Leadership&#39;s Roles&quot;
Source: Quinn R.E. et al. (1996). Becoming a Master Manager: A Competing Values Approach.</p>
<p><img src="https://velog.velcdn.com/images/dev-april/post/3153feb3-08c4-4c48-8a82-e391268431fe/image.jpeg" alt="">
&quot;Quinn&#39;s Competing Values Framework&quot;
Source: Quinn R.E. et al. (1996). Becoming a Master Manager: A Competing Values Approach.</p>
<p>출처 <a href="https://experienceetc.blogspot.com/2012/11/strategic-human-resource-management.html">https://experienceetc.blogspot.com/2012/11/strategic-human-resource-management.html</a></p>
<h2 id="1-개념">1. 개념</h2>
<blockquote>
<p>과거 조직문화에 관한 연구들은 다양하고 배타적이며 모순적인 가치요소들이 공존하고 있는 조직문화의 실제를 동태적으로 분석하지 못하고 일반적인 사회 문화 차원의 추상적인 접근이 많았다.이러한 접근방법은 조직 내에 존재하는 다양하고 서로 모순되는 가치요소에 대한 이해에 한계가 있으며, 다양한 상황조건에서 조직문화와 조직효과성의 관계를 설명하는데도 제약이 따랐다. 따라서 다양한 요소들을 포괄하는 시각으로 조직문화를 연구해 볼 필요성이 대두되었고, 이러한 맥락에서 출발하여 조직 문화에 대한 새로운 해석 가능성을 제시해주는 것이 경쟁가치모형(Competing Value Model)이었다. 조직문화의 연구에서 경쟁가치모형은 모순적이고 배타적인 다양한 조직문화의 가치요소들을 포괄적으로 분석할 수 있는 틀을 제공해 준다. 
  경쟁가치모형에서 각 차원의 양쪽 끝 부분에 두 개씩 효과성 지표 집락이 형성되어 총 4개의 집락이 생겨난다. 한 차원(수직축)은 다른 한 차원(수평축)은 내부지향, 통합, 단합(unity)을 강조하는 집락과, 외부지향, 차별, 경쟁을 강조하는 집락으로 구분되었다. 여기서는 각 차원을 연속체로 보고 양 끝에 상반(모순, 경쟁)되는 가치(집락)가 배치되었다고 하여 이 틀을 ‘경쟁가치모형(competing values model : CVM)이라고 부르게 되었다.</p>
</blockquote>
<h2 id="2-이론적-모형">2. 이론적 모형</h2>
<blockquote>
<p>조직문화의 경쟁가치모형은 두 가지 상반된 차원으로 구성되는데 이에 대해서 보다 구체적으로 살펴보면 다음과 같다. 유연성 지향의 가치는 분권화의 다양성(차별화)을 강조하는 반면, 통제지향의 가치는 집권화와 통합을 강조하는데, 이는 조직의 유기적 특성과 기계적 특성의 구분을 의미하기도 한다. 내부지향성은 조직의 유지를 위한 조정과 통합을 강조하는 반면, 외부지향성은 조직 환경에 대한 적응, 경쟁, 상호관계를 강조한다. 이러한 두 가지 차원의 결합에 의해 네 가지 조직문화의 유형이 결정되는데, 각 유형별로 리더십, 동기부여, 조직효과성 기준에 대한 상이한 기본전제를 특징으로 하고 있다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/dev-april/post/b4e25f56-2da8-44eb-9a3c-cad41495c831/image.png" alt="">
경쟁가치모형과 네 가지 조직문화 유형</p>
<p>출처 : Parker, R. &amp; Bradley, L.(2000), &quot;Organizational Culture in the Public Sector : evidence from six organizations, International Journal of Public Sector Management, 132(2)</p>
<h3 id="관계지향-문화">관계지향 문화</h3>
<blockquote>
<p>관계지향문화는 집단문화(group culture) 혹은 인간관계 모형(human relation model)이라고도 하며, 구성원들의 신뢰, teamwork을 통한 참여, 충성, 사기 등의 가치를 중시한다.  이러한 문화유형에서는 무엇보다 조직 내 가족적인 인간관계의 유지에 최대의 역점을 둔다. 조직구성원이나 단결, 협동, 공유가치, 의사결정과정에 참여 등이 중시되며, 개인의 능력개발에 대한 관심이 높고 조직구성원에 대한 인간적 배려와 가족적인 분위기를 만들어내는 특징을 가지고 있다.</p>
</blockquote>
<h3 id="혁신지향-문화">혁신지향 문화</h3>
<blockquote>
<p>혁신지향문화는 발전문화(development culture), 혹은 개방체계모형(open system model)이라고도 하며, 조직의 변화와 유연성을 강조하면서, 조직이 당면하고 있는 외부환경에의 적응능력에 중점을 둔다. 외부환경에 대한 변화지향성과 신축적 대응성을 기반으로 조직구성원의 도전의식, 모험성, 창의성, 혁신성, 자원획득 등을 중시하며 조직의 성장과 발전에 관심이 높은 조직문화를 의미하기 때문에 조직구성원의 업무수행에 대한 자율성과 자유 재량권 부여 여부가 혁신문화의 핵심 요인이 된다.</p>
</blockquote>
<h3 id="위계지향-문화">위계지향 문화</h3>
<blockquote>
<p>위계지향문화는 위계문화(hierarchy culture), 혹은 내부과정모형(internal process model)이라고도 하며, 공식적 명령과 규칙, 집권적 통제와 안정지향성을 강조하는 관료제의 가치와 규범을 반영한다. 위계질서에 의한 명령과 통제, 업무 처리 시 규칙과 법 준수, 관행, 안정, 문서와 형식, 보고와 정보관리, 명확한 책임소재 등을 강조하는 관료적 문화의 특성을 지니고 있다. 위계지향문화는 전통적인 관료제적 조직문화를 대표하며, 계층제적인 강력한 감독체계와 보편적인 서비스, 예측된 규범과 절차를 문화적 속성으로 하기 때문에 따라서 무엇보다 안정성과 통제에 대한 필요성과 조직 내부적 유지와 통합에 초점을 둔다.</p>
</blockquote>
<h3 id="과업지향-문화">과업지향 문화</h3>
<blockquote>
<p>과업지향문화는 합리문화(rational culture), 혹은 합리적 목적모형(rational goal model)이라고도 하며, 조직의 성과목표 달성과 과업 수행에 있어서의 생산성을 강조하는 문화유형이다. 이러한 문화적 특성이 지배적인 조직은 목표달성, 계획, 능률성, 성과 보상의 가치를 강조한다. 과업지향문화에서는 외부지향성의 관점에서 경쟁을, 성과통제의 관점에서 목표달성을 강조하며, 생산성과 능률성의 기준이 목표 달성에 있어 중요하다. 따라서 주로 공급자나 고객, 규제자 등 외부관계자와의 거래에 강조점을 두며, 경쟁력과 생산성이 핵심가치가 된다.</p>
</blockquote>
<h2 id="3-평가와-전망">3. 평가와 전망</h2>
<blockquote>
<p>지금까지의 조직문화 연구는 실제 조직의 다양하면서도 배타적인 요소들을 간과한 단선적인 접근에서 이루어져 왔다는 한계를 가지고 있다. 조직문화 연구에서 이러한 요소들을 모두 고려한 조직문화유형을 제시한 것은 퀸 등의 연구(Quinn &amp; Rohrbaugh, 1981: Quinn &amp; McGrath, 1985)가 대표적이다.
  특히 Quinn과 Kimberly(1984)의 조직문화유형으로 꼽히는, 관계지향문화, 혁신문화, 과업지향문화, 위계지향문화는 조직의 다양한 문화요소들을 포괄적인 시각을 포함하고 있다. 이러한 특징으로 인해 조직문화와 조직성과간의 역학관계 분석을 위해 지금도 많은 학자들이 이러한 문화유형을 연구 분석 틀로서 활용하고 있으며, 정부 및 행정조직에 대한 문화연구에 있어서도 이러한 연구 성향이 큰 영향을 미치고 있다.</p>
</blockquote>
<p>출처 <a href="https://blog.naver.com/wlgid0727/220059924304">https://blog.naver.com/wlgid0727/220059924304</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA['Web3' 란 무엇일까요?]]></title>
            <link>https://velog.io/@dev-april/Web3%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C%EC%9A%94</link>
            <guid>https://velog.io/@dev-april/Web3%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C%EC%9A%94</guid>
            <pubDate>Wed, 11 Oct 2023 15:32:12 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/dev-april/post/6572d625-405d-4bc7-be58-fd22bd9a0dd4/image.png" alt="">
출처 <a href="https://youyaa.com/web3-so-far-and-predictions/">https://youyaa.com/web3-so-far-and-predictions/</a></p>
<p>&quot;Web3&quot;는 블록체인, 특히 이더리움과 관련된 분산 웹 기술을 지칭하는 용어입니다. Web3는 일반적으로 인터넷의 세 번째 버전을 나타내며, 사용자와 개발자 모두에게 중앙 집중식 플랫폼의 제한을 극복할 수 있는 새로운 방법을 제공합니다.</p>
<h3 id="web3의-주요-특징">Web3의 주요 특징:</h3>
<ol>
<li><strong>분산 웹:</strong> 웹3는 사용자의 데이터를 중앙 서버가 아닌, 블록체인 네트워크에 저장합니다. 이로 인해 데이터의 소유권과 보안이 강화되며, 중앙 집중식 기관이나 정부의 통제를 받지 않습니다.</li>
<li><strong>스마트 컨트랙트:</strong> 스마트 컨트랙트는 자동 실행 코드로, 블록체인 상에서 동작합니다. 스마트 컨트랙트를 사용하면 사용자와 개발자는 투명하고 신뢰할 수 있는 거래를 할 수 있습니다.</li>
<li><strong>디지털 자산:</strong> 웹3에서는 크립토커런시, NFT(Non-Fungible Token) 등 다양한 형태의 디지털 자산을 사용할 수 있습니다.</li>
<li><strong>자율조직:</strong> DAO(Decentralized Autonomous Organization) 같은 개념이 도입되어 사용자들이 직접 플랫폼의 거버넌스에 참여하고 결정을 내릴 수 있습니다.</li>
</ol>
<h3 id="web3의-발전-단계">Web3의 발전 단계:</h3>
<ol>
<li><strong>Web1 (정적 웹):</strong> 웹의 초기 단계에서는 주로 텍스트와 이미지가 포함된 정적인 페이지만 제공되었습니다.</li>
<li><strong>Web2 (소셜 웹):</strong> 사용자가 콘텐츠를 생성하고 공유할 수 있는 플랫폼(예: 페이스북, 트위터 등)이 등장했습니다.</li>
<li><strong>Web3 (분산 웹):</strong> 블록체인 기술을 기반으로 사용자의 데이터 소유권과 투명성을 중시하는 인터넷의 새로운 형태입니다.</li>
</ol>
<p>Web3가 주목받는 이유 중 하나는 중앙 기관의 통제 없이 개인의 데이터 소유권과 보안을 강화할 수 있다는 점입니다. 그러나 이 기술도 완벽하지 않으며, 아직 많은 도전 과제와 문제점이 남아 있습니다. 신기술에 대한 대중의 이해와 수용, 기술적인 한계, 법률 및 규제의 불확실성 등이 그 예입니다.</p>
<hr>
<p>&quot;Web3&quot; or &quot;Web 3.0&quot; refers to a new paradigm for applications on the internet. It represents the third era of the web.</p>
<h3 id="web-evolution-overview">Web Evolution Overview:</h3>
<ol>
<li><strong>Web1 (The Static Web):</strong> The early web where content was read-only and static.</li>
<li><strong>Web2 (The Social Web):</strong> This era brought interactivity, social media, and user-generated content.</li>
<li><strong>Web3 (The Decentralized Web):</strong> The emerging era. It introduces decentralized protocols and technologies, enabling users to have control over their own data, identities, and transactions.</li>
</ol>
<h3 id="key-features-of-web3">Key Features of Web3:</h3>
<ul>
<li><strong>Decentralization:</strong> Web3 reduces reliance on central authorities or intermediaries, like tech giants or financial institutions. Decentralized networks, like blockchains, are a crucial part of this.</li>
<li><strong>Cryptography:</strong> Cryptographic techniques secure transactions and data, ensuring privacy and enabling things like cryptocurrencies.</li>
<li><strong>Smart Contracts:</strong> These are self-executing contracts with the terms written into code, facilitating, verifying, or enforcing credible transactions without third parties.</li>
<li><strong>Token Economy:</strong> Digital assets or tokens can represent ownership or value in various applications, incentivizing users and developers in the ecosystem.</li>
</ul>
<h3 id="web3-market-in-it-industry">Web3 Market in IT Industry:</h3>
<ol>
<li><strong>Blockchain &amp; Cryptocurrency Firms:</strong> Companies providing blockchain technology, cryptocurrency trading platforms, wallet services, etc.</li>
<li><strong>Decentralized Finance (DeFi):</strong> Services offering decentralized lending, borrowing, or trading financial instruments.</li>
<li><strong>Decentralized Autonomous Organizations (DAOs):</strong> Organizations run and managed by smart contracts and consensus among its members, rather than by a centralized authority.</li>
<li><strong>NFT Marketplaces:</strong> Platforms for creating, selling, and buying Non-Fungible Tokens, which represent ownership of unique items or content.</li>
<li><strong>DApps (Decentralized Applications):</strong> Applications that run on decentralized networks, often built using smart contracts.</li>
<li><strong>Infrastructure and Development Platforms:</strong> Companies providing tools, services, and infrastructure for developers to build and deploy Web3 applications.</li>
<li><strong>Identity &amp; Security Solutions:</strong> Services offering decentralized identity and security solutions for users and applications in the Web3 space.</li>
</ol>
<h3 id="market-impact">Market Impact:</h3>
<ul>
<li><strong>Investment Opportunities:</strong> The Web3 space has attracted significant investment from venture capitalists, individual investors, and corporations.</li>
<li><strong>Innovation &amp; Startups:</strong> There’s a surge in startups and projects focused on decentralized technologies, services, and platforms.</li>
<li><strong>Job Creation:</strong> New career opportunities and roles are emerging, including blockchain developers, smart contract engineers, and decentralized finance analysts.</li>
<li><strong>Challenges &amp; Risks:</strong> The space also faces challenges, like regulatory uncertainty, security concerns, and technology maturity and adoption issues.</li>
</ul>
<h3 id="conclusion">Conclusion:</h3>
<p>The Web3 market is dynamic and rapidly evolving, with many players entering the space and developing innovative solutions and services. As technologies mature and adoption grows, Web3 could substantially influence the IT industry and the broader economy, bringing about significant changes and opportunities.</p>
<hr>
<h2 id="web-30">Web 3.0</h2>
<blockquote>
<p>Though there are a number of differences between web 2.0 and web 3.0, at the heart of everything is decentralisation. Any issues surrounding security and monetisation would no longer be a problem due to the fact that web 3.0 is verifiable, self-governing and permissionless. Developers in web3 would not usually build apps that run on a single server or store information in a single database, instead, everything would become decentralised. 
</n>
Essentially, apps on web 3.0 would normally run using blockchain technology. This is the same kind of tech that helps to create cryptocurrency and as such, is completely decentralised. Cryptocurrency will also play a large role in these protocols as it will provide financial incentive to those who create decentralised apps and those who govern and improve them.
</n>
Thanks to the decentralised nature of web3, it would mean that organisations would no longer be able to retain data about what you do on the internet. Instead, once you log off, you would take your data with you. It means that web3 is not prone to the same security risks that come with the internet we are currently using. </p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[AI  네이버 블로그 수집]]></title>
            <link>https://velog.io/@dev-april/AI-%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%B8%94%EB%A1%9C%EA%B7%B8-%EC%88%98%EC%A7%91</link>
            <guid>https://velog.io/@dev-april/AI-%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%B8%94%EB%A1%9C%EA%B7%B8-%EC%88%98%EC%A7%91</guid>
            <pubDate>Wed, 04 Oct 2023 08:42:32 GMT</pubDate>
            <description><![CDATA[<h1 id="데이터셋-만들기">데이터셋 만들기</h1>
<p>데이터셋을 만들기 위해서는 데이터를 수집하고 레이블링할 필요가 있음</p>
<h2 id="머신-러닝">머신 러닝</h2>
<p>데이터가 적을때도 성능이 나온다</p>
<h2 id="딥러닝">딥러닝</h2>
<p>데이터가 많을때(수십, 수백억개) 성능이 잘 나옴</p>
<h1 id="데이터-수집">데이터 수집</h1>
<p>데이터를 수집할 때는 데이터가 편향되지 않도록 주의</p>
<h2 id="데이터-레이블링">데이터 레이블링</h2>
<ul>
<li><p>데이터 레이블링은 주관적인 판단이 필요하기 때문에, 다양한 이슈가 발생할 수 있음(주관성, 비용)</p>
</li>
<li><p>레이블링하기 복잡하거나 어려운 데이터면 비용은 더 커짐
(의료나 법률, 과학기술 등 복잡한 배경지식이 있어야 레이블링 할 수 있는 데이터)</p>
</li>
</ul>
<h2 id="자동화된-레이블링">자동화된 레이블링</h2>
<ul>
<li>레이블링의 여러 문제를 완화하기 위해서 머신러닝을 이용하여 데이터 레이블링을 자동화할 수도 있음</li>
<li>준지도 학습(Semi-supervised Learning) : 레이블링되지 않은 데이터와 레이블링 된 데이터를 함께 사용하여 모델을 학습시키는 방법</li>
</ul>
<p>새로 출시된 생성형 AI
<a href="https://www.bing.com/create">https://www.bing.com/create</a></p>
<h1 id="셀레늄">셀레늄</h1>
<ul>
<li>웹 브라우저 자동 제어를 위한 소프트웨어</li>
<li>웹 브라우저가  JavaScript 실행, 서버와 통신 등을 처리</li>
<li>직접 스크랩 할 경우 HTML만 전송하지만 웹 브라우저는 문서 내 모든 요소(이미지, 광고 등)를 다운로드 하므로 속도가 느릴 수 있음</li>
</ul>
<h2 id="라이브러리-설치">라이브러리 설치</h2>
<p>Colab에서는 크롬창이 안보이기 때문에 Jupyter Notebook을 사용하였다</p>
<h2 id="웹-드라이버-설치윈도-맥">웹 드라이버 설치(윈도, 맥)</h2>
<ol>
<li>크롬버전 확인: chrome://version
우상단 ... -&gt; 도움말 -&gt; Chrome 정보</li>
</ol>
<p>2.<a href="https://googlechromelabs.github.io/chrome-for-testing/">https://googlechromelabs.github.io/chrome-for-testing/</a>
방문</p>
<ol start="3">
<li>자기 운영체제에 맞는 압축 파일 주소를 주소창에 붙여넣기
<img src="https://velog.velcdn.com/images/dev-april/post/b8927252-a6ad-488c-afa8-7de118c9690f/image.png" alt=""></li>
</ol>
<h2 id="jupyter-lab-사용">Jupyter Lab 사용</h2>
<h3 id="설치">설치</h3>
<pre><code class="language-python">!pip install selenium</code></pre>
<h3 id="이-경로에-아까-다운받은-chromdrioverexe-폴더를-이동">이 경로에 아까 다운받은 chromdriover.exe 폴더를 이동</h3>
<pre><code class="language-python">import os
print(os.getcwd())</code></pre>
<p>C:\Users\AprilChoi</p>
<h3 id="import">import</h3>
<pre><code class="language-python">from selenium.webdriver import Chrome
from selenium.webdriver.chrome.service import Service

service = Service(executable_path=&#39;chromedriver.exe&#39;)
browser = Chrome(service=service)</code></pre>
<h3 id="데이터-수집-1">데이터 수집</h3>
<pre><code class="language-python">browser.get(&#39;https://blog.naver.com&#39;) # 네이버 블로그로 이동해라 

browser.current_url # 현재 실제 주소가 어떻게 되냐

from selenium.webdriver.common.by import By
elems = browser.find_elements(By.CSS_SELECTOR, &#39;a.link_naver&#39;)
elems

elem = elems[0]
elem.text

elem.get_attribute(&#39;href&#39;) # 네이버로고를 코드로 클릭할 수 있다

# 본인이 원하는 키워드 넣기
url = &#39;https://section.blog.naver.com/Search/Post.naver?pageNo={}&amp;keyword={}&#39;
browser.get(url.format(1, &#39;던스트&#39;)) 

# 제목 링크 찾기
elems = browser.find_elements(By.CSS_SELECTOR, &#39;a.desc_inner&#39;)

post_urls = []
for elem in elems:
    post_urls.append(elem.get_attribute(&#39;href&#39;))

post_urls</code></pre>
<h2 id="iframe">iframe</h2>
<p>한 페이지의 일부에 다른 웹페이지를 보여줌</p>
<h3 id="우클릭-허용-확장프로그램-설치후-사용">우클릭 허용 확장프로그램 설치후 사용</h3>
<p><a href="https://chrome.google.com/webstore/detail/enable-right-click-allow/mlloloooolpffjkjaclpfpeednngpjon/related?utm_source=ext_sidebar&amp;hl=ko">https://chrome.google.com/webstore/detail/enable-right-click-allow/mlloloooolpffjkjaclpfpeednngpjon/related?utm_source=ext_sidebar&amp;hl=ko</a></p>
<h2 id="블로그-내용-긁어오기">블로그 내용 긁어오기</h2>
<pre><code class="language-python"># id와 내용 뽑기
import re
post_url = post_urls[0]
m = re.match(r&#39;https://blog.naver.com/(\w+)/(\d+)&#39;, post_url) # 정규표현식 이용해서 뽑아내기
blog_id, log_no = m.groups()
frame_url = f&#39;https://blog.naver.com/PostView.naver?blogId={blog_id}&amp;logNo={log_no}&#39;

browser.get(frame_url)

browser.find_element(By.CSS_SELECTOR, &#39;div.se-main-container&#39;).text

# 주소 수집하기
import time
url = &#39;https://section.blog.naver.com/Search/Post.naver?pageNo={}&amp;keyword={}&#39;

post_urls = []

for page in range(1, 3): # 1~2페이지(3페이지 포함X)
    browser.get(url.format(page, &#39;던스트&#39;))
    time.sleep(3) # 3초간 대기
    elems = browser.find_elements(By.CSS_SELECTOR, &#39;a.desc_inner&#39;)
    for elem in elems:
        post_urls.append(elem.get_attribute(&#39;href&#39;))

post_urls

# 본문 수집하기
import re
import tqdm.auto as tqdm

texts = []
for post_url in tqdm.tqdm(post_urls):
    m = re.match(r&#39;https://blog.naver.com/(\w+)/(\d+)&#39;, post_url)
    blog_id, log_no = m.groups()
    frame_url = f&#39;https://blog.naver.com/PostView.naver?blogId={blog_id}&amp;logNo={log_no}&#39;

    browser.get(frame_url)
    time.sleep(3)
    texts.append(browser.find_element(By.CSS_SELECTOR, &#39;div.se-main-container&#39;).text)

# 엑셀파일로 저장하기
import pandas as pd
df = pd.DataFrame({&#39;url&#39;: post_urls, &#39;text&#39;: texts})
df.to_excel(&#39;blog.xlsx&#39;)    
</code></pre>
<p><img src="https://velog.velcdn.com/images/dev-april/post/e6462ba2-5530-4edf-b990-27ff5167455a/image.png" alt="">
코드로 &#39;던스트&#39; 검색
<img src="https://velog.velcdn.com/images/dev-april/post/985af7ae-1da8-41db-beb0-3d977002ebb7/image.png" alt="">
수집된 주소들
<img src="https://velog.velcdn.com/images/dev-april/post/90c8c45e-6176-4def-91ad-1710d55431b6/image.png" alt="">
엑셀 파일로 저장된 주소와 본문</p>
<p>Q. url = &#39;<a href="https://section.blog.naver.com/Search/Post.naver?pageNo=%7B%7D&amp;keyword=%7B%7D&#39;">https://section.blog.naver.com/Search/Post.naver?pageNo={}&amp;keyword={}&#39;</a>
이 주소는 어떻게 가져오신 건가요?</p>
<p>(1) 검색을 한다
그냥 네이버 블로그 홈에서 검색을 하면 아래와 같은 주소로 이동
<a href="https://section.blog.naver.com/Search/Post.naver?pageNo=1&amp;rangeType=ALL&amp;orderBy=sim&amp;keyword=%EB%8D%98%EC%8A%A4%ED%8A%B8">https://section.blog.naver.com/Search/Post.naver?pageNo=1&amp;rangeType=ALL&amp;orderBy=sim&amp;keyword=%EB%8D%98%EC%8A%A4%ED%8A%B8</a></p>
<p>(2) 포스트에 들어가서 본문을 가져온다
검색을 한 주소로 들어가면 그 블로그가 프레임으로 되어 있다
프레임 보기</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[express & nodemon 설치(복습)]]></title>
            <link>https://velog.io/@dev-april/express-nodemon-%EC%84%A4%EC%B9%98%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@dev-april/express-nodemon-%EC%84%A4%EC%B9%98%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Tue, 03 Oct 2023 13:47:18 GMT</pubDate>
            <description><![CDATA[<h1 id="express">express</h1>
<h2 id="설치">설치</h2>
<p><code>npm install express</code></p>
<h2 id="server-폴더-만들기">server 폴더 만들기</h2>
<p>sample-app &gt; src &gt; server</p>
<h2 id="appjs-혹은-serverjs-파일-만들기">app.js 혹은 server.js 파일 만들기</h2>
<p>파일명은 자유다</p>
<h2 id="import옛날-방식">import(옛날 방식)</h2>
<p>아직 최적화가 안되어있기 때문. 아마 요즘 문법으로 조만간 바뀔듯</p>
<pre><code class="language-jsx">const express = require(&#39;express&#39;);</code></pre>
<p>요즘 문법: </p>
<pre><code class="language-jsx">import express from &quot;express&quot;;</code></pre>
<h2 id="실행">실행</h2>
<p>터미널에
<code>node ./server/app</code>
app.js (.js는 생략 가능)</p>
<p>포트번호를 바꾸거나 하면 서버를 다시 켜야되기 때문에 불편...
그래서 nodemon을 설치한다</p>
<h1 id="nodemon">nodemon</h1>
<p>수정이 될 때마다 서버를 자동으로 재시작 해준다</p>
<h2 id="설치-1">설치</h2>
<p><code>npm install nodemon</code></p>
<p>만약 저 명령어로 설치가 안된다면 전역으로 설치
<code>npm install --global nodemon</code> </p>
<h2 id="실행-1">실행</h2>
<p><code>nodemon ./server.app</code></p>
<p>react - 3000번
nodemon - 3001번
그럼 동시에 실행을 시켜야되는데?</p>
<p>원래는 터미널을 한개 더 열어서 react/sample-app 가서
<code>npm start</code>
해서 서버를 켜줘야함</p>
<p>너무 불편하죠..?
그래서 동시에 실행해주려면 라이브러리가 있어야한다</p>
<h2 id="concurrently-설치">concurrently 설치</h2>
<p><code>npm install concurrently</code></p>
<h2 id="packagejson-가서-명령어-수정">package.json 가서 명령어 수정</h2>
<p>명령어 두개를 실행시키고 싶다</p>
<pre><code class="language-jsx">&quot;scripts&quot;: {
    &quot;abc&quot; : &quot;react-scripts start &amp;&amp; nodemon ./server/app&quot;,
       ...
},</code></pre>
<h2 id="저장-후-실행">저장 후 실행</h2>
<p><code>npm run abc</code></p>
<p>그런데 한 가지 아쉬운 점은 터미널을 봤을때
리액트쪽만 보인다.</p>
<h2 id="서버-종료ctrl--c후-수정">서버 종료(ctrl + c)후 수정</h2>
<p>둘 중에 하나라도 동작하지 않으면 꺼지게 수정</p>
<pre><code class="language-jsx">&quot;scripts&quot;: {
    &quot;abc&quot; : &quot;concurrently \&quot;react-scripts start\&quot; \&quot;nodemon ./server/app\&quot;&quot;,
         ...
},</code></pre>
<p><img src="https://velog.velcdn.com/images/dev-april/post/4b254477-5ffc-4524-a517-5c0e9741a382/image.png" alt="">
터미널을 보면
[1] 번 [nodemon]</p>
<p>[2] 번 리액트가 잘 실행된는 것을 확인 할 수 있다</p>
<p>아 근데 npm run abc 라고 치기 좀 불편한데..?
그냥 npm start 로 바꾸자</p>
<pre><code class="language-jsx">&quot;scripts&quot;: {
    &quot;server&quot; : &quot;nodemon ./server/app&quot;,
    &quot;client&quot; : &quot;react-scripts start&quot;,
    &quot;start&quot;: &quot;concurrently \&quot;npm run client\&quot; \&quot;npm run server\&quot;&quot;,
         ...
},</code></pre>
<h2 id="잘-실행되나-확인">잘 실행되나 확인</h2>
<p><img src="https://velog.velcdn.com/images/dev-april/post/7ad4bb16-d521-42bf-a33b-c5c16d2de11b/image.png" alt=""></p>
<p>잘 실행이 되는것을 확인 할 수 있다</p>
<p>이게 또 옵션을 줄 수가 있다</p>
<h2 id="옵션주기--kill-others-on-fail">옵션주기(--kill-others-on-fail)</h2>
<p>만약에 둘 중에 하나만 켜지면 둘다 실행하지 마라</p>
<pre><code class="language-jsx">&quot;scripts&quot;: {
    &quot;server&quot; : &quot;nodemon ./server/app&quot;,
    &quot;client&quot; : &quot;react-scripts start&quot;,
    &quot;start&quot;: &quot;concurrently --kill-others-on-fail \&quot;npm run client\&quot; \&quot;npm run server\&quot;&quot;,
      ...
}</code></pre>
<p>역시 복습을 해야 다시 정리가 되는구나...닝겐이란🐰</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[axios 사용 시 async & await(복습)]]></title>
            <link>https://velog.io/@dev-april/axios-%EC%82%AC%EC%9A%A9-%EC%8B%9C-async-%EC%99%80-await%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@dev-april/axios-%EC%82%AC%EC%9A%A9-%EC%8B%9C-async-%EC%99%80-await%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Tue, 03 Oct 2023 12:19:54 GMT</pubDate>
            <description><![CDATA[<h2 id="axios">axios</h2>
<h3 id="설치">설치</h3>
<p><code>npm install axios</code></p>
<h3 id="실행">실행</h3>
<p><code>npm start</code></p>
<h3 id="import">import</h3>
<p>우리가 만든게 아니고 설치한 라이브러리니까 꼭 import를 해줘야 한다</p>
<pre><code class="language-jsx">import axios from &quot;axios&quot;;</code></pre>
<h2 id="연습용-서버는-koreanjsoncom-사용">연습용 서버는 koreanjson.com 사용</h2>
<p><img src="https://velog.velcdn.com/images/dev-april/post/faaa6c7d-0dd1-49a3-b334-b86b536ff79f/image.png" alt="">
함수결과가 객체 라는것을 확인 할 수가 있다.
<img src="https://velog.velcdn.com/images/dev-april/post/de87dec1-3c72-4c5e-a9dd-1fc7d9a21d7c/image.png" alt="">
그런데 then 안쪽에 코드가 너무 길어지니까...</p>
<h3 id="pageajs">pageA.js</h3>
<pre><code class="language-jsx">import axios from &quot;axios&quot;;

const PageA = () =&gt;{

    const onButtonClick = ()=&gt;{
        // 서버에게 게시글 200개 가져다줘~!
        // 비동기 함수(5분 걸린다고 치자)
        axios.get(&#39;https://koreanjson.com/posts&#39;).then((res)=&gt;{ // get() 함수 실행결과를 매개변수 res에다 집어넣는것
            console.log(res);
        }).catch((err)=&gt;{
            console.log(&#39;오류가 발생함!&#39;);
        })
        console.log(&#39;안녕하세요&#39;);
    }

        // 가져온 게시글 보여줘(위가 끝나고 나야 가능)

        // 동기화 하기
        const asyncButtonClick = async ()=&gt;{
            try{
                let res = await axios.get(&#39;https://koreanjson.com/posts&#39;); // get() 함수 실행결과를 기다렸다가 res 라는 변수에다 집어넣는것(위아래 값 동일)
                console.log(res);
                console.log(&#39;안녕하세요&#39;);
            }catch(err){
                console.log(err);
                console.log(&#39;오류발생함&#39;);
            }
        }
        return(
            &lt;&gt;
                &lt;h1&gt;page A 입니다&lt;/h1&gt;
                &lt;button onClick={asyncButtonClick}&gt;async await 버튼&lt;/button&gt;
                &lt;button onClick={onButtonClick}&gt;클릭!&lt;/button&gt;
            &lt;/&gt;
        )
}

export default PageA;</code></pre>
<h3 id="여기서-한가지-문제점은">여기서 한가지 문제점은?</h3>
<p>1번 방법 axios.get(&#39;&#39;).then() 사용시 오류가 났을때는 어떻게하지??
정상적으로 실행이 되면 .then() 으로 잘 가는데
오류가 나면 catch로 잡아줘야 한다</p>
<h3 id="그럼-err-엔-뭐가-들어있을까">그럼 err 엔 뭐가 들어있을까?</h3>
<p>그 오류에 대한 정보가 객체로 들어있다
<img src="https://velog.velcdn.com/images/dev-april/post/d917d97c-7e58-4996-86a0-1c8040d91b30/image.png" alt=""></p>
<p>2번 방법을 사용할 때에도 try-catch 문법으로 오류가 발생할 수 있는 블록을 잡아줘야 한다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[react-router-dom 기본 동작 원리와 구조(복습)]]></title>
            <link>https://velog.io/@dev-april/react-router-dom-%EA%B8%B0%EB%B3%B8-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC%EC%99%80-%EA%B5%AC%EC%A1%B0%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@dev-april/react-router-dom-%EA%B8%B0%EB%B3%B8-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC%EC%99%80-%EA%B5%AC%EC%A1%B0%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Tue, 03 Oct 2023 10:35:04 GMT</pubDate>
            <description><![CDATA[<h2 id="1-react-폴더-생성">1. react 폴더 생성</h2>
<p><code>npx create-react-app sample-app</code></p>
<h2 id="2-불필요한-파일들-삭제-및-부분-삭제">2. 불필요한 파일들 삭제 및 부분 삭제</h2>
<p>sample-app&gt; src&gt;</p>
<p>App.css
logo.svg
reportWebVitals.js
setupTests.js 테스트할때 필요한거라 지금은 필요가 없다
App.js return() 안쪽 전체 삭제</p>
<pre><code class="language-jsx">function App() {
  return (

  );
}

export default App;</code></pre>
<p>index.js</p>
<pre><code class="language-jsx">import React from &#39;react&#39;;
import ReactDOM from &#39;react-dom/client&#39;;
import &#39;./index.css&#39;;
import App from &#39;./App&#39;;

const root = ReactDOM.createRoot(document.getElementById(&#39;root&#39;));
root.render(
    &lt;App /&gt;
);</code></pre>
<p>sample-app&gt; public&gt;
index.html 는 사용할껀데 주석처리된 부분은 필요가 없다
<noscript>, <link> 등등 다 삭제
이렇게만 남겨놓기</p>
<pre><code class="language-jsx">  &lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot; /&gt;
    &lt;link rel=&quot;icon&quot; href=&quot;%PUBLIC_URL%/favicon.ico&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
    &lt;meta name=&quot;theme-color&quot; content=&quot;#000000&quot; /&gt;

    &lt;title&gt;React App&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div id=&quot;root&quot;&gt;&lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>logo.png
manifest.json
robots.txt</p>
<h2 id="react-router-dom-설치">react-router-dom 설치</h2>
<p>폴더 이동 먼저하고 
<code>cd sample-app</code></p>
<p>여기다가 라이브러리 설치
<code>npm install react-router-dom</code></p>
<p>실행
<code>npm start</code></p>
<h2 id="appjs">App.js</h2>
<p>react-router-dom 으로 감싸기
그래야 어떤 주소로 가면 이 페이지를 그려줘~라고 설정 해놓을 수 있음</p>
<pre><code class="language-jsx">import {RouterProvider, createBrowserRouter} from &quot;react-router-dom&quot;;
import PageA from &quot;./pages/pageA&quot;; // import 자동으로 안되니 꼭 해주는게 중요!
import PageB from &quot;./pages/pageB&quot;;
import PageC from &quot;./pages/pageC&quot;;

const router = createBrowserRouter([
  {path:&#39;/&#39;, element:&lt;PageA/&gt;},
  {path:&#39;/b&#39;, element:&lt;PageB/&gt;},
  {path:&#39;/c&#39;, element:&lt;PageC/&gt;},
]);


function App() {
  return (
    &lt;RouterProvider router={router}/&gt;
  );
}

export default App;</code></pre>
<p>자 이제 페이지 만들러 ㄱㄱ</p>
<h2 id="페이지-생성">페이지 생성</h2>
<p>sample-app&gt; src&gt; pages 폴더 생성
sample-app&gt; src&gt; pages&gt; pageA 파일 생성</p>
<h3 id="pageajs">pageA.js</h3>
<pre><code class="language-jsx">const PageA = () =&gt;{
    return(
        &lt;&gt;
            &lt;h1&gt;page A 입니다&lt;/h1&gt;
        &lt;/&gt;
    )
}

export default PageA;</code></pre>
<h3 id="pagebjs">pageB.js</h3>
<pre><code class="language-jsx">const PageB = () =&gt;{
    return(
        &lt;&gt;
            &lt;h1&gt;page B 입니다&lt;/h1&gt;
        &lt;/&gt;
    )
}

export default PageB;</code></pre>
<h3 id="pagecjs">pageC.js</h3>
<pre><code class="language-jsx">const PageC = () =&gt;{
    return(
        &lt;&gt;
            &lt;h1&gt;page C 입니다&lt;/h1&gt;
        &lt;/&gt;
    )
}

export default PageC;</code></pre>
<p>이제 <a href="http://localhost:3000/">http://localhost:3000/</a> 를 브라우저 주소창에 쓰면 PageA가 잘 나오는것을 확인할 수 있다.
<img src="https://velog.velcdn.com/images/dev-april/post/5a72d542-7923-48bf-bc4c-b8672605ee26/image.png" alt=""></p>
<h1 id="react-기본-동작-원리">react 기본 동작 원리</h1>
<p><img src="https://velog.velcdn.com/images/dev-april/post/a5cd9d9c-37e7-4477-bd21-905fafe84b57/image.png" alt=""></p>
<p>RouterProvider 태그 안만 다시 그려진다
App 태그나 다른 RouterProvider 태그는 디자인을 안 입혀놨기때문에
실질적으로 우리 눈에 보이는건 h1 태그밖에 없다</p>
<p><em>컴포넌트가 그려졌을때 이 컴포넌트가 어떤 컴포넌트 안에 들어있는지 구조를 잘 파악하는게 중요하다</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JWT토큰 만들기🎫(Token, Session, Cookies)]]></title>
            <link>https://velog.io/@dev-april/JWS%EB%A1%9C-%ED%86%A0%ED%81%B0-%EB%A7%8C%EB%93%A4%EA%B8%B0token-Session-Cookies</link>
            <guid>https://velog.io/@dev-april/JWS%EB%A1%9C-%ED%86%A0%ED%81%B0-%EB%A7%8C%EB%93%A4%EA%B8%B0token-Session-Cookies</guid>
            <pubDate>Mon, 02 Oct 2023 14:06:16 GMT</pubDate>
            <description><![CDATA[<p>출처 <a href="https://brunch.co.kr/@jinyoungchoi95/1">https://brunch.co.kr/@jinyoungchoi95/1</a></p>
<h1 id="짚고-넘어가기">짚고 넘어가기</h1>
<h2 id="유효성-검사">유효성 검사</h2>
<p>이메일형식을 이렇게 지정해놨다면
<a href="mailto:ddd@naver.com">ddd@naver.com</a></p>
<p>유효성 검사를 통과했다 != 로그인에 성공했다
유효성 검사를 통과했다 =&gt; 이 값을 서버에 전달할 수 있겠다</p>
<p>react -&gt; express -&gt; mysql</p>
<p>값이 있을때 : 응답(200) 
값이 없을때 : 응답은 서버 만드는사람 마음대로(404나 오류 메세지)</p>
<hr>
<h1 id="로그인-성공시-로직">로그인 성공시 로직</h1>
<p>_로그인후 로그인한 사람의 정보가 있어야하는데...
어떻게? _</p>
<p>과거: express에 session이라는 저장공간을 만들어 저장해놨음
세션 id를 react 한테 줌
<img src="https://velog.velcdn.com/images/dev-april/post/c699cb52-b52c-4caf-8417-d3a2bb08d9b9/image.png" alt=""></p>
<p>게시글을 볼때 지금 로그인한 사람의 세션 id 까지 express에 전달.문제점: 사용자가 많아졌을땐 컴퓨터(서버) 한대로는 처리가 안됨..5대로 돌려야되는데 그럼 저장된 정보를 불러오는데 문제가 생김(서버간 세션 공유가 안되기 때문에)</p>
<p>그럼 데이터베이스는 하나니까 로그인한 사람의 정보를 DB에 저장을 해놓자! 한 가지 문제점?
데이터베이스도 여러개를 만들 수가 있다(scale out)
<em>그럼 로그인한 정보를 react가 가지고있음 되는거 아냐?</em></p>
<p><img src="https://velog.velcdn.com/images/dev-april/post/f0247c2f-010d-4bcd-beaf-648d2d14e092/image.png" alt=""></p>
<blockquote>
<p>로그인 성공했다는 의미로 증명서를 발급해줌(토큰)
자 여기 너가 가지고 있어하고 react에게 줌
react가 express에게 넘겨주면서
토큰 검사(유효하면 mysql가서 게시글 가져옴)를 함</p>
</blockquote>
<h2 id="리액트에서-로그인-요청위-내용-풀어쓰기">리액트에서 로그인 요청(위 내용 풀어쓰기)</h2>
<p>express는 mysql에서 해당 사용자 있는지 확인</p>
<p>사용자가 있다면 jwt 토큰 발급하여 react로 전달</p>
<p>react jwt토큰 저장해놓고
앞으로 로그인 한 사람만 접근할 수 있는 페이지가 있다면
jwt토큰을 함께 담아서 요청</p>
<p>express에서는 jwt토큰을 받아서, 토큰이 유효한지 검사하여
해당 토큰이 유효하면 응답하고,
유효하지 않으면 오류 발생(권한이 없습니다 로그인을 다시 해주세요!)</p>
<h1 id="토큰-만들기">토큰 만들기</h1>
<h2 id="jwtjson-web-token">JWT(JSON Web Token)</h2>
<p>잘 생각해보면 JS 객체에다 저장하는게 가장 편리함
객체를 암호화해서 토큰을 만들 수 있음</p>
<p><img src="https://velog.velcdn.com/images/dev-april/post/886ce156-9d00-4212-8c0f-a5d67b123bb7/image.png" alt=""></p>
<p>점을 기반으로 HEADER(어떤 방식으로 암호화를 했는지 ALGORITHM &amp; TOKEN TYPE 여러가지 정보들을 넣는 공간).PAYROAD(실질적으로 넣고싶은 DATA).VERIFY SIGNATURE(얘가 위조가 됐는지 안됐는지)</p>
<p>원래 비밀번호 암호화한것은 복호화가 불가능(단방향 암호화)
그런데 JWT는 복호화가 가능하다(절대 비밀번호 넣지 않는다)
누가 로그인했는지 알려면 주요 KEY값으로 EMAIL을 넣는다</p>
<h2 id="설치">설치</h2>
<p><code>npm install jsonwebtoken</code></p>
<h2 id="import">import</h2>
<pre><code class="language-jsx">const jwt = require(&quot;jsonwebtoken&quot;); // 옛날방식의 import</code></pre>
<h2 id="사용법">사용법</h2>
<p>1.Sign synchronous 동기적으로(차례대로)
sign()</p>
<p>2.Sign asynchronously 비동기적으로</p>
<p>1번 사용</p>
<p>jwt.sign( {DATA}, &#39;어떤 KEY를 가지고?(노출 XXX)&#39;, {OPTION-어떤 알고리즘으로?지속시간은?} )</p>
<p>let myToken = jwt.sign( {email:&#39;abc@naver.com&#39;}, &#39;tokenpw&#39;, {expiresIn:&#39;1h&#39;} )</p>
<p>&quot;iat&quot; : issued at
&quot;exp&quot; : expired</p>
<p>문제는 회원가입시 비밀번호가 DB에 bcrypt를 통해 암호화되서 들어감</p>
<h3 id="회원가입">회원가입</h3>
<p>리액트        mysql
<a href="mailto:ab@ab.com">ab@ab.com</a>    <a href="mailto:ab@ab.com">ab@ab.com</a>
123456        $2b$10$TcZOlfVlXOWfz.7XIuBW5u8wUKM0VS/C5UdZ082VITw.PiGlCpAfa</p>
<h3 id="로그인">로그인</h3>
<p><a href="mailto:ab@ab.com">ab@ab.com</a>
123456     -&gt; 암호화해서 회원가입할때 암호화된 애랑 비교하면 되지 않을까? bcrypt 는 보안이 철저해서 똑같이 암호화가 되지 않는다. </p>
<p><a href="mailto:ab@ab.com">ab@ab.com</a>이메일 가진 녀석을 찾아서
암호화된 비밀번호 가져오기
bcrypt(일반 비밀번호, 암호화 된 비밀번호)</p>
<p>비밀번호를 맞게쓰면 토큰이 나온다
<em>이 토큰을 변수에 저장하면 큰일나는 이유?
LoginPage 함수 안에 저장해봤자 다른 페이지로 이동하면 사라져버리기 때문에...
그래서 브라우저에 저장공간이 있다(local storage, Session storage, Cookies)</em></p>
<p>어떤걸 사용하든 본인의 취향 차이(보안쪽으로 가게되면 세세한 차이가 있다)</p>
<h2 id="전역-스테이트변수">전역 스테이트변수</h2>
<pre><code>state변수는 만들어져있는 컴포넌트 안에서밖에 사용을 못한다
token은 a컴포넌트, b컴포넌트, c컴포넌트에서 모두 사용을 해야하는데..?</code></pre><p>전역 스테이트변수는 스테이트변수는 스테이트변수인데
모든 컴포넌트에서 접근할 수 있는 스테이트변수를 의미한다</p>
<h3 id="전역스테이트변수-라이브러리">전역스테이트변수 라이브러리</h3>
<pre><code>redux, context api, ....</code></pre><h2 id="content-api">content api</h2>
<h3 id="1-context를-만든다">1. context를 만든다</h3>
<pre><code>createContext를 활용하여
ex)
    const ABC = createContext();</code></pre><h3 id="2-해당-내가-만든-context-provider를-활용하여">2. 해당 내가 만든 context provider를 활용하여</h3>
<pre><code>감싸준다(provider로 감싼 자식들에서는 모두 사용가능)

ex)
&lt;ABC.Provider&gt;
    이 안에 그려지는 자식 컴포넌트에서는 모두 값 접근가능
&lt;/ABC.Provider&gt;</code></pre><h3 id="3-이때-자식에서-사용할-수-있도록-하고-싶은-값들은">3. 이때 자식에서 사용할 수 있도록 하고 싶은 값들은</h3>
<pre><code>provider의 value에다 넘겨준다
ex)
    &lt;ABC.Provider value={ {a:값, b:값, c:값} }&gt;
        이 안에 그려지는 자식 컴포넌트에서는 모두
        {a:값, b:값, c:값} 값 접근가능
    &lt;/ABC.Provider&gt;</code></pre><p>궁금한게...
꼭 value라는 이름을 써야할까?
무조건 value = {} 에 들어있는 값만 사용가능</p>
<h3 id="4-자식-컴포넌트에서는-usecontext를-사용하여-어떤-context에서-어떤-값을-사용하고-싶은지-명시한다">4. 자식 컴포넌트에서는 useContext를 사용하여 어떤 context에서 어떤 값을 사용하고 싶은지 명시한다</h3>
<pre><code>ex)
    const value = useContext(ABC);
구조분해할당도 사용가능
    const {b, c} = useContext(ABC);</code></pre><h3 id="appjs">App.js</h3>
<p>전문이 너무 길어 추가된 부분만 명시 해놓았습니다.</p>
<pre><code class="language-jsx">import { createContext, useState } from &#39;react&#39;;

const router = createBrowserRouter([
  .
  .
  .
// 사용자에 대한 토큰 만들기
export const UserContext = createContext();

const App = ()=&gt;{
  // 전역에서 사용할 변수
  const [ accessToken, setAccessToken ] = useState(null);
  return (
    &lt;UserContext.Provider value={ { accessToken, setAccessToken } }&gt;
      &lt;RouterProvider router={router}/&gt;
    &lt;/UserContext.Provider&gt;
  );
}
</code></pre>
<h3 id="loginjs">login.js</h3>
<pre><code class="language-jsx">import { useContext, useState } from &quot;react&quot;;
import { useNavigate } from &quot;react-router-dom&quot;;
import axios from &quot;axios&quot;;
import { UserContext } from &quot;../../App&quot;;

const LoginPage = ()=&gt;{
   const navigate = useNavigate();

  // App.js에 있는 accessToken 변수와 setAccessToken함수 사용하기
  const {setAccessToken} = useContext(UserContext);
  .
  .
  .
  const onLoginSubmit = async (e)=&gt;{
if(check){
      // 로그인한 회원 조회
      try{
        let res = await axios.post(&#39;/api/login&#39;, {email, password});
        alert(res.data.accessToken);  // 비밀번호를 맞게쓰면 토큰이 나온다
        // 이 토큰을 변수에 저장하면 큰일나는 이유?
        // LoginPage 함수 안에 저장해봤자 다른 페이지로 이동하면 사라져버리기 때문에
        // 그래서 브라우저에 저장공간이 있다(local storage, Session storage, Cookies)
        localStorage.setItem(&#39;accessToken&#39;, res.data.accessToken);
        setAccessToken(res.data.accessToken);

        navigate(&#39;/&#39;, {replace:false}); // 뒤로가기 못하게
      }catch(err){
        console.log(err);
        if(err.response.status === 404){
          alert(&#39;아이디 또는 비밀번호를 확인해주세요&#39;);
        }</code></pre>
<h3 id="envlocal">.env.local</h3>
<pre><code class="language-jsx">JWT_SECRET=board23</code></pre>
<p>점점 어려워 지는구나<del>~</del>헤롱@_@</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[비동기 함수의 동기화 <async await 문법>]]></title>
            <link>https://velog.io/@dev-april/%EB%B9%84%EB%8F%99%EA%B8%B0-%ED%95%A8%EC%88%98%EB%A5%BC-%EB%8F%99%EA%B8%B0%EB%A1%9C-%EB%B0%94%EA%BE%B8%EA%B8%B0-async-await-%EB%AC%B8%EB%B2%95</link>
            <guid>https://velog.io/@dev-april/%EB%B9%84%EB%8F%99%EA%B8%B0-%ED%95%A8%EC%88%98%EB%A5%BC-%EB%8F%99%EA%B8%B0%EB%A1%9C-%EB%B0%94%EA%BE%B8%EA%B8%B0-async-await-%EB%AC%B8%EB%B2%95</guid>
            <pubDate>Wed, 27 Sep 2023 13:46:13 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/dev-april/post/5f21ff53-c7e5-4d6a-90f7-51e40f06e24f/image.png" alt="">
출처 <a href="https://www.boardinfinity.com/blog/javascript-async-and-await-function/">https://www.boardinfinity.com/blog/javascript-async-and-await-function/</a></p>
<h2 id="비동기함수">비동기함수</h2>
<pre><code>fetch
axios.get
axios.post
axios...

pool.query

보통 데이터를 갖고올때 오래걸리는 애들
우리가 생각할때 불편한 애들
순서가 위-&gt; 아래가 아니기때문에</code></pre><h2 id="async-await-문법-javascript">async await 문법 javaScript</h2>
<pre><code>비동기 함수를 동기 함수처럼 사용하고 싶어

비동기 함수 앞에 await를 사용하면 동기함수로 해석한다
await를 썼으면 await를 감싸고있는 함수를 async함수라고
알려줘야 한다!!</code></pre><p>가독성을 위해 메모를 코드 블럭 안에 넣어두었습니다.</p>
<pre><code class="language-jsx">    일반적인 함수
    async funtion 함수이름(){
        await
    }
    익명함수
    async function(){

    }

    화살표 함수
    async ()=&gt;{

    }

ex1)
console.log(&#39;코드1&#39;);
axios.get(&#39;ddd&#39;).then(()=&gt;{console.log(&#39;&#39;)}).catch(()=&gt;{});
console.log(&#39;코드3&#39;);

ex2)
pool.query(&#39;SELECT * FROM tmp&#39;, (err, result, fields)=&gt;{
    // 이 공간은 sql이 끝나고 동기적으로 실행되는 곳
    // err 에는 오류발생하면 err객체 안발생하면 null
    // result 에는 ? 정상적으로 끝나면 결과(배열, 객체)
        오류발생시 undefined
    // fields 에는 ? 정상적으로 끝나면 각 컬럼에 대한 정보
        오류발생시 혹은 SELECT 아닌경우 undefined
});
console.log(&#39;dd&#39;);

ex3)
axios.get(&#39;/users&#39;).then((res)=&gt;{
    // get함수가 정상적으로 끝났을때 실행되는 공간(동기적으로)
    // res 에는 객체(status, statusCode, statustext, data, ...)
}).catch((err)=&gt;{
    // get함수가 오류가 발생하면서 끝났을때 실행되는 공간(동기적으로)
    // err에는 에러 객체(에러정보, 에러이름, response, ... )
})

기존 동기함수가 비동기 함수라면??
예를 들어, 함수 중에 ceil이라는 함수가 있다고 가정 해보자.
let res = await ceil(3.5); // 다른거 먼저 하지말고 결과 나올때까지 기다리겠다.
console.log(res + 7);

컴퓨터
ceil(3.5) 아직 결과가 안나왔다면
let res = Promise 타입의 객체를 일단 넣어줌

완전 이거랑 똑같이 동작함
ceil(3.5).then((res)=&gt;{
    console.log(res + 7);
})

Q.이 함수를 어떻게 await로 변경할 수 있을까?
axios.get(&#39;/users&#39;).then((res)=&gt;{
    console.log(res);
})

let res = await axios.get(&#39;/users&#39;);
console.log(res);

그런데 한 가지 문제가 있다...만약 오류가 발생한다면?
catch가 실행되어야 하는데
만약 실행하다가 오류가 발생하면 어떻게 되요?
-&gt; try &amp; catch로 감싸주면 된다

try{
    let res = await axios.get(&#39;/users&#39;);
    console.log(res);
}catch(err){            // 오류가 발생했을때만 이쪽으로 넘어온다
    console.log(err);
}

ex4)
올림, 내림의 결과가 두개가 나온다
doubleMath(3.5).then(a, b)=&gt;{
    console.log(a); // a = 4
    console.log(b); // a = 3
}

let res = await doubleMath(3.5); --&gt; 배열로 [4, 3]
console.log(res[0]);
console.log(res[1]);

구조분해할당
let [a, b] = await doubleMath(3.5); --&gt; 배열로 [4, 3]
console.log(res[a]);
console.log(res[b]);

이걸 왜 해봤냐면...
pool.query(&#39;SELECT * from tmp&#39;, (err, result, fields)=&gt;{
    if(err !== null){
        console.log(err);
    }else{
        console.log(result);
        console.log(fields);
    }
})

정확히 얘기하면 성공했으면 결과가 2개 나온다
try{
    let [res, fields] = await pool.query(&#39;SELECT * from tmp&#39;); // [ , ]
    console.log(result);
    console.log(fields);
}catch(err){
    console.log(err);
}

뭐가 더 편하세요? 취향 차이ㅎㅎㅎ 선택해서 쓰세요~
대신 주의점!
함수 앞에 async 를 꼭 붙여준다!!

  async function(){

    }</code></pre>
<h2 id="비밀번호-암호화-시키기">비밀번호 암호화 시키기</h2>
<ol>
<li>설치
<code>npm install bcrypt</code></li>
<li>import
<code>const bcrypt = require(&#39;bcrypt&#39;);</code></li>
<li>사용
app.js 참고 <h3 id="appjs">app.js</h3>
<pre><code class="language-jsx">const express = require(&#39;express&#39;);
// import express from &quot;express&quot;; 요즘 문법과 동일한데 따로 뭘 깔아줘야 이걸 쓸 수 있음
// const bodyParser = require(&#39;bodyParser&#39;); 필요 없음
const mysql = require(&#39;mysql2/promise&#39;); // /promise 를 써줘야 async 실행 가능
// const cors = require(&#39;cors&#39;);
const bcrypt = require(&#39;bcrypt&#39;);
</code></pre>
</li>
</ol>
<p>// require(&#39;dotenv&#39;).config({path:&#39;../.env.local&#39;}); 아래와 동일함
const dotenv = require(&#39;dotenv&#39;);
dotenv.config({path:&#39;../.env.local&#39;});</p>
<p>console.log(process.env.DB_USER)</p>
<p>// mysql 설정</p>
<p>// 이걸 깃허브에 올린다고 생각해봐라...다 노출. 그래서 변수를 만들어야한다</p>
<p>const pool = mysql.createPool({
    host: process.env.DB_HOST,  // process 함수 안에 env 라는 key가 있는것
    user: process.env.DB_USER,
    database: process.env.DB_DATABASE,
    password: process.env.DB_PASSWORD,
    port:&#39;3306&#39;
});</p>
<p>const app = express();
const port = 3002;</p>
<p>// app.use(bodyParser().json()); 옛날방식
app.use(express.json());
app.use(express.urlencoded({extended : true}));</p>
<p>// app.use(cors({origin: &#39;<a href="http://localhost:3001&#39;%7D">http://localhost:3001&#39;}</a>));</p>
<p>app.get(&#39;/api&#39;, (req, res)=&gt;{
    res.send(&#39;성공했습니다!&#39;);
})</p>
<p>// 모든 사원 조회
app.get(&#39;/api/employees&#39;, (req, res)=&gt;{</p>
<pre><code>// mysql에서 employees 테이블 모든 행, 컬럼 조회
pool.query(&#39;select * from employees&#39;, (err, rows, fields)=&gt;{
    console.log(rows);
    // console.log(fields); 컬럼에 대한 정보라 실질적으로 잘 쓰지 않는다
    res.json(rows);
});

// res.json();</code></pre><p>});</p>
<p>// 사원 한명 추가
app.post(&#39;/api/employees&#39;, ()=&gt;{});</p>
<p>// 회원 한명 추가
app.post(&#39;/api/users&#39;, async (req, res)=&gt;{
    console.log(req.body);
    const sql =<code>INSERT INTO tbl_users
    (email, pw, question, answer)
    VALUES (?, ?, ?, ?)</code>;
    // 구조분해할당해서 넣어버려(이거 좀 어려워 보임)
    let {email, password, question, answer} = req.body;
    // 비밀번호 암호화 시키기
    let enPw = bcrypt.hashSync(password, 10);
    try{
    let [result, fields]= await pool.query(sql, [email, enPw, question, answer]);
        console.log(&#39;result&#39;, result);
        console.log(&#39;fields&#39;, fields);
        res.json(&#39;Success!!&#39;); // fetch함수는 res.json()
    }catch(err){
        if(err.errno === 1406){
            // 아이디가 컬럼의 최대 허용 용량을 벗어났다 1406
            // 회사마다 에러 넘버가 존재함
            res.status(400).json({errCode : 1, errMsg : &#39;아이디가 너무 김&#39;}); 
        }else if(err.errno === 1062){
        // 아이디가 중복되었다 1062
            res.status(400).json({errCode : 2, errMsg : &#39;아이디가 중복됨&#39;});
        }else{
        // 그외
        console.log(err);
            res.status(400).json({errCode : 3, errMsg: &#39;서버쪽에서 오류 발생함&#39;});
        }
    }
    // MySQL query 실행하기
    // pool.query(<code>INSERT INTO tbl_users
    // (email, pw, question, answer)
    // VALUES (?, ?, ?, ?)
    //</code>, [req.body.email, req.body.password, req.body.question, req.body.answer],
    //  (err, result, fields)=&gt;{
    //     if(err !== null){
    //         if(err.errno === 1406){
    //             // 아이디가 컬럼의 최대 허용 용량을 벗어났다 1406
    //             // 회사마다 에러 넘버가 존재함
    //             res.status(400).json({errCode : 1, errMsg : &#39;아이디가 너무 김&#39;}); 
    //         }else if(err.errno === 1062){
    //         // 아이디가 중복되었다 1062
    //             res.status(400).json({errCode : 2, errMsg : &#39;아이디가 중복됨&#39;});
    //         }else{
    //         // 그외
    //             res.status(400).json({errCode : 3, errMsg: &#39;서버쪽에서 오류 발생함&#39;});
    //         }
    //     }else{
    //         console.log(&#39;result&#39;, result);
    //         console.log(&#39;fields&#39;, fields);
    //         res.json(&#39;성공이야~!!&#39;); // fetch함수는 res.json()
    //     }
    // } 
    // );
    // res.redirect(&#39;/&#39;); 예전 백엔드 방식
    // 새로 넣을때 아까 er-error
});</p>
<p>app.listen(port, () =&gt;{console.log(<code>express 서버 실행됨! 포트:${port}</code>)});</p>
<pre><code>![](https://velog.velcdn.com/images/dev-april/post/d93d5ced-ecea-4816-9679-1ffd2f04e764/image.png)
회원 가입 버튼을 누르니 비밀번호가 잘 암호화되서 DB에 들어간 것을 확인할 수 있다🥰🥰

### join.js
```jsx
import { useState } from &quot;react&quot;;
import { AuthBody, AuthBox, AuthForm, BgImg, Button, CancelIcon, ErrMsg, Input, InputBoxWrap, Option, Select, Wrap } from &quot;../../styles/auth/auth.styles&quot;;
import CloseIcon from &#39;@mui/icons-material/Close&#39;;
import axios from &quot;axios&quot;;
import styled from &quot;@emotion/styled&quot;;
import { useNavigate } from &quot;react-router-dom&quot;;

const JoinPage = ()=&gt;{
    // 원래는 state 변수 9개 만들어야함...
    // 사용자가 email에 입력한 값
    const [email,setEmail] = useState(&#39;&#39;);
    const [password,setPassword] = useState(&#39;&#39;);
    const [passwordCheck ,setPasswordCheck] = useState(&#39;&#39;);
    const [question,setQuestion] = useState(1);
    const [answer,setAnswer] = useState(&#39;&#39;);

    const [emailErrMsg, setEmailErrMsg] = useState(&#39;&#39;);
    const [passwordErrMsg, setPasswordErrMsg] = useState(&#39;&#39;);
    const [PasswordCheckErrMsg, setPasswordCheckErrMsg] = useState(&#39;&#39;);
    const [answerErrMsg, setAnswerErrMsg] = useState(&#39;&#39;);


    // 모달창이 열려있는지 닫혀있는지 만들어줄 state변수
    const [isOpen, setIsOpen] = useState(false);

    // 페이지 이동 할때 사용하는 함수
    const navigate = useNavigate(); 


    const emailInputHandler = (e)=&gt;{
        setEmail(e.target.value);

        const emailText = e.target.value;

        if(emailText === &#39;&#39;){
            setEmailErrMsg(&#39;이메일은 필수 입력 값입니다.&#39;);
        }else if(!emailText.includes(&#39;@&#39;)){
            setEmailErrMsg(&#39;이메일 형식을 지켜주세요&#39;);
        }else{
            setEmailErrMsg(&#39;&#39;);
        }

    }

    const passwordInputHandler = (e)=&gt;{
        const passwordText = e.target.value;
        setPassword(passwordText);

        if(passwordText === &#39;&#39;){
            setPasswordErrMsg(&#39;비밀번호는 필수 입력 값입니다.&#39;);
        }else if(passwordText.length &lt; 6){
            setPasswordErrMsg(&#39;최소 6글자 이상으로 작성해주세요.&#39;);
        }else{
            setPasswordErrMsg(&#39;&#39;);
        }

        if(passwordText !== passwordCheck){
            setPasswordCheckErrMsg(&#39;비밀번호가 일치하지 않습니다.&#39;);
        } 


    }


    const passwordCheckInputHandler = (e)=&gt;{
        const passwordCheckText = e.target.value;
        setPasswordCheck(passwordCheckText);

        if(passwordCheckText ===&#39;&#39;){
            setPasswordCheckErrMsg(&#39;비밀번호 확인은 필수 입력 값입니다.&#39;);
        }else if(passwordCheckText !== password){
            setPasswordCheckErrMsg(&#39;비밀번호가 일치하지 않습니다.&#39;);
        }else{
            setPasswordCheckErrMsg(&#39;&#39;);
        }
    }

    const onSelectHandler = (e)=&gt;{
        // console.log(e.target);
        setQuestion(parseInt(e.target.value));
    }

    const onAnswerInputHandler = (e)=&gt;{
        setAnswer(e.target.value);
        if(e.target.value === &#39;&#39;){
            setAnswerErrMsg(&#39;이메일 찾기 응답은 필수 입력 값입니다&#39;);
        }else{
          setAnswerErrMsg(&#39;&#39;);
        }
    }

    const submitHandler = async (e)=&gt;{
      // submit Event가 발생하면 실행되는함수,
      // e에는 발생한 이벤트 객체가 대입이 된다.
      // e.preventDefault() 함수는 이벤트의 기본 동작을 막는 함수이고,
      // submit 이벤트의 기본 동작은 데이터를 전송하는 것이므로, 전송을 막는 것
      e.preventDefault();


      let check = true;

      // 이메일 input 태그 확인
      // state변수 email 확인
      if(email === &#39;&#39;){
        setEmailErrMsg(&#39;이메일은 필수 입력 값입니다.&#39;);
        check = false;
      }else if(!email.includes(&#39;@&#39;)){
        setEmailErrMsg(&#39;이메일 형식을 지켜주세요&#39;);
        check = false;
      }else{
        setEmailErrMsg(&#39;&#39;);
      }

      // 비밀번호 입력 확인
      // state변수 password 확인
      if(password === &#39;&#39;){
        setPasswordErrMsg(&#39;비밀번호는 필수 입력 값입니다.&#39;);
        check = false;
      }else if(password.length &lt; 6){
        setPasswordErrMsg(&#39;최소 6글자 이상으로 작성해주세요.&#39;);
        check = false;
      }else{
        setPasswordErrMsg(&#39;&#39;);
      }

      // 비밀번호 확인 입력 확인
      // state변수 passwordCheck 확인
      if(passwordCheck ===&#39;&#39;){
        setPasswordCheckErrMsg(&#39;비밀번호 확인은 필수 입력 값입니다.&#39;);
        check = false;
      }else if(passwordCheck !== password){
        setPasswordCheckErrMsg(&#39;비밀번호가 일치하지 않습니다.&#39;);
        check = false;
      }else{
        setPasswordCheckErrMsg(&#39;&#39;);
      }
      // 대답 입력 확인
      // state변수 answer 확인
      if(answer === &#39;&#39;){
        setAnswerErrMsg(&#39;이메일 찾기 응답은 필수 입력 값입니다&#39;);
        check = false;
      }else{
        setAnswerErrMsg(&#39;&#39;);
      }


      // 모든 값들이 정상적으로 입력되었다면
      // submit
      if(check){
        // alert(&#39;정상 입력됨!&#39;);
        // 서버로 전송!
        // console(e.target); // form 태그가 들어있음
        // e.target.submit();

        try{
          let res = await axios.post(&#39;/api/users&#39;, {email, password, question, answer})
          console.log(res)
          setIsOpen(true);
        }catch(err){
          console.log(err);
          if(err.response.data.errCode === 1){
            // alert(&#39;아이디가 너무 깁니다.&#39;);
            setEmailErrMsg(&#39;입력 항목에 너무 긴 항목이 있습니다.&#39;)
          }else if(err.response.data.errCode === 2){
            setEmailErrMsg(&#39;중복된 아이디가 존재합니다.&#39;)
          }else{
          alert(&#39;서버에 문제가 발생했습니다. 잠시 뒤에 다시 시도해주세요.&#39;);
          }
        }



        // axios는 비동기 함수
        // axios.post(&#39;/api/users&#39;, { 
        //   email, // email:email key와 value가 동일하면 생략가능
        //   password,
        //   question,
        //   answer
        // }).then((res)=&gt;{
        //   console.log(res)
        //   // 회원가입이 성공했다면 실행시킬 요소들
        //   // alert(&#39;회원가입 성공했습니다!&#39;);
        //   setIsOpen(true);
        // }).catch((err)=&gt;{
        //   console.log(err);
        //   // 회원가입이 실패했다면 실행시킬 코드
        //   if(err.response.data.errCode === 1){
        //     // alert(&#39;아이디가 너무 깁니다.&#39;);
        //     setEmailErrMsg(&#39;아이디가 너무 깁니다.&#39;)
        //   }else if(err.response.data.errCode === 2){
        //     setEmailErrMsg(&#39;중복된 아이디가 존재합니다.&#39;)
        //   }else{
        //   alert(&#39;서버에 문제가 발생했습니다. 잠시 뒤에 다시 시도해주세요.&#39;);
        //   }
        // });

        console.log(&#39;ddddd&#39;);
      }
    }

    // 모달창 버튼이 클릭되었을 때
    const onModalClick = ()=&gt;{
      // 로그인 페이지로 이동,
      // 페이지 이동시킬 때는 
      navigate(&#39;/login&#39;, {replace: true}); 
    }

  return(
    &lt;BgImg&gt;
      &lt;Wrap&gt;
        &lt;CancelIcon&gt;&lt;CloseIcon/&gt;&lt;/CancelIcon&gt;
        &lt;AuthBox&gt;
          &lt;h1&gt;회원가입&lt;/h1&gt;
          &lt;AuthBody&gt;
            &lt;AuthForm onSubmit={submitHandler} method=&quot;POST&quot; action=&quot;/api/users&quot;&gt;
              &lt;InputBoxWrap&gt;
                &lt;div className=&quot;input-box&quot;&gt;
                  &lt;Input name=&quot;email&quot; onChange={emailInputHandler} type=&quot;text&quot; placeholder=&quot;아이디&quot;/&gt;
                  &lt;ErrMsg&gt;{emailErrMsg}&lt;/ErrMsg&gt;
                &lt;/div&gt;
                &lt;div className=&quot;input-box&quot;&gt;
                  &lt;Input name=&quot;pw&quot; onChange={passwordInputHandler} type=&quot;password&quot; placeholder=&quot;비밀번호&quot;/&gt;
                  &lt;ErrMsg&gt;{passwordErrMsg}&lt;/ErrMsg&gt;
                &lt;/div&gt;
                &lt;div className=&quot;input-box&quot;&gt;
                  &lt;Input onChange={passwordCheckInputHandler} type=&quot;password&quot; placeholder=&quot;비밀번호 확인&quot;/&gt;
                  &lt;ErrMsg&gt;{PasswordCheckErrMsg}&lt;/ErrMsg&gt;
                &lt;/div&gt;
                &lt;div className=&quot;input-box&quot;&gt;
                  &lt;Select name=&quot;question&quot; onChange={onSelectHandler}&gt;
                    &lt;Option value={1}&gt;내가 태어난 곳은?&lt;/Option&gt;
                    &lt;Option value={2}&gt;어린시절 나의 별명은?&lt;/Option&gt;
                    &lt;Option value={3}&gt;나의 강아지 이름은?&lt;/Option&gt;
                  &lt;/Select&gt;
                  &lt;Input name=&quot;answer&quot; onChange={onAnswerInputHandler} type=&quot;text&quot; placeholder=&quot;이메일을 찾을 때의 질문에 답하세요&quot; /&gt;
                  &lt;ErrMsg&gt;{answerErrMsg}&lt;/ErrMsg&gt;
                &lt;/div&gt;
              &lt;/InputBoxWrap&gt;
              &lt;Button&gt;회원가입하기&lt;/Button&gt;
            &lt;/AuthForm&gt;
          &lt;/AuthBody&gt;
        &lt;/AuthBox&gt;
      &lt;/Wrap&gt;
      &lt;ModalWrap isOpen={isOpen}&gt;
        &lt;Modal&gt;
          &lt;h1&gt;성공!&lt;/h1&gt;
          &lt;p&gt;확인을 누르시면 로그인 페이지로 이동합니다&lt;/p&gt;
          &lt;button onClick={onModalClick}&gt;확인&lt;/button&gt;
        &lt;/Modal&gt;
      &lt;/ModalWrap&gt;
    &lt;/BgImg&gt;
  );
}

const ModalWrap = styled.div`

  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;

  background-color: rgba(0,0,0,0.8);
/* 조건부 렌더링 */
  display: ${ (props)=&gt;{return props.isOpen ? &#39;flex&#39; : &#39;none&#39;} };
  justify-content: center;
  align-items: center;
`;

const Modal = styled.div`
  width: 450px;
  background-color: white;
  border-radius: 16px;

  display: flex;
  flex-direction: column;

  align-items: center;
  padding: 30px;
`;

export default JoinPage;

</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[ChatGPT 잘 쓰는 방법]]></title>
            <link>https://velog.io/@dev-april/ChatGPT-%EC%9E%98-%EC%93%B0%EB%8A%94-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@dev-april/ChatGPT-%EC%9E%98-%EC%93%B0%EB%8A%94-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Mon, 25 Sep 2023 04:27:02 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/dev-april/post/789ecf87-9918-47b6-bd8b-e05791d3dd35/image.webp" alt="">
출처 <a href="https://bootcamp.uxdesign.cc/supercharging-your-product-design-workflow-with-chat-gpt-and-figma-8da99128b1ef">https://bootcamp.uxdesign.cc/supercharging-your-product-design-workflow-with-chat-gpt-and-figma-8da99128b1ef</a></p>
<h1 id="강화학습">강화학습</h1>
<p>환경과 상호작용하여 가장 많은 보상(&lt;-&gt;처벌)을 받는 행동을 학습</p>
<h2 id="생성형-aigenerative-ai">생성형 AI(generative AI)</h2>
<ul>
<li>텍스트, 이미지, 소리, 영상, 3D 모델 등 다양한 콘첸츠를 Y로 생성</li>
</ul>
<h2 id="chatgpt">ChatGPT</h2>
<ul>
<li>사실을 물어보면 안된다(검색 X). 그럴듯한 문장만 만들어낼뿐. 애초에 용도가 그렇지 않다.(casusal LM)</li>
</ul>
<p>Q. 그럼 chatGPT는 뭘 할 때 사용하는게 가장 좋을까요??</p>
<p>A. ex) 제주도 여행계획(존재하지 않는 장소를 추천해줄수 있음)
-&gt; 제주도 여행지 목록을 주고 제주도 여행계획을 짜라.
A 카페, B 카페, C 호텥, D 박물관 이 중에서 어디를 가면 좋을지 계획을 세워봐라.</p>
<ul>
<li><p>번역은 대체로 잘 해준다.
작동 방식은 ChatGPT, [빙 챗, 구글 바드, 클로바X] 다 똑같으나
괄호 안은 검색까지 해줌</p>
</li>
<li><p>환율 계산 -&gt; (1) 사실(현재 환율이 얼마다)을 알아야한다
(2) 언어 모델은 계산에 취약함</p>
</li>
<li><p>ChatGPT 자체는 그럴듯한 말을 지어낼 수 있음(프로그램도 포함)
파이썬은 내장되어있어 바로 실행 가능하나 자바는 코드를 짜주지만 실행은 내가 따로 복붙해서 해봐야 한다</p>
</li>
<li><p>현재 GPT4가 그럴듯한 말 만들기 측면의 성능은 가장 높음
(코딩도 포함)</p>
</li>
<li><p>ChatGPT 가 2021년까지 데이터로 언어를 구사할 수 있는 능력이 학습이 되어 있다</p>
</li>
</ul>
<p>여기서 학습 - &quot;그럴듯한 문장을 만드는 능력&quot; 간접적으로 사실도 학습
이 문제는 극복할 수도 없는 문제(극복할 필요도 없음)</p>
<p>모델 학습 -&gt; 파라미터를 조정하는 굉장히 길고 오래 걸리는 과정</p>
<p>언어 능력이 뛰어나다(한국말을 잘한다) != 한국어로 된 모든 지식을 가지고 있다</p>
<p>데이터 -&gt; ChatGPT의 파라미터를 추정하는 데 사용</p>
<h2 id="chatgpt-잘-쓸-수-있는-tip">ChatGPT 잘 쓸 수 있는 TIP</h2>
<p><em>: 영어로 쓴다ㅎㅎ</em></p>
<p>ChatGPT3.5 영어 - 70.1점짜리 대답
ChatGPT4 한국어 - 77점짜리 대답
ChatGPT4 영어 - 85.5점짜리 대답</p>
<h2 id="직업별-gpt-등-ai에-노출된-업무의-비율">직업별 GPT 등 AI에 노출된 업무의 비율</h2>
<ul>
<li>과학, 수학, 비판적 사고 등은 적게 노출</li>
<li>읽기, 쓰기, 프로그래밍 등은 많이 노출(말만 잘하면 되는 일)</li>
</ul>
<p>ex) 변호사 일장일단 - 내 일의 효율성이 높아질 수도 있고, 반대로 내 직업이 사라질 수도 있다</p>
<p>말빨만 끝내주게 좋은 애ㅋㅋㅋ
리서치를 맡긴다(X)</p>
<h2 id="언어-모형language-model">언어 모형(Language Model)</h2>
<ul>
<li>Casual LM: 앞의 문장을 바탕으로 다음에 나올 단어를 예측(GPT)</li>
<li>Masked LM: 앞뒤의 내용을 바탕으로 빈 칸의 단어를 예측(BERT)</li>
<li>프롬프트(prompt): 언어 모형에 제시하는 문장</li>
</ul>
<p>프롬프트 엔지니어링을 잘 하려면 사실 관계를 잘 알아서
프롬프트에 넣어줘야 함</p>
<h2 id="유용한-프롬프트-기법-사용">유용한 프롬프트 기법 사용</h2>
<ol>
<li>예시 들기</li>
<li>중요한 말 반복하기</li>
<li>짧게 짧게 말하기</li>
<li>단계적으로 나눠서 질문하기</li>
</ol>
<p>프라이빗 ChatGPT 출시 예정</p>
<ul>
<li>은행, 헬스케어, 대기업 등 개인정보 민감 대상 기업에서 사용</li>
<li>현재 가격의 10배 정도 $20 -&gt; $200</li>
</ul>
<p>수학문제를 잘 풀어주는 사이트
<a href="https://www.wolframalpha.com/">https://www.wolframalpha.com/</a></p>
<h3 id="플러그인">플러그인</h3>
<p>wolfram check 해두면  wolfram 한테 수학문제에 대한 답을 받아와서 답변을 해줌</p>
<h3 id="그-외에-chatgpt가-잘-못하는-것">그 외에 ChatGPT가 잘 못하는 것</h3>
<ul>
<li>수학</li>
<li>정확한 인용(외부 검색이 안됨)</li>
</ul>
<h3 id="최근-동향">최근 동향</h3>
<ul>
<li>ChatGPT를 하나의 구성 요소로 하는 더 큰 AI 시스템을 개발</li>
<li>LangChain 등</li>
</ul>
<hr>
<h1 id="chatgpt-프롬프트-쓰기">ChatGPT 프롬프트 쓰기</h1>
<h2 id="좋은-프롬프트의-요소">좋은 프롬프트의 요소</h2>
<ul>
<li>역할과 목표</li>
<li>단계별 지침</li>
<li>예시</li>
<li>개인화</li>
<li>제약 조건</li>
</ul>
<h2 id="1-역할과-목표">1. 역할과 목표</h2>
<ul>
<li>AI에게 특정한 역할이나 입장에서 작성하도록 지시
ex) 투자자의 입장에서 위의 보도자료에 대한 질문을 5개 만들어라.</li>
</ul>
<h2 id="2-단계별-지침chain-of-thoughts">2. 단계별 지침(Chain-of-Thoughts)</h2>
<ul>
<li>단계별로 명시적인 지침을 제공</li>
<li>let&#39;s think step by step 이라고 써도 비슷한 효과
ex) 베이글 카페 사업 계획을 세워봐라. 사업계획 수립 전에 어떤 간계를 거쳐 수립할건지 생각해봐. </li>
<li>Self-Consistency: 답변을 여러번 생성하여 가장 많이 나온 답변을 선택</li>
<li>Tree of Thoughts: 문제를 여러 개의 작은 문제로 나누게 해서 답변</li>
</ul>
<h2 id="3-개인화">3. 개인화</h2>
<ul>
<li>독자에 대한 정보를 제공하여 개인화된 답변을 생성
ex) 엔진오일에 대해 초등학생이 이해할 수 있게 1문단으로 설명해봐.</li>
</ul>
<h2 id="chatgpt에게-질문하기-하기">ChatGPT에게 질문하기 하기</h2>
<ul>
<li>ChatGPT를 잘 활용하기 어렵다면 ChatGPT에게 도움을 요청할 수 있음</li>
</ul>
<h2 id="목차-개요-만들기">목차, 개요 만들기</h2>
<ul>
<li>긴 텍스트 생성 작업 시 목차, 개요를 만든 후 구체적 내용을 만들어 나가는 방식이 유용
ex) 기업 임원들을 대상으로 ChatGPT에 대해 1시간짜리 강의를 한다. 강의 목차를 작성해. -&gt; 챕터 4를 작성하자. 현재 목차는 아래와 같다.</li>
</ul>
<h2 id="자료-검색">자료 검색</h2>
<ul>
<li>검색어 생성 기법</li>
<li>검색 플러그인 사용</li>
<li>AI 검색 엔진<ul>
<li>perplexity.ai</li>
<li>phind.com</li>
<li>you.com</li>
</ul>
</li>
</ul>
<h2 id="그룹화">그룹화</h2>
<ul>
<li>카테고리들을 더 상위의 카테고리로 묶어라</li>
</ul>
<h2 id="advanced-data-analysis">Advanced Data Analysis</h2>
<p>= code inerpreter</p>
<h2 id="토론">토론</h2>
<ul>
<li>혼자 여러가지 역할을 수행하게 할 수 있다</li>
</ul>
<h2 id="요약">요약</h2>
<p>사실 -&gt; 검색</p>
<p>계획, 의견, 추론, 생각, 아이디어 -&gt; GhatGPT 사용</p>
<p>ex) 위의 내용을 요약해서 표로 만들어라. 이런거 잘함ㅎㅎ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[🐼Express를 이용해 CRUD 하기(Read & Update편)]]></title>
            <link>https://velog.io/@dev-april/Express%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%B4-CRUD-%ED%95%98%EA%B8%B0Read-Update%ED%8E%B8</link>
            <guid>https://velog.io/@dev-april/Express%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%B4-CRUD-%ED%95%98%EA%B8%B0Read-Update%ED%8E%B8</guid>
            <pubDate>Thu, 21 Sep 2023 07:11:14 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/dev-april/post/05f44e1f-f62b-4a55-97a2-fae3ef775dd0/image.webp" alt="">
출처 <a href="https://morioh.com/a/4a5e054d3143/crud-operations-with-react-node-express-and-mongodb-a-complete-guide">https://morioh.com/a/4a5e054d3143/crud-operations-with-react-node-express-and-mongodb-a-complete-guide</a></p>
<p>mysql프로그램은 컴퓨터를 키면 바로 동작하고 있음(3306번 port)</p>
<p>express 3002번 port
react 3001번 port</p>
<h1 id="express와-react를-동시에-실행">express와 react를 동시에 실행?</h1>
<pre><code class="language-jsx">    concurrently 라이브러리 설치하여
    package.json에 start 명령어를 둘 다 실행할 수 있도록 설정하여
    npm start를 하면 동시에 서버와 클라이언트가 켜지게 설정

    같은 컴퓨터 안에서 서로 다른 프로그램이
    다른 포트에서 동작하는 프로그램에 접근을 하려면
    CORS 정책을 수정해줘야 한다.</code></pre>
<h2 id="a-클라이언트쪽에서-설정">A. 클라이언트쪽에서 설정</h2>
<pre><code class="language-jsx">    http-proxy-middleware
    라는 라이브러리를 설치

    setupProxy.js 파일을 만들고,
    주소 끝에 &#39;/api&#39; 로 끝나면
    서버 포트쪽으로 보내게 설정을 만들어준다
    localhost:3001/api 로 get
    실질적으로는
    localhost:3002/api 로 get 요청이 가버린다
    --&gt; react에서는 주소 끝을 api로 끝나는 주소는 사용할 수 없다</code></pre>
<p>저는 A 방법을 사용하였습니다.</p>
<h3 id="setupproxyjs">setupProxy.js</h3>
<pre><code class="language-jsx">const {createProxyMiddleware} = require(&#39;http-proxy-middleware&#39;);


module.exports = function(app){
    app.use(
        createProxyMiddleware(&#39;/api&#39;, {
            target: &#39;http://localhost:3002&#39;,
            changeOrigin:true
        })
    )
}</code></pre>
<h2 id="b-서버쪽에서-설정express-파일에서-설정하는-방법">B. 서버쪽에서 설정(express 파일에서 설정하는 방법)</h2>
<pre><code class="language-jsx">    cors 라이브러리를 설치한다
    npm install cors

    app.use(cors({origin: &#39;http://localhost:3001&#39;}));

    해당 코드 한줄 추가
    (3001번포트 허용하겠다는 의미)

    리액트에서는 요청할 때
    localhost:3002 get요청 직접적으로 해도 상관없음

    express                    react axios
    res.json(&#39;배상엽&#39;)      --&gt;    res.data에 &#39;배상엽&#39;이 들어있음
    res.json(10)        --&gt;    res.data에 10이 들어있음
    res.json([1,2,3])   --&gt;    res.data에 [1,2,3]이 들어있음</code></pre>
<h3 id="1-필요한-library들-설치-후-packagejson에서-dependencies-확인하기">1. 필요한 library들 설치 후 package.json에서 &quot;dependencies&quot; 확인하기</h3>
<p>npm install concurrently --save</p>
<blockquote>
<p>concurrently는 JavaScript 프로젝트에서 여러 개의 명령어를 병렬로 실행하도록 도와주는 패키지입니다. (ChatGPT)</p>
</blockquote>
<p>npm install http-proxy-middleware --save</p>
<blockquote>
<p>설치가 완료되면 해당 패키지를 require 또는 import 문을 사용하여 JavaScript 코드에서 사용할 수 있습니다. 이 패키지를 사용하면 웹 서버에서 HTTP 프록시를 설정하는 데 도움이 되며, 다른 서버로 요청을 전달하거나 경로를 리라우팅할 수 있습니다. (ChatGPT)</p>
</blockquote>
<p>npm install mysql2 --save</p>
<h3 id="2-scripts-에-명령어-재정의해서-포트-두개-열기">2. &quot;scripts&quot; 에 명령어 재정의해서 포트 두개 열기</h3>
<pre><code class="language-jsx"> &quot;scripts&quot;: {
    &quot;client&quot;: &quot;set PORT=3001 &amp;&amp; react-scripts start&quot;,
    &quot;server&quot;: &quot;cd server &amp;&amp; nodemon app&quot;,
    &quot;start&quot;: &quot;concurrently --kill-others-on-fail \&quot;npm run server\&quot; \&quot;npm run client\&quot;&quot;,
    &quot;build&quot;: &quot;react-scripts build&quot;,
    &quot;test&quot;: &quot;react-scripts test&quot;,
    &quot;eject&quot;: &quot;react-scripts eject&quot;
  },</code></pre>
<h3 id="packagejson">package.json</h3>
<pre><code class="language-jsx">{
  &quot;name&quot;: &quot;test&quot;,
  &quot;version&quot;: &quot;0.1.0&quot;,
  &quot;private&quot;: true,
  &quot;dependencies&quot;: {
    &quot;@emotion/react&quot;: &quot;^11.11.1&quot;,
    &quot;@emotion/styled&quot;: &quot;^11.11.0&quot;,
    &quot;@mui/icons-material&quot;: &quot;^5.14.3&quot;,
    &quot;@mui/material&quot;: &quot;^5.14.5&quot;,
    &quot;@testing-library/jest-dom&quot;: &quot;^5.17.0&quot;,
    &quot;@testing-library/react&quot;: &quot;^13.4.0&quot;,
    &quot;@testing-library/user-event&quot;: &quot;^13.5.0&quot;,
    &quot;axios&quot;: &quot;^1.5.0&quot;,
    &quot;concurrently&quot;: &quot;^8.2.1&quot;,
    &quot;express&quot;: &quot;^4.18.2&quot;,
    &quot;http-proxy-middleware&quot;: &quot;^2.0.6&quot;,
    &quot;mysql2&quot;: &quot;^3.6.1&quot;,
    &quot;nodemon&quot;: &quot;^3.0.1&quot;,
    &quot;react&quot;: &quot;^18.2.0&quot;,
    &quot;react-dom&quot;: &quot;^18.2.0&quot;,
    &quot;react-router-dom&quot;: &quot;^6.15.0&quot;,
    &quot;react-scripts&quot;: &quot;5.0.1&quot;,
    &quot;web-vitals&quot;: &quot;^2.1.4&quot;
  },
  &quot;scripts&quot;: {
    &quot;client&quot;: &quot;set PORT=3001 &amp;&amp; react-scripts start&quot;,
    &quot;server&quot;: &quot;cd server &amp;&amp; nodemon app&quot;,
    &quot;start&quot;: &quot;concurrently --kill-others-on-fail \&quot;npm run server\&quot; \&quot;npm run client\&quot;&quot;,
    &quot;build&quot;: &quot;react-scripts build&quot;,
    &quot;test&quot;: &quot;react-scripts test&quot;,
    &quot;eject&quot;: &quot;react-scripts eject&quot;
  },
  &quot;eslintConfig&quot;: {
    &quot;extends&quot;: [
      &quot;react-app&quot;,
      &quot;react-app/jest&quot;
    ]
  },
  &quot;browserslist&quot;: {
    &quot;production&quot;: [
      &quot;&gt;0.2%&quot;,
      &quot;not dead&quot;,
      &quot;not op_mini all&quot;
    ],
    &quot;development&quot;: [
      &quot;last 1 chrome version&quot;,
      &quot;last 1 firefox version&quot;,
      &quot;last 1 safari version&quot;
    ]
  }
}
</code></pre>
<h3 id="appjs">app.js</h3>
<pre><code class="language-jsx">const express = require(&#39;express&#39;);
// import express from &quot;express&quot;; 요즘 문법과 동일한데 따로 뭘 깔아줘야 이걸 쓸 수 있음
const mysql = require(&#39;mysql2&#39;);
// const cors = require(&#39;cors&#39;);

// mysql 설정
const pool = mysql.createPool({
    host:&#39;localhost&#39;,
    user:&#39;user&#39;,
    database:&#39;board&#39;,
    password:&#39;1111&#39;,
    port:&#39;3306&#39;
});



const app = express();
const port = 3002;

// app.use(cors({origin: &#39;http://localhost:3001&#39;}));

app.get(&#39;/api&#39;, (req, res)=&gt;{
    res.send(&#39;성공했습니다!&#39;);
})

// 모든 사원 조회
app.get(&#39;/api/employees&#39;, (req, res)=&gt;{

    // mysql에서 employees 테이블 모든 행, 컬럼 조회
    pool.query(&#39;select * from employees&#39;, (err, rows, fields)=&gt;{
        console.log(rows);
        // console.log(fields); 컬럼에 대한 정보라 실질적으로 잘 쓰지 않는다
        res.json(rows);
    });

    // res.json();
});

// 사원 한명 추가
app.post(&#39;/api/employees&#39;, ()=&gt;{});

app.listen(port, () =&gt;{console.log(`express 서버 실행됨! 포트:${port}`)});
</code></pre>
<h3 id="expresstestjs">expressTest.js</h3>
<pre><code class="language-jsx">import axios from &quot;axios&quot;;
import { useRef, useState } from &quot;react&quot;;

const ExpressTestPage = ()=&gt;{

    const [employees, setEmployees] = useState([]);

    const onExpressClick = ()=&gt;{
        axios.get(&#39;/api&#39;)
        .then((res)=&gt;{
            console.log(&#39;.응답 받아옴!!&#39;, res);
        }).catch((err)=&gt;{ console.log(&#39;실패!!&#39;, err)});
    }

    const getEmployees = ()=&gt;{
        axios.get(&#39;/api/employees&#39;).then((res)=&gt;{
            console.log(res.data);
            setEmployees(res.data);
        }).catch((err)=&gt;{console.log(err)});
    }

    const fetchEmployees =()=&gt;{
        fetch(&#39;/api/employees&#39;)
            .then((res)=&gt;{return res.json})
            .then((data)=&gt;{console.log(data)})
            .catch((err)=&gt;{console.log(err)});
    }

    const empNameRef = useRef(null); // 초기값을 넣어둔다

    const addEmp= ()=&gt;{
        // document.querySelector(&#39;#emp_name&#39;)
        // document.querySelector를 통해 태그를 가져오는 것이 아닌
        // Ref 객체를 통해 태그를 가져온다
        console.log(empNameRef.current.value);
    }

    return(
        &lt;&gt;
            &lt;h1&gt;입력&lt;/h1&gt;
            &lt;label&gt;
                사원이름
                &lt;input ref={empNameRef} id=&quot;emp_name&quot;/&gt;
            &lt;/label&gt;
            &lt;label&gt;
                사원 봉급
                &lt;input id=&quot;salary&quot;/&gt;
            &lt;/label&gt;
            &lt;button onClick={addEmp}&gt;추가 하기&lt;/button&gt;

            &lt;h1&gt;사원목록&lt;/h1&gt;
            {employees.map((e)=&gt;&lt;div key={e.id}&gt;사원이름 : {e.emp_name}, 사원번호 : {e.id}, 봉급 : {e.salary}&lt;/div&gt;)}
            {/* &lt;div&gt;사원이름: 홍길동, 사원번호: 1, 봉급: 1000&lt;/div&gt;
            &lt;div&gt;사원이름: 홍길동, 사원번호: 1, 봉급: 1000&lt;/div&gt;
            &lt;div&gt;사원이름: 홍길동, 사원번호: 1, 봉급: 1000&lt;/div&gt;
            &lt;div&gt;사원이름: 홍길동, 사원번호: 1, 봉급: 1000&lt;/div&gt;
            &lt;div&gt;사원이름: 홍길동, 사원번호: 1, 봉급: 1000&lt;/div&gt; */}
            &lt;h1&gt;익스프레스 통신 테스트 페이지 입니다!&lt;/h1&gt;
            &lt;button onClick={onExpressClick}&gt;버튼입니다!&lt;/button&gt;
            &lt;button onClick={getEmployees}&gt;mysql에서 가져와 보겠습니다&lt;/button&gt;
            &lt;button onClick={fetchEmployees}&gt;fetch로 모든 직원 정보보기&lt;/button&gt;
        &lt;/&gt;
    );
}

export default ExpressTestPage;</code></pre>
<p><img src="https://velog.velcdn.com/images/dev-april/post/bd2ef05b-b80e-40b6-a2d5-abe9d4174480/image.png" alt="">
나의 희망 봉급이다...ㅋㅋㅋ
<img src="https://velog.velcdn.com/images/dev-april/post/491718fa-938f-4981-a118-9b448808f5a1/image.png" alt="">
응답을 잘 받아오는것을 볼 수 있다.</p>
<p>IntelliJ 와 Oracle을 이용해서 CRUD를 해봤었는데(백엔드)...
프론트엔드 만으로도 이게 가능해지다니 너무 신기하고 더 간편한것 같다🥰🥰🥰</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Machine Learning vs Deep Learning 09-19]]></title>
            <link>https://velog.io/@dev-april/%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D%EA%B3%BC-%EB%94%A5%EB%9F%AC%EB%8B%9D</link>
            <guid>https://velog.io/@dev-april/%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D%EA%B3%BC-%EB%94%A5%EB%9F%AC%EB%8B%9D</guid>
            <pubDate>Tue, 19 Sep 2023 07:19:24 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/dev-april/post/8853c673-2a8b-4ac1-89b1-d8b9a10e121d/image.png" alt="">
출처 <a href="https://www.linkedin.com/pulse/artificial-intelligence-ai-vs-machine-learning-deep-natarajan-siva">https://www.linkedin.com/pulse/artificial-intelligence-ai-vs-machine-learning-deep-natarajan-siva</a></p>
<h2 id="머신-러닝machine-learning">머신 러닝(Machine Learning)</h2>
<ul>
<li><p>통계적/ 수학적 기법으로 모형을 설계</p>
</li>
<li><p>컴퓨터가 모형을 바탕으로 데이터로부터 학습
ex) y = ax + b (회기분석)</p>
</li>
<li><p>학습의 형태(사용도%)</p>
<ul>
<li><p>지도 학습(90%):x와 y가 짝지어진 형태의 데이터에서 관계를 학습</p>
</li>
<li><p>비지도학습(9%) 데이터의 내재적 구조를 학습
ex) Big5 성격 척도 OCEAN(개방, 성실성, 외향성, 친화성, 신경성)
  MBTI 에 빠져있는 것(신경성)</p>
</li>
<li><p>강화학습(1%) 환경과 상호작용하여 가장 많은 보상을 받는 행동을 학습
ex) 알파고가 바둑을 둘 때(게임엔 승, 패가 있다)
알파고A vs 알파고B
실제로 많이 쓰진 않는다(수천만번의 강화학습을 하기엔 현실적으로 어렵기 때문에)</p>
</li>
</ul>
</li>
</ul>
<h2 id="지도-학습-supervised-learning">지도 학습 (Supervised Learning)</h2>
<ul>
<li>머신 러닝의 90% 이상을 차지하는 학습 형태
  ex) 개인의 금융 생활 정보(x) -&gt; 대출 상환 가능성(y)<pre><code>  지원자의 자기소개서(x) -&gt; 입사 후 인사평가 점수(y)</code></pre></li>
</ul>
<h2 id="뉴런-neuron">뉴런 (neuron)</h2>
<ul>
<li>동물의 신경계를 구성하는 신경 세포</li>
<li>흥분하면 전기 신호가 발생</li>
<li>신경 전달 물질을 사용하여 세포 간 통신</li>
</ul>
<h2 id="인공신경망-artificial-neural-network">인공신경망 (artificial neural network)</h2>
<ul>
<li>생물학적 신경망에서 영감을 받은 머신러닝 모델</li>
<li>인공 뉴런은 입력값을 가중합하고, 그 결과에 활성화 함수를 적용하여 출력</li>
<li>인공 뉴런은 로지스틱 회귀분석과 (거의) 같음</li>
<li>다층 신경망: 뉴런들로 이뤄진 층(layer)을 만들고, 이것을 여러 층으로 쌓은 것
→ 딥러닝으로 발전</li>
<li>보편근사정리: 충분히 큰 다층신경망은 어떤 함수도 모방할 수 있음</li>
</ul>
<h2 id="딥러닝-이전과-이후의-특징-추출">딥러닝 이전과 이후의 특징 추출</h2>
<ul>
<li>딥러닝 이전에는 과제 특성에 맞게 여러 단계의 처리 과정을 거쳐 특징을 추출</li>
<li>종단간 학습(end to end leaning): 딥러닝에서는 원 데이터를 거의 그대로 입력하여 원하는 출력을 얻음</li>
<li>표상 학습(representation learning): 신경망이 과제를 수행하는데 적합한 특징들을 내부적으로 학습</li>
</ul>
<h2 id="인간과-기계의-학습-방법의-차이">인간과 기계의 학습 방법의 차이</h2>
<ul>
<li>스스로 생각하는 존재 인격화된 존재라는 통념</li>
<li>인간은 소량의 데이터나 심지어 데이터 없이도 학습이 가능하나 인공지능은 대량의 데이터가 필요 (cf. Zero Shot Learning)</li>
<li>인공지능은 좁은 범위의 문제에만 학습이 가능 전이(transfer) 가 어려움</li>
</ul>
<h2 id="티처블-머신-teachable-machine">티처블 머신 (teachable machine)</h2>
<ul>
<li>구글이 제공하는 무료 No Code 머신러닝 플랫폼</li>
<li><a href="https://teachablemachine.withgoogle.com/">https://teachablemachine.withgoogle.com/</a>
재밌네 이거..ㅎㅎㅎ
핵심: 다양하고 많은 데이터가 있어야한다</li>
</ul>
<h1 id="딥러닝-프레임워크">딥러닝 프레임워크</h1>
<h2 id="넘파이-numpy">넘파이 (numpy)</h2>
<ul>
<li>고성능 수치 연산을 위한 라이브러리</li>
<li>머신러닝, 데이터 분석의 기반</li>
<li>싱글 코어에 최적화, 병렬 처리는 안됨</li>
<li>딥러닝에는 직접 사용되지 않으나, 사용법이 호환됨</li>
</ul>
<h2 id="판다스-pandas">판다스 (pandas)</h2>
<ul>
<li>표 형태의 데이터에 대한 불러오기, 저장, 정렬, 필터링 등의 기능을 제공</li>
</ul>
<h2 id="사이킷런-scikit-learn">사이킷런 (scikit learn)</h2>
<ul>
<li>머신러닝 라이브러리</li>
<li>딥러닝을 제외한 머신러닝 전 과정의 기능을 제공</li>
<li>대부분의 머신러닝 라이브러리들이 사이킷런과 호환</li>
</ul>
<h2 id="gpu">GPU</h2>
<ul>
<li>컴퓨터에서 일반적인 계산은 중앙처리장치 CPU라고 하는 칩에서</li>
<li>딥러닝에서는 여기에 더해 GPU라는 칩을 사용(성능은 적어도 갯수로 밀어붙이는 것)</li>
<li>GPU(그래픽 처리 장치): 원래는 게임 등에서 컴퓨터 그래픽을 처리하는데 특화된 장치<ul>
<li>GPU는 대량의 _단순 계산_을 병렬로 실행</li>
<li>여러 가지 계산을 순서대로 하는 것이 아니라 따로 따로 계산한 다음에 합칠 수 있음</li>
<li>GPU는 수천 개의 작업을 동시에 수행</li>
</ul>
</li>
<li>CPU는 병렬 처리에 최적화되어 있지 않으며 처리 능력이 제한<ul>
<li>CPU의 사양을 보면 코어 →쉽게 생각하면 코어 하나가 한 번에 한 가지 계산</li>
<li>개인용 PC에서 CPU에 있는 코어 개수는 많아야 열 몇 개 수준</li>
</ul>
</li>
<li>최신 GPUGPU에는 몇 만 개의 코어</li>
<li>그래픽도 딥러닝과 같이 단순 계산이 많음<ul>
<li>동시에 여러 가지 계산을 할 수 있는 GPUGPU를 활용하면 높은 성능을 낼 수 있음</li>
</ul>
</li>
</ul>
<h1 id="딥러닝-프레임워크-1">딥러닝 프레임워크</h1>
<ul>
<li>GPU 지원 + 딥러닝 모델을 정의하고 학습시키는데 필요한 다양한 기능들을 제공</li>
</ul>
<h2 id="텐서플로-tensorflow">텐서플로 (TensorFlow)</h2>
<ul>
<li>구글이 개발</li>
<li>가장 높은 점유율</li>
<li>기업용 기능이 많음<h2 id="파이토치-pytorch---meta로-변경">파이토치 (PyTorch) -&gt; Meta로 변경</h2>
</li>
<li>페이스북이 개발</li>
<li>새로운 모형을 만들기 편리하여 학계에서 인기<h2 id="작스-jax">작스 (jax)</h2>
</li>
<li>전문가용</li>
<li>다양한 수학 계산을 최적화하여 빠르게 실행하는데 초점(속도)</li>
<li>딥러닝도 구현할 수 있음<h2 id="케라스-keras">케라스 (Keras)</h2>
</li>
<li>초보자용</li>
<li>여러 딥러닝 프레임워크를 같은 방법으로 편하게 사용할 수 있도록 하는 라이브러리</li>
<li>현재 텐서플로를 지원 텐서플로에도 케라스가 내장), 신버전부터 파이토치와 작스도 지원</li>
</ul>
<p>Q. 딥러닝 프레임워크는 파이썬 언어로만 가능한가요?
-&gt; yes or no
새로운 모델을 만들거나 개발, 학습 =&gt; 주로 Python
만들어진 모델을 사용 =&gt; 다른 언어도 OK</p>
<h1 id="컴퓨터-비전의-개념">컴퓨터 비전의 개념</h1>
<h2 id="컴퓨터-비전-computer-vision">컴퓨터 비전 (computer vision)</h2>
<ul>
<li>컴퓨터를 이용해 이미지로부터 의미 있는 정보를 추출하는 것</li>
<li>생물의 시각에 해당하는 영역을 다루는 인공지능 의 분야</li>
</ul>
<h2 id="응용-ocr">응용: OCR</h2>
<ul>
<li>광학 문자 인식(OCR: Optical Character 은 이미지에서 텍스트를 추출하는 기술<ul>
<li>이미지에서 텍스트를 추출하여 디지털 데이터로 전환할 수 있음</li>
</ul>
</li>
<li>이는 다양한 문서 처리 및 정보 수집 작업에 사용<ul>
<li>예) 회사의 인보이스, 영수증, 합의서 등 다양한 문서들을 디지털화</li>
</ul>
</li>
<li>또한, 광학 문자 인식 기술은 비대면 계좌 개설에서 신분증 인식 등과 같은 분야에서도 많이 사용<ul>
<li>예를 들어, 은행에서는 고객의 신분증 정보를 광학 문자 인식을 이용하여 자동으로 인식<h2 id="응용-화상-회의">응용: 화상 회의</h2>
</li>
</ul>
</li>
<li>화상 회의 소프트웨어는 오프라인 미팅을 대체하는데 중요한 역할</li>
<li>온라인 화상 회의를 기능 중에 배경을 흐리게 하거나 합성하는 기능이 있음</li>
<li>과거에는 크로마 키(chroma key) 또는 그린 스크린, 블루 스크린 등이 필요</li>
<li>현재는 image segmentation 기법을 이용하여 사람과 배경을 분리하고, 배경을 흐리게 하거나 합성하는 방법이 주로 사용</li>
</ul>
<p><em>그래서 AI를 어디다가 활용할 수 있을까? 를 항상 생각을 해봐야 한다</em></p>
<h2 id="컴퓨터-그래픽-방식">컴퓨터 그래픽 방식</h2>
<h3 id="비트맵-방식-bitmap">비트맵 방식 (bitmap)</h3>
<ul>
<li>이미지를 작은 정사각형 모양의 픽셀이라고 하는 점들로 저장하는 방식</li>
<li>각각의 픽셀이 밝기를 가짐<ul>
<li>픽셀이 꺼지면 밝기 0) 검은 색이 되고, 최대로 켜지면 흰색 그 중간에서는 회색</li>
</ul>
</li>
<li>비트맵 방식은 이미지를 확대하거나 축소할 때 왜곡이 생길 수 있음<ul>
<li>작은 이미지를 크게 확대해보시면 이미지가 흐릿해지는 것을 볼 수 있음</li>
<li>또 이미지의 크기가 커지면, 이미지 한 장에 들어가는 점의 개수도 늘어나기 때문에 용량이 커진다는 문제가 있음<h3 id="컬러-비트맵-이미지">컬러 비트맵 이미지</h3>
</li>
</ul>
</li>
<li>여러 개의 픽셀을 합쳐서 표현</li>
<li>빛의 삼원색(RGB)<pre><code>  - 빨강(R)</code></pre><ul>
<li>초록(G)<ul>
<li>파랑(B)</li>
</ul>
</li>
</ul>
</li>
<li>인쇄용 이미지는 CMYKCMYK를 사용<h3 id="비트맵-저장-형식">비트맵 저장 형식</h3>
</li>
<li>JPEG (Joint Photographic Experts Group)<ul>
<li>대부분의 사진이나 이미지에 사용되며, 손실 압축 방식으로 이미지를 압축</li>
<li>파일 크기를 줄일 수 있으나, 이미지의 품질을 약간 손상</li>
</ul>
</li>
<li>GIF (Graphics Interchange Format Format) 와 PNG (Portable Network Graphics)<ul>
<li>작은 애니메이션 이미지나 로고, 아이콘 등에 사용</li>
<li>비손실 압축 방식으로 그래픽이나 웹 디자인에 많이 사용</li>
</ul>
</li>
<li>WebP<ul>
<li>Google에서 웹 페이지에서 더욱 빠르게 로딩되도록 개발한 영상 이미지 파일 포맷</li>
<li>기존의 JPEGJPEG와 PNG, GIF GIF의 장점을 모두 합쳐서 손실 압축과 비손실 압축을 모두 지원</li>
<li>더 효율적인 압축 방식을 사용하기 때문에 파일 크기는 더 작고, 이미지 품질은 더 높은 특징<h3 id="벡터-방식-vector">벡터 방식 vector</h3>
</li>
</ul>
</li>
<li>벡터 방식은 이미지를 수학적인 곡선과 모양으로 표현</li>
<li>이미지를 확대하거나 축소할 때도 깨지지 않고 선명한 이미지를 유지<h3 id="벡터-저장-형식">벡터 저장 형식</h3>
</li>
<li>pdf (Portable Document Format Format) 문서용</li>
<li>svg (Scalable Vector Graphics) 주로 웹 사이트에서 사용<h3 id="포인트-클라우드">포인트 클라우드</h3>
</li>
<li>3D이미지에 사용하는 방식</li>
<li>각각의 포인트는 이미지의 한 점을 나타내며 색상 정보도 함께 저장</li>
<li>주로 라이다 같은 장비로 찍은 이미지를 표현할 때 사용
(살면서 우리가 거의 볼 일이 없다...ㅋㅋㅋ)</li>
</ul>
<h2 id="컴퓨터-비전-과업">컴퓨터 비전 과업</h2>
<h3 id="과업-task">과업 task</h3>
<ul>
<li>머신러닝을 통해서 풀려고 하는 문제의 종류나 달성하려는 목표</li>
<li>예시:<ul>
<li>이미지 분류</li>
<li>물체 탐지</li>
<li>이미지 분리</li>
<li>깊이 추정</li>
<li>이미지 간 변환</li>
<li>이미지 생성</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[🐼express.js로 서버랑 DB 연결하기]]></title>
            <link>https://velog.io/@dev-april/express.js%EB%A1%9C-%EC%84%9C%EB%B2%84%EB%9E%91-DB-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@dev-april/express.js%EB%A1%9C-%EC%84%9C%EB%B2%84%EB%9E%91-DB-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 18 Sep 2023 13:33:08 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/dev-april/post/0845c5a1-994d-4745-a78a-81fe57441c72/image.png" alt="">
출처 <a href="https://velog.io/@gidong_e/Node.js-Express">https://velog.io/@gidong_e/Node.js-Express</a></p>
<h1 id="웹사이트의-동작원리">웹사이트의 동작원리</h1>
<blockquote>
<h2 id="1-client브라우저-html-css-javascript--react-next">1. client(브라우저) (html, css, javascript / react, next)</h2>
<pre><code>에서 데이터를 서버쪽으로 전송((특정 요청도 함께)서버야 뭐 해줘!)
요청할때 어느정도 들을 규정 REST API
조회같은 요청 --&gt; get 요청 이라고 하자
삭제같은 요청 --&gt; delete 요청
추가같은 요청 --&gt; post 요청
수정 요청 --&gt; put 요청
요청에 대한 모양은 주소모양으로 하자
사용자 정보 조회는
    www.naver.com/user 로 get 요청
사용자 정보 수정
    www.naver.com/user put 요청 + April이라는 사용자를 나이 20으로
    www.naver.com/ get 요청</code></pre></blockquote>
<h2 id="2-서버는-client의-데이터와-요청의-정보를-받는다">2. 서버는 client의 데이터와 요청의 정보를 받는다</h2>
<pre><code>app.get(&#39;/user&#39;, 함수);
app.put(&#39;/user&#39;, 함수);</code></pre><p>&quot;April&quot; 데이터 받았고, 요청은 April의 신상정보 조회 요청이네
    데이터베이스에서 April의 신상 정보 조회(SQL)
    (SELECT age, salary, name FROM tbl_users WHERE name = &#39;April&#39;)
    데이터베이스 속 데이터를 가져왔다
    데이터베이스에서 받은 데이터를 client에게 다시 전송(응답)</p>
<h2 id="3-client브라우저">3. client(브라우저)</h2>
<p>서버로부터 받은 응답을 사용자에게 화면으로 보여주기
express.js 서버쪽에서 사용하는 프레임워크
    프레임워크 : 공통적인 기능을 미리 구현해 놓은 일종의 반조리식품
    서버에서 클라이언트쪽으로 데이터전송, 이미지파일, js파일, 보안기능, ...
서버로 활용하고 싶은 폴더를 생성하여
해당 폴더 안에서 npm init 을 실행하면 package.json(해당폴더에 대한 정보가 들어있는 파일)
이 자동으로 만들어 진다
entry point: (index.js) app.js (server.js 로 만드는 사람도 있음)</p>
<h1 id="express-설치">Express 설치</h1>
<pre><code> npm install express --save // 임시적으로 사용하려면 --save 빼도 된다</code></pre><hr>
<h3 id="포트번호">포트번호?</h3>
<p>   같은 컴퓨터 안에서 실행되고 있는 프로그램들을 구분하기 위한 번호</p>
<h3 id="누구의-컴퓨터">누구의 컴퓨터?</h3>
<p>   April의 컴퓨터
    Kyle의 컴퓨터
    컴퓨터를 구분하는 것은 ip주소 127.0.0.1</p>
<h3 id="목표는-april의-컴퓨터">목표는 April의 컴퓨터</h3>
<p>   실행중인 프로그램이
        LoL             3000
        Zoom            3001
        kakao talk      8080
        ...             3360</p>
<hr>
<h3 id="실행-명령어">실행 명령어</h3>
<pre><code>node app</code></pre><h2 id="nodemon">nodemon</h2>
<p>   express로 만든 프로그램이 실행중인 상태에서
    코드를 수정하면 반영되지 않기 때문에 서버를 다시 껐다 켜줘야 한다
    이때 nodemon을 사용하면 코드가 수정되면 알아서 서버를 껐다 켜준다</p>
<h3 id="설치">설치</h3>
<pre><code>npm install nodemon --save</code></pre><p>전역설치(어떤 프로젝트 만들든 터미널에서 명령어 사용할수있도록)</p>
<pre><code>npm install --global nodemon</code></pre><h3 id="실행">실행</h3>
<pre><code>nodemon 파일이름</code></pre><hr>
<h2 id="서버랑-db-연결">서버랑 DB 연결</h2>
<pre><code>npm install --save mysql2</code></pre><p>mysql은 설치되면
따로 실행하지 않아도 
프로그램이 실행됨 (컴퓨터켜지면)</p>
<p>react       3001 실행중
express가   3000번 실행중
mysql은 3306번 실행중</p>
<h3 id="원리">원리</h3>
<ol>
<li><p>리액트가 요청(클라이언트)
 /user get 요청! &#39;April&#39;
 (3000번에서 실행중인 express 한테)</p>
</li>
<li><p>express는
 &#39;April&#39;이라는 데이터를 받아서
  app.get(&#39;/user&#39;, 함수1);
  에 명시된 함수1을 실행함!
  함수1 내부적으로</p>
<pre><code> 1. 3306번에 실행중인 mysql접속
 2. &#39;April&#39; 데이터 SELECT
 3. 결과로 받아온 데이터 res.json 응답
     (다시 리액트에게 응답)</code></pre></li>
<li><p>리액트는 응답을 받아서 받아온 데이터를
 이쁘게 h1태그 쌓아서 보여줌</p>
</li>
</ol>
<h3 id="appjs">app.js</h3>
<pre><code class="language-jsx">// 옛날 문법 commonjs 모듈
// 요즘 문법 es 모듈(express가 아직 es모듈로 작성했을때는 올바르게 동작하지 않는 경우가 있음)
// import styled from &quot;@emotion/styled&quot;
// import express from &quot;express&quot;;
const express = require(&#39;express&#39;);
const mysql = require(&#39;mysql2&#39;);

const app = express();
const port = 3000;

// 앞에있는 req는 요청에대한 정보가 객체로 들어있다
// 뒤에있는 res는 응답에대한 정보가 객체로 들어있다
app.get(&#39;/&#39;, (req, res)=&gt;{
    // 데이터베이스 가서 조회해줘
    // 데이터베이스에 가져온 데이터를 클라이언트로 보내야하네? 이때 사용하는 것이
    res.send(&#39;hello world&#39;)
    });

// /a 로 get 요청시 응답으로 age is 10 출력해줘
app.get(&#39;/a&#39;, (req, res)=&gt;{
    let html = `
        &lt;h1&gt;메인페이지 입니다&lt;/h1&gt;
        &lt;p&gt;안녕하세요&lt;/p&gt;
    `;
    res.send(html); // 데이터 보내기 방법1
});

// JavaScript Object Notation(자바 스크립트 객체 표기법)
app.get(&#39;/b&#39;, (req, res)=&gt;{
    res.json({age:10, name:&#39;Jay&#39;}); // 데이터 보내기 방법2
})
// 이미 실행 중인 포트였기때문에 실행 X
// Ctrl + c 눌러서 서버 끄고
// node app 다시 켜야한다

app.get(&#39;/c&#39;, (req, res)=&gt;{
    console.log(&#39;삭제완료!&#39;); // DELETE FROM USERS WHERE name=&#39;April&#39;;
    res.end(); // 데이터 보내기 방법3(보낼게 없을때)
});

// creating connection pool
const pool = mysql.createPool({
    host:&#39;localhost&#39;, // &#39;127.0.0.1&#39; 로 써도 된다
    database:&#39;board&#39;,
    user:&#39;boarduser&#39;,
    password:&#39;0000&#39;, // 안알랴줌~ㅎㅎㅎ
    port:3306
});


// mysql접속해서 사용자이름이 April인 사람의 데이터 조회
app.get(&#39;/d&#39;, (req, res)=&gt;{

    pool.query(&#39;select * from tbl_a&#39; , (err, results, fields)=&gt;{
        console.log(err);
        console.log(&#39;res에는&#39;, results);
        console.log(&#39;fields에는&#39;,fields);
        res.json(results);
    });

});

app.listen(port, ()=&gt;{console.log(`app listening on ${port}`)});
// listen 함수
// 1. 인자
//     두개 앞에는 숫자타입, 뒤에는 함수
// 2. 동작
//      해당 프로그램이 앞쪽에 전달받은 숫자 번 포트에서 동작하게 만드는 함수
//      뒤쪽에 인자로 전달한 콜백함수는 프로그램이 실행되었을 때 최초 한번 실행되는 함수이다
// 3. 결과값
//      생각X (실행중인 서버타입)
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[DBMS 고오급 들어갑니다~ day03 ( join)]]></title>
            <link>https://velog.io/@dev-april/DBMS-%EA%B3%A0%EA%B8%89-%EB%93%A4%EC%96%B4%EA%B0%91%EB%8B%88%EB%8B%A4-join</link>
            <guid>https://velog.io/@dev-april/DBMS-%EA%B3%A0%EA%B8%89-%EB%93%A4%EC%96%B4%EA%B0%91%EB%8B%88%EB%8B%A4-join</guid>
            <pubDate>Wed, 13 Sep 2023 13:16:43 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/dev-april/post/bcc921cc-58fc-40e1-acc6-043efac731bd/image.jpg" alt=""></p>
<p>출처 <a href="https://www.geeksforgeeks.org/sql-join-set-1-inner-left-right-and-full-joins/">https://www.geeksforgeeks.org/sql-join-set-1-inner-left-right-and-full-joins/</a></p>
<p>끝나지 않은 SELECT...ㅎㅎㅎ
<del>DBMS 세번째 배우니까 이제 좀 할만하다(머리 사양이 좀..)</del>
join 이번에 확실히 기억하고 넘어가보자구!!</p>
<h2 id="day03txt">day03.txt</h2>
<pre><code class="language-sql">SELECT
    컬럼 골라내기 ( SELECT a, b)
    행 골라내기 ( WHERE 절)

정렬하여 조회하기
    최신순, 오래된순, 좋아요순, ...

SELECT 컬럼1, 컬럼2, 컬럼3
FROM 테이블명
WHERE 조건 -- 행을 안 골라내고 싶으면 안써도됨
ORDER BY 컬럼 옵션;

옵션
    ASC
        오름차순(작은값-&gt;큰값)
    DESC
        내림차순(큰값-&gt;작은값)

컬럼 이름에 별명 붙이기(alias)
SELECT id 아이디, name &quot;사용자 이름&quot;, age AS &quot;나이&quot;
from tbl_tmp;
    AS 는 생략 가능,
    &quot;&quot; 는 컬럼의 별명을 이미 사용되고 있는 예약어(명령어)로 사용하거나
    띄어쓰기가 포함된 별명을 사용하는 경우를 제외하고는 생략가능
    SELECT
        a AS &quot;안녕&quot;,
        b &quot;반가워&quot;,
        c AS 가격,
        d cnt

두개의 테이블을 합치기
    JOIN

내부/동등조인(inner/equi join)
    두개의 테이블을 합치긴 할건데, 조건을 만족하는 행들끼리 합치겠다

SELECT 컬럼, 컬럼, ...
FROM 테이블명1 INNER JOIN 테이블명2
ON 조인조건
[WHERE 조건]
[ORDER BY 컬럼 옵션]

OUTER JOIN

    SELECT 컬럼, 컬럼, ...
    FROM 테이블명1 LEFT OUTER JOIN 테이블명2
    ON 조인조건
    [WHERE 조건]
    [ORDER BY 컬럼 옵션]

    SELECT 컬럼, 컬럼, ...
    FROM 테이블명1 RIGHT OUTER JOIN 테이블명2
    ON 조인조건
    [WHERE 조건]
    [ORDER BY 컬럼 옵션]

날짜 형식 패턴
    %m : 두글자 월 03
    %M : March
    %d : 두글자 일  22
    %D : 22nd
    %y : 두글자 년도
    %Y : 네글자 년도
    %h : 00 ~ 12
    %H : 00 ~ 23

데이터 수정
    UPDATE 테이블명
    SET 컬럼명 = 값, 컬럼명 = 값, ...
    WHERE 조건;

데이터 삭제
    DELETE FROM 테이블명
    WHERE 조건;

데이터 추가 시에는
    부모에 없는 값을 자식테이블에 추가할수 없다

데이터 삭제 시에는
    자식에서 사용되고 있는 값을 부모에서 삭제할수 없다
    자식에서 사용되고 있는 값이 부모에서 삭제된다면 자동으로
    자식에서도 삭제가 되게 만드는 옵션 : ON DELETE CASCADE

    자식에서 사용되고 있는 값이 부모에서 삭제된다면 자동으로
    자식의 값을 NULL 로 바꾸는 옵션 : ON DELETE SET NULL</code></pre>
<h3 id="01정렬sql">01정렬.sql</h3>
<pre><code class="language-sql">select * from tbl_tmp;

select *
from tbl_tmp
order by age asc;

select *
from tbl_tmp
order by age desc;

select id 아이디, name as &quot;이름&quot;, age as &quot;나이&quot;
from tbl_tmp
order by 나이 asc; -- 컬럼의 별명으로도 정렬 가능    

-- 테이블 하나 더 만들어보자(고오급 진도 나간다)
create table tbl_posts(
    post_id int,
    title varchar(100),
    contents varchar(200),
    writer int,
    constraint tbl_posts_pk primary key(post_id),
    constraint tbl_posts_writer_fk foreign key(writer) references tbl_tmp(id)
);

# tbl_tmp의 id 컬럼에 4645가 없기에
# tbl_posts의 writer에는 4645가 저장될 수 없다(외래키 제약조건위반)
insert into tbl_posts
(post_id, title, contents, writer)
values
(2315, &#39;javascript를 배워봅시다&#39;, &#39;javascript 얼마나 재밌게요~&#39;, 40);

insert into tbl_posts
(post_id, title, contents, writer)
values
(105, &#39;오늘 뭐먹을까요?&#39;, &#39;오늘 저녁메뉴 추천좀&#39;, 20);

insert into tbl_posts
(post_id, title, contents, writer)
values
(50, &#39;안녕하세요&#39;, &#39;반가워여~&#39;, null);

select * from tbl_posts;

select * from tbl_tmp;

# 내부조인
select tbl_posts.title, tbl_tmp.name-- 컬럼이름이 같을 수도 있기 때문에 소속을 알려주는 습관 들이기
from tbl_posts inner join tbl_tmp -- 자리를 바꿔도 결과는 동일(컬럼 순서 바뀌는건 상관X)
on tbl_posts.writer = tbl_tmp.id;

# 테이블 이름에 별명 짓기 (AS XX)
select tp.title 제목, tt.name 작성자
from tbl_posts tp inner join tbl_tmp tt
on tp.writer = tt.id;

# left outer join
# 왼쪽에 있는 테이블의 행을 모두 보겠다(손실없이)
select *
from tbl_posts tp left outer join tbl_tmp tt
on tp.writer = tt.id;

# Right outer join
# 왼쪽에 있는 테이블의 행을 모두 보겠다(손실없이)
select *
from tbl_posts tp right outer join tbl_tmp tt
on tp.writer = tt.id;

# 산술연산자 자유롭게 사용 가능
# 예) 사원, 이름, 나이, 봉급 컬럼이 있을텐데 원래 봉급의 x2.4 해서 성과급 볼때 사용
select * from tbl_tmp;

select age, age + 10
from tbl_tmp;

# 날짜 데이터
alter table tbl_tmp
modify join_date datetime default now(); 

insert into tbl_tmp
(id, name, age, join_date)
values
(78, &#39;Kyle&#39;, 7, str_to_date(&#39;07-31-2017&#39;, &#39;%m-%d-%Y&#39;));

insert into tbl_tmp
(id, name, age, join_date)
values
(120, &#39;Jay&#39;, 40, now() );

select now(); -- Oracle의 sysdate() 와 동일

select * from tbl_tmp;

# 데이터 수정
update tbl_tmp
set name = &#39;Stephany&#39;, age = 33
where id = 30;

# Oracle 가능, MySQL은 기본적으로 safe mode가 적용되어
# primary key 가 아닌 조건으로 행을 골라내어 수정하는것을 막아준다(해제 가능)
# 영어식 문법이기때문에 거꾸로 쓰면 더 편함
update tbl_tmp
set join_date = now()
where id &lt;=60;

# 데이터 삭제
delete from tbl_tmp
where id = 50;

# 자식에서 사용중인 값을 부모에서 삭제하려면 오류발생(FK)
delete from tbl_tmp
where id = 40;

# 외래키 제약조건을 설정할 때
# 부모의 값이 삭제되면 자식의 값도 삭제
# 혹은 자식의 값을 null로 자동으로 바꿔주는 옵션을 만들수 있음
create table tbl_a(
    id int primary key,
    pw varchar(20)
);

insert into tbl_a
values(4, &#39;wlwl&#39;);

select * from tbl_a;

create table tbl_b(
    post_id int primary key,
    writer int,
    constraint fk foreign key (writer)
    references tbl_a(id) on delete cascade -- 계단식으로(id 삭제하면 writer도 자동으로 삭제시켜라)
);

create table tbl_b(
    post_id int primary key,
    writer int,
    constraint fk foreign key (writer)
    references tbl_a(id) on delete set null -- 삭제가 발생하면 그 부분을 null값 으로 대체해라
);

insert into tbl_b
values(300, 3);

select * from tbl_b;

delete from tbl_a
where id = 3;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[JupyterLab notebook 사용🪐]]></title>
            <link>https://velog.io/@dev-april/JupyterLab-notebook-%EC%82%AC%EC%9A%A9-5twtn0b0</link>
            <guid>https://velog.io/@dev-april/JupyterLab-notebook-%EC%82%AC%EC%9A%A9-5twtn0b0</guid>
            <pubDate>Tue, 12 Sep 2023 04:40:03 GMT</pubDate>
            <description><![CDATA[<p>출처<a href="https://jakeash22.medium.com/why-you-should-consider-switching-to-jupyterlab-from-jupyter-notebook-7f309519c0c2">https://jakeash22.medium.com/why-you-should-consider-switching-to-jupyterlab-from-jupyter-notebook-7f309519c0c2</a></p>
<h2 id="쥬피터랩-노트북-다운로드하기">쥬피터랩 노트북 다운로드하기</h2>
<ol>
<li>구글에 가서 Anaconda로 검색을 한다</li>
<li>Free Download 클릭</li>
<li>Download 버튼 클릭 (운영체제 아이콘을 잘 확인)</li>
<li>다운받은 Anaconda3...을 실행</li>
<li>Next와 I Agree를 눌러서 설치
 (관리자 권한으로 설치하는 옵션은 선택하지 마세요)</li>
</ol>
<p>시작 -&gt; Anaconda 3(64-bit) -&gt; JupyterLab notebook 앱 실행 혹은
    -&gt; Anaconda Navigator 에서 JupyterLab notebook launch하기
    -&gt; 데이터가 있는 Downloads 폴더로 이동
    -&gt; 오른쪽 상단에 New -&gt; python3 실행</p>
<p>까만창만 떠있는 경우
(1) 까만창을 클릭한 다음에 그냥 엔터 한 번
(2) 인터넷 주소를 복사해서 인터넷 주소창에 붙여넣고 이동</p>
<p>Desktop: 바탕화면
Documents: 문서
Downloads: 다운로드</p>
<p>colab: 구글에 서버가 있고, 인터넷 접속해서 사용
jupyter: 인터넷 창만 사용할 뿐, 실제로는 여러 컴퓨터에서 작동</p>
<p>=&gt; 궁금해서 다운받아봤지만 깃허브로 결과물을 저장하는 나에겐 최대의 단점ㅠㅠ
나는 그냥 colab을 사용하겠다ㅋㅋ
하지만 library들을 내 pc에 install해놓으면 편할 것 같기도하고 와이파이가 잘 안되거나 컴퓨터 사양이 좋지 않은 사람들에겐 도움이 될것 같다..^-^</p>
]]></description>
        </item>
    </channel>
</rss>