<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>misolab.log</title>
        <link>https://velog.io/</link>
        <description>self.do(now)</description>
        <lastBuildDate>Fri, 27 Oct 2023 14:37:22 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>misolab.log</title>
            <url>https://velog.velcdn.com/images/do-ockhyun/profile/c43c00cc-e4c1-4552-a5ae-0861d61b23c5/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. misolab.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/do-ockhyun" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[vue3 composition api 정리 ]]></title>
            <link>https://velog.io/@do-ockhyun/vue3-composition-api-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@do-ockhyun/vue3-composition-api-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Fri, 27 Oct 2023 14:37:22 GMT</pubDate>
            <description><![CDATA[<p><strong>Vue.js Composition API</strong></p>
<ol>
<li><p>Vue.js 3의 Composition API는 컴포넌트의 로직을 모듈화하고 재사용 가능하게 만드는 새로운 방식의 컴포넌트 구성 방법입니다.</p>
</li>
<li><p><code>setup</code> 함수는 모든 컴포넌트에서 진입점 역할을 하며, 컴포넌트 내부의 데이터, 메소드 및 리액티브 상태를 설정하는 데 사용됩니다.</p>
</li>
<li><p><code>ref</code>와 <code>reactive</code> 함수를 사용하여 데이터를 리액티브하게 만들 수 있으며, <code>computed</code>, <code>watch</code>, <code>onMounted</code>, <code>onUpdated</code>, <code>onBeforeUnmount</code>와 같은 컴포지션 함수를 사용하여 컴포넌트 동작을 정의할 수 있습니다.</p>
</li>
<li><p><code>&lt;script setup&gt;</code>은 Composition API를 사용하여 컴포넌트를 더 간결하게 정의하는 방법으로, <code>setup</code> 함수를 별도로 정의하지 않아도 됩니다.</p>
</li>
</ol>
<p><strong>&quot;use&quot;로 시작하는 커스텀 함수</strong></p>
<ol start="5">
<li>&quot;use&quot;로 시작하는 함수를 사용하여 컴포넌트 로직을 모듈화하고 재사용할 수 있습니다. 이러한 함수는 컴포넌트 내에서 커스텀 로직을 정의하고 다른 컴포넌트에서 재사용할 수 있도록 도와줍니다.</li>
</ol>
<p><strong>함수형 프로그래밍과의 관련성</strong></p>
<ol start="6">
<li>Vue 3 Composition API는 함수형 프로그래밍의 원리와 개념을 포함하고 있으며, 데이터 불변성, 순수 함수, 함수 조합 및 데이터 변환과 같은 함수형 프로그래밍의 개념을 지원합니다.</li>
</ol>
<p>이러한 개념과 기술을 활용하여 Vue.js 애플리케이션을 보다 모듈화하고 유지보수 가능하게 만들 수 있으며, 코드의 가독성과 품질을 향상시킬 수 있습니다. Vue.js Composition API와 함수형 프로그래밍을 조합하여 좀 더 강력하고 효율적인 웹 애플리케이션을 개발하는 데 도움이 됩니다.</p>
<hr>
<p>Vue.js Composition API에서 &quot;use&quot; 함수를 활용한 코드 예제를 아래에 제시하겠습니다:</p>
<pre><code class="language-vue">&lt;template&gt;
  &lt;div&gt;
    &lt;p&gt;Count: {{ customLogic.data }}&lt;/p&gt;
    &lt;p&gt;Double: {{ customLogic.double }}&lt;/p&gt;
    &lt;button @click=&quot;customLogic.increment&quot;&gt;Increment&lt;/button&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script&gt;
import { useCustomLogic } from &#39;./useCustomLogic&#39;;

export default {
  setup() {
    const customLogic = useCustomLogic(0);
    return { customLogic };
  }
}
&lt;/script&gt;</code></pre>
<p>위 코드에서는 &quot;useCustomLogic&quot; 함수를 사용하여 커스텀 로직을 정의하고, 이 커스텀 로직을 다른 컴포넌트에서 재사용합니다. &quot;useCustomLogic&quot; 함수는 초기값을 받아서 해당 로직을 캡슐화하고, 컴포넌트에서 필요할 때 호출하여 사용합니다.</p>
<p><code>useCustomLogic</code> 함수는 아래와 같이 정의될 수 있습니다:</p>
<pre><code class="language-javascript">import { ref, computed, watch } from &#39;vue&#39;;

function useCustomLogic(initialValue) {
  const data = ref(initialValue);

  const double = computed(() =&gt; data.value * 2);

  const increment = () =&gt; {
    data.value++;
  };

  watch(data, () =&gt; {
    // 데이터가 변경될 때 실행할 동작
  });

  return {
    data,
    double,
    increment,
  };
}</code></pre>
<p>이로써 &quot;use&quot; 함수를 사용하여 컴포넌트 로직을 모듈화하고 재사용할 수 있게 됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹페이지 스크린샷 저장하기]]></title>
            <link>https://velog.io/@do-ockhyun/%EC%9B%B9%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@do-ockhyun/%EC%9B%B9%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 15 Oct 2023 12:34:46 GMT</pubDate>
            <description><![CDATA[<p>아침에 새로운 아이디어가 생각나서 크롤링을 찾아봤다.
그러던중 화면을 복사할게 아니라 스크린샷을 저장하고 이를 원(origin) 페이지로 링크를 걸기로 했다.</p>
<p>GPT에 물어보니, puppeteer를 이용하면 된다고 했다.</p>
<hr>
<h3 id="puppeteer-사용법을-알려줘세요">Puppeteer 사용법을 알려줘세요</h3>
<p>Puppeteer는 Node.js 기반의 라이브러리로, Chrome 또는 Chromium 브라우저를 제어하여 웹페이지 스크린샷을 생성하고 다양한 웹 테스트 및 자동화 작업을 수행할 수 있게 해줍니다. 아래는 Puppeteer를 사용하여 웹페이지 스크린샷을 캡처하는 간단한 예제입니다.</p>
<ol>
<li><p><strong>Puppeteer 설치:</strong>
Node.js 프로젝트에서 Puppeteer를 사용하려면 먼저 Puppeteer를 설치해야 합니다. 프로젝트 폴더에서 다음 명령을 실행하여 Puppeteer를 설치하세요:</p>
<pre><code>npm install puppeteer</code></pre></li>
<li><p><strong>스크린샷 캡처 코드:</strong></p>
<p>아래 코드 예제는 Puppeteer를 사용하여 웹페이지의 스크린샷을 캡처하는 방법을 보여줍니다.</p>
<pre><code class="language-javascript">const puppeteer = require(&#39;puppeteer&#39;);

(async () =&gt; {
  // Puppeteer를 시작합니다.
  const browser = await puppeteer.launch();

  // 새 페이지를 엽니다.
  const page = await browser.newPage();

  // 웹페이지로 이동합니다.
  await page.goto(&#39;https://example.com&#39;);

  // 스크린샷을 캡처합니다.
  await page.screenshot({ path: &#39;example.png&#39; });

  // 브라우저를 종료합니다.
  await browser.close();
})();</code></pre>
<p>이 코드는 Puppeteer를 사용하여 &#39;<a href="https://example.com&#39;">https://example.com&#39;</a> 웹페이지로 이동하고, 스크린샷을 &#39;example.png&#39; 파일로 저장합니다. 필요에 따라 웹페이지의 크기, 스크린샷 형식 및 다른 옵션을 사용자 정의할 수 있습니다.</p>
</li>
<li><p><strong>스크린샷 생성:</strong>
코드를 실행하려면 Node.js 스크립트를 실행하면 됩니다.</p>
<pre><code>node your_script.js</code></pre></li>
<li><p><strong>출력 확인:</strong>
스크린샷은 현재 작업 디렉토리에 &#39;example.png&#39;라는 파일 이름으로 저장됩니다. 웹페이지 스크린샷을 확인할 수 있습니다.</p>
</li>
</ol>
<p>이것은 Puppeteer의 간단한 사용 예제이며, Puppeteer는 훨씬 더 많은 기능과 옵션을 제공합니다. 브라우저 조작, 웹 테스트, 자동화, PDF 생성 등 다양한 작업을 수행할 수 있습니다. 필요에 따라 Puppeteer 문서를 참고하여 자세한 정보를 얻을 수 있습니다.</p>
<h3 id="로그인이-필요한-사이트면-어떻게-하죠">로그인이 필요한 사이트면 어떻게 하죠?</h3>
<p>로그인이 필요한 웹페이지의 스크린샷을 캡처하려면 Puppeteer와 같은 도구를 사용하여 로그인 과정을 자동화해야 합니다. 아래는 Puppeteer를 사용하여 로그인이 필요한 웹페이지에서 스크린샷을 캡처하는 예제입니다:</p>
<pre><code class="language-javascript">const puppeteer = require(&#39;puppeteer&#39;);

(async () =&gt; {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  // 웹페이지로 이동
  await page.goto(&#39;https://example.com&#39;);

  // 로그인 폼 입력 필드를 찾고 입력
  await page.type(&#39;#username&#39;, &#39;your_username&#39;);
  await page.type(&#39;#password&#39;, &#39;your_password&#39;);

  // 로그인 버튼을 클릭
  await page.click(&#39;#login-button&#39;);

  // 로그인 완료 후 대기 (로그인 완료를 확인하는 방법은 웹페이지에 따라 다를 수 있습니다)
  await page.waitForNavigation();

  // 스크린샷 캡처
  await page.screenshot({ path: &#39;after_login.png&#39; });

  // 브라우저 닫기
  await browser.close();
})();</code></pre>
<p>이 예제에서는 Puppeteer를 사용하여 웹페이지로 이동하고, 로그인 폼의 필드에 사용자 이름과 비밀번호를 입력한 후 로그인 버튼을 클릭합니다. 그리고 로그인이 완료될 때까지 대기한 뒤 스크린샷을 캡처합니다.</p>
<p>로그인 웹페이지의 HTML 구조와 로그인 프로세스는 사이트마다 다를 수 있으므로 웹페이지에 따라 필드 및 버튼을 선택하는 방법을 조정해야 합니다. Puppeteer의 <code>page.type</code>, <code>page.click</code>, 및 <code>page.waitForNavigation</code> 등의 메서드를 사용하여 작업을 수행합니다.</p>
<p>또한, 로그인 자격 증명을 코드 내에 하드코딩하는 것은 보안상 취약할 수 있으므로, 민감한 정보를 관리하기 위한 안전한 방법을 고려해야 합니다.</p>
<hr>
<p>여기서 로그인 폼 입력 필드를 찾는게 어려울 수 있는데
이때는 개발자도구를 이용하면 편하다.</p>
<ul>
<li><p>selector 정보가 필요한 요소에 우클릭 &gt; 검사 &gt; copy &gt; Copy selector
<img src="https://velog.velcdn.com/images/do-ockhyun/post/77d1b4a7-3233-4721-b39e-04b24fba9a56/image.png" alt=""></p>
</li>
<li><p>그렇게 복사한 값을 코드에 적용하면</p>
<pre><code class="language-js">// 로그인 폼 입력 필드에 값을 입력
await page.type(&#39;#login_form &gt; div.form-group &gt; input:nth-child(1)&#39;, &#39;username&#39;);
await page.type(&#39;#login_form &gt; div.form-group &gt; input.form-control.is-invalid&#39;, &#39;password&#39;);

// 로그인 버튼 클릭
await page.click(&#39;#login_form &gt; a&#39;);</code></pre>
</li>
</ul>
<p>마지막으로, 이미지 크기가 default 600x800 이라고 하는데
나는 fullSize가 필요했다. 
찾아보니, <code>fullPage</code>가 있었다.</p>
<pre><code class="language-js">await page.screenshot({ path: `${name}.png`, fullPage: true});</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[TDD와 인생의 공통점]]></title>
            <link>https://velog.io/@do-ockhyun/TDD%EC%99%80-%EC%9D%B8%EC%83%9D%EC%9D%98-%EA%B3%B5%ED%86%B5%EC%A0%90</link>
            <guid>https://velog.io/@do-ockhyun/TDD%EC%99%80-%EC%9D%B8%EC%83%9D%EC%9D%98-%EA%B3%B5%ED%86%B5%EC%A0%90</guid>
            <pubDate>Sat, 14 Oct 2023 02:14:35 GMT</pubDate>
            <description><![CDATA[<h3 id="목표-설정">목표 설정</h3>
<p>TDD에서는 테스트 케이스를 작성해서 원하는 동작을 명확하게 정의해야 해. 
인생에서도 목표를 설정하고 행동 계획을 세우는 게 중요하지.</p>
<h3 id="실패를-허용">실패를 허용</h3>
<p>TDD에서는 처음에는 테스트가 실패하는 게 허용돼. 
그래서 문제를 파악하고 개선할 수 있어. 
인생에서도 실패를 허용하고, 실패로부터 배우며 성장 하자.</p>
<h3 id="반복과-개선">반복과 개선</h3>
<p>TDD에서는 테스트를 통과하기 위해 코드를 반복적으로 개선해야 돼. 
인생에서도 지속적인 노력과 개선을 통해 더 나은 결과를 얻을 수 있어.</p>
<h3 id="피드백">피드백</h3>
<p>TDD에서는 테스트 결과를 통해 피드백을 받고 문제를 찾을 수 있어. 
인생에서도 주변의 피드백과 경험을 통해 자기 성장과 남과 더불어 살아가보렴.</p>
<p><img src="https://velog.velcdn.com/images/do-ockhyun/post/ea2010fd-3680-4c93-b4cf-864988351e7d/image.avif" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>