<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>PhilipsVelog.log</title>
        <link>https://velog.io/</link>
        <description>Philip Sung</description>
        <lastBuildDate>Mon, 06 May 2024 08:08:48 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>PhilipsVelog.log</title>
            <url>https://velog.velcdn.com/images/velog_sp/profile/e4291d19-0027-4f36-b933-92e0276a565d/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. PhilipsVelog.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/velog_sp" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[11장]]></title>
            <link>https://velog.io/@velog_sp/11%EC%9E%A5</link>
            <guid>https://velog.io/@velog_sp/11%EC%9E%A5</guid>
            <pubDate>Mon, 06 May 2024 08:08:48 GMT</pubDate>
            <description><![CDATA[<h1 id="11장에-앞서-10장-中-이벤트-핸들링">11장에 앞서: 10장 中 이벤트 핸들링</h1>
<h2 id="이벤트-핸들링">이벤트 핸들링</h2>
<h3 id="이벤트-타겟">이벤트 타겟</h3>
<p>웹 페이지에서 사용자가 클릭하는 지점에 있는 요소는 &quot;이벤트 타깃&quot; 또는 &quot;리프 노드&quot;다. 이는 해당 클릭 지점에서 가장 구체적인, 즉 가장 하위에 위치한 요소이다. 이 타겟에 대한 이벤트가 발생하는 과정에서 이벤트가 전파되는 경우 각 노드는 &quot;원본 이벤트 객체&quot;를 공유한다. 캡쳐링-타겟도달-버블링을 거치는 이유는 다음과 같다.</p>
<p><strong>캡쳐링</strong>
특정 상황에서 이벤트를 미리 처리하거나 중간에 이벤트를 중단해야 할 때 유용하다. 캡처링 단계의 존재는 개발자가 이벤트 처리의 흐름을 더욱 세밀하게 제어할 수 있게 해준다. </p>
<ul>
<li><p>이벤트 핸들링의 우선 순위 제공: 특정 이벤트가 발생했을 때, 상위 요소에서 먼저 이벤트를 감지하고 처리할 기회를 제공. 이는 하위 요소보다 먼저 이벤트에 반응해야 하는 경우 유용하다. 예를 들어, 특정 조건에서 이벤트를 차단하거나, 특정 동작을 먼저 수행한 후 하위 요소로 이벤트를 전달해야 할 때 사용된다.</p>
</li>
<li><p>보안 및 사전 처리: 캡처링 단계에서 이벤트를 처리함으로써, 보안 관련 로직이나 데이터 검증과 같은 작업을 수행할 수 있다. 이를 통해 이벤트가 실제 타깃에 도달하기 전에 필요한 조치를 취할 수 있다.</p>
</li>
</ul>
<h2 id="리액트-이벤트-핸들링">리액트 이벤트 핸들링</h2>
<p>리액트는 자체적인 합성 이벤트(synthetic events) 시스템을 통해 DOM 이벤트를 처리한다. 이 합성 이벤트는 브라우저 간 호환성을 보장하고, 리액트 이벤트 핸들러에서 자체적으로 이벤트를 관리하므로 더 빠른 성능을 제공한다. 합성 이벤트는 실제 DOM 이벤트를 감싸는 래퍼로, 리액트 이벤트가 실제 DOM으로 전파되기 전에 리액트가 중간에서 처리한다.</p>
<p>브라우저에서 이벤트 발생 -&gt; 이벤트 처리 시스템이 document level 또는 root level에서 이벤트 리스닝 -&gt; 내부  타입과 타겟 식별 -&gt; 합성 이벤트 생성 -&gt; 핸들러 실행 -&gt; 이벤트 버블링 에뮬레이션 -&gt; (선택)버블링 또는 타겟 단계에서stop propagation 적용</p>
<p>대충 갓난아기가 쿠키를 로켓배송시켰다고 생각하면 모든게 이해가 된다.</p>
<h2 id="리액트-19">리액트 19</h2>
<p>Next 13부분을 살펴본 뒤 보면 이해가 잘 된다. 아래에서 다루도록 하겠다.</p>
<hr>
<h1 id="11장-nextjs-13과-리액트-18">11장 Next.js 13과 리액트 18</h1>
<p>Nextjs 13의 주요한 변경사항</p>
<ul>
<li>서버사이드 렌더링과 관련된 변화가 많이 있는 React 18을 채용하였다.</li>
<li>레이아웃 지원을 시작했다.</li>
<li>트랜스파일러로 Rust를 사용한 SWC를 출시하였다.</li>
<li>웹팩을 대체할 Turbopack을 출시하였다.</li>
</ul>
<hr>
<h1 id="nextjs-돌아보기">Next.js 돌아보기</h1>
<p>서버 사이드 렌더링(SSR), 정적 사이트 생성(SSG), 클라이언트 사이드 렌더링(CSR), 그리고 Incremental Static Regeneration(ISR)을 지원하는 React 기반의 프레임워크이다. 이 프레임워크는 웹 개발에 있어서 빠른 성능, SEO 최적화, 그리고 개발자 친화적인 환경을 제공하기 위해 설계되었다.</p>
<p>Next.js는 Nest.js와 같은 별도의 서버 프레임워크 없이도 웹 애플리케이션의 전반적인 기능을 수행할 수 있으며, API 라우트를 통해 서버 사이드 로직 처리 역시 가능하다. 따라서 Next.js 하나로 클라이언트와 서버의 모든 동작을 처리할 수 있다. </p>
<p>pages 디렉토리 내의 각 파일은 라우트와 직접 매핑되므로, 파일 이름과 구조를 명확히 관리해야 한다.</p>
<p>클라이언트 사이드 코드와 서버 사이드 코드를 명확히 분리하며, 보안을 유지해야 한다.</p>
<h2 id="서버-사이드">서버 사이드</h2>
<p><strong>렌더링 방식:</strong> Next.js의 서버 사이드 렌더링은 초기 페이지 로드 시 사용자의 요청에 따라 즉시 HTML을 생성하고, 이를 클라이언트로 전송한다. 이 방식은 사용자에게 빠른 초기 로딩을 제공하고, 검색 엔진 최적화(SEO)에 유리하다.</p>
<p><strong>API 라우트:</strong> /pages/api 디렉토리 내부에 파일을 배치함으로써 API 라우트를 설정할 수 있다. 이 라우트들은 서버에서만 실행되며, 데이터베이스 쿼리, 사용자 인증, 외부 API 호출 등 서버 사이드 로직을 처리한다.</p>
<p><strong>데이터 페칭:</strong> 서버 사이드에서는 getServerSideProps, getStaticProps 등의 데이터 페칭 함수를 사용하여 페이지 렌더링 전에 필요한 데이터를 미리 가져올 수 있다.</p>
<h2 id="클라이언트-사이드">클라이언트 사이드</h2>
<p><strong>하이드레이션:</strong> 서버로부터 받은 HTML은 클라이언트에서 React가 관리하는 동적인 웹 페이지로 &quot;하이드레이션&quot;되어 사용자와의 상호작용을 처리한다. 이 과정에서 클라이언트 사이드에서만 필요한 자바스크립트가 로드되고 실행된다.</p>
<p><strong>동적 라우팅:</strong> 클라이언트 사이드 라우팅은 사용자가 페이지 간에 이동할 때 페이지를 새로 로드하지 않고, 필요한 데이터만을 비동기적으로 불러와 페이지를 업데이트한다. 이는 사용자 경험을 향상시킨다.</p>
<p><strong>클라이언트 사이드 데이터 페칭:</strong> 페이지의 동적 부분에 대한 데이터는 클라이언트 사이드에서 fetch API나 Axios 같은 라이브러리를 사용해 비동기적으로 불러올 수 있다.</p>
<h2 id="서버와-클라이언트-간의-상호작용">서버와 클라이언트 간의 상호작용</h2>
<p>Next.js에서 서버와 클라이언트 사이의 상호작용은 주로 데이터와 상태를 공유하는 방식으로 이루어진다. 예를 들어, 서버에서 생성된 HTML 페이지는 클라이언트로 전송된 후, 사용자의 상호작용에 따라 필요한 데이터만을 클라이언트에서 불러와 업데이트한다. 또한, API 라우트를 통해 클라이언트는 서버에 데이터 요청을 보낼 수 있고, 서버는 이에 대한 응답을 처리하여 다시 클라이언트로 전송한다.</p>
<hr>
<h2 id="111-app-디렉터리의-등장">11.1 app 디렉터리의 등장</h2>
<pre><code class="language-javascript">export default function App() {
  return (
    &lt;div&gt;
        Common Layout
    &lt;/div&gt;
    &lt;Routes&gt;
        &lt;Route ... &gt;
        &lt;Route ... &gt;
    &lt;/Routes&gt;</code></pre>
<p>리액트에선 위와 같은 구조에서 Common Layout을 유지할 수 있으나, Next.js는 각각의 파일이 하나의 페이지가 되므로 공통 영역을 가질 수 없다. Next.js 13까지 공통된 것은 다음과 같았다.</p>
<p><strong>_document.js</strong>
_document.js 파일은 서버에서만 작동하는 파일이다. 이 파일은 웹 애플리케이션의 HTML 문서 구조를 정의하는 데 사용된다. 클라이언트 사이드 로직을 추가하는 것은 금지되어 있다. 그 이유는 _document.js가 초기 서버 사이드 렌더링 시에만 실행되며, 페이지를 네비게이션 할 때 재실행되지 않기 때문이다. 따라서 클라이언트 사이드에서 변화를 일으킬 수 있는 스크립트나 로직은 이 파일에 포함되어서는 안 된다.</p>
<p><strong>_app.js</strong>
_app.js 파일은 Next.js 애플리케이션의 루트 컴포넌트를 정의한다. 이 파일은 페이지 간의 상태 유지를 가능하게 하며, 애플리케이션 전반에 걸쳐 공통적으로 사용되는 레이아웃이나 페이지 전환, 타이틀 업데이트 등을 관리한다. 모든 페이지 요청에 대해 실행되기 때문에, _app.js는 전역 상태 관리나 라우팅 관리에 적합하다. _document.js와 달리, _app.js는 클라이언트 사이드에서도 실행되어 페이지 간에 일관된 상태를 유지할 수 있도록 한다.</p>
<p>그러나 위와 같은 요소를 사용하여서는 페이지별로 다른 레이아웃을 생성할 수 없기 때문에 제한적이었다. 이러한 사항을 레이아웃을 통해 극복하였다.</p>
<p>아래에서 구조를 살펴본다.</p>
<h3 id="1111-라우팅">11.1.1 라우팅</h3>
<p>기존에 Next.js는 프레임워크로서 파일시스템을 기반으로 페이지를 생성하였다. 정해진 디렉터리 구조 등을 따라야 했으며 이에 따라 생성되는 내용은 다음과 같다.</p>
<blockquote>
<p>/pages/a/b.tsx(파일시스템) -&gt; /a/b(URL)</p>
</blockquote>
<p>이는 Next.js 13에 이르러 다음과 같이 변경되었다.</p>
<blockquote>
<p>app/a/b -&gt; /a/b</p>
</blockquote>
<p>디렉터리 b 내에는 예약된 파일명만이 next.js에서 사용되게 된다. 예약된 파일명은 다음과 같다.</p>
<ul>
<li><strong>layout.js</strong></li>
<li><strong>page.js</strong></li>
<li><strong>error.js</strong></li>
</ul>
<h4 id="11111-layoutjs">11.1.1.1 layout.js</h4>
<pre><code class="language-typescript">export default function AppLayout({ children }: { children: ReactNode}) {
  return (
    &lt;PageLayout&gt;
        {children}
    &lt;/PageLayout&gt;
  )
}</code></pre>
<p>이와 같은 파일을 서브루트로 할당되는 서브디렉터리 내에 할당할 수가 있는데 이렇게 할당된 layout은 해당 위치부터 하위에 이르기까지 영향을 미친다.</p>
<p>루트의 경우에는 웹페이지에 필요한 기본 정보를 담아둘 수도 있다.</p>
<p>이를 통해 공통된 UI 뿐만 아리나 웹페이지를 시작하는데에 필요한 공통 코드를 삽입할 수도 있다. 다만 다음과 같은 주의사항을 준수하여야 한다.</p>
<ul>
<li>layout은 app 디렉터레 내부에서는 예약어이다. layout.{js|jsx|ts|tsx}는 공통 레이아웃 관리 목적으로만 사용한다.</li>
<li>layout은 children을 props로 받아서 렌더링해야 한다.</li>
<li>layout에서는 반드시 export default로 내보내는 컴포넌트가 있어야 한다.</li>
<li>비동기 작업을 수행할 수 있다는 점을 인지한다.</li>
</ul>
<p><strong>클라이언트 사이드:</strong> layout은 페이지 전환 시에도 유지되는 구조를 제공하며, 사용자 인터페이스의 일관성을 유지한다.</p>
<p><strong>서버 사이드:</strong> 서버에서 페이지 요청 시에도 layout은 사용되어 일관된 HTML 구조를 생성한다.</p>
<h4 id="11112-pagejs">11.1.1.2 page.js</h4>
<p>기존에 Next.js에서 렌더링 되는 페이지의 역할을 맡았던 파일에 대한 예약어이다.</p>
<p><strong>클라이언트 사이드:</strong> 각 페이지는 클라이언트 사이드에서 동적으로 렌더링된다.</p>
<p><strong>서버 사이드:</strong> 첫 요청이나 페이지 새로고침 시에는 서버에서 페이지가 렌더링되고, 결과적으로 생성된 HTML이 클라이언트로 전송된다.
다음과 같은 props를 받는다.</p>
<p>params
params 객체는 동적 라우팅을 사용할 때 URL의 경로 부분에서 정의된 변수들을 포함한다. 예를 들어, /posts/[id]라는 파일 경로로 정의된 페이지가 있고 사용자가 /posts/123 URL로 접속했다면, params 객체는 { id: &#39;123&#39; }와 같이 매핑된다. 이 객체는 페이지 경로의 각 세그먼트를 변수로 캡처하여 접근할 수 있게 해준다.</p>
<p>searchParams
searchParams 객체는 URL의 쿼리 문자열 부분을 처리한다. 이 객체는 URLSearchParams 인터페이스를 기반으로 하며, URL의 쿼리스트링에서 키-값 쌍을 쉽게 읽거나 조작할 수 있다. 예를 들어, 사용자가 /search?query=nextjs URL로 접속했다면, searchParams.get(&#39;query&#39;)는 nextjs를 반환한다.</p>
<h4 id="11113-errorjs">11.1.1.3 error.js</h4>
<p>해당 라우팅 영역에서 사용되는 공통 에러 컴포넌트이다. 라우팅별로 서로 다른 에러 UI를 렌더링할 수 있다.</p>
<p><strong>클라이언트 사이드:</strong> loading은 사용자가 새 페이지로 이동하는 동안 보여지는 상태이다. 페이지 로딩 중 사용자 경험을 개선하기 위해 사용된다.</p>
<p><strong>서버 사이드:</strong> 서버 사이드에서는 loading 상태가 존재하지 않는다. 페이지 로딩 상태는 클라이언트에서 관리된다.</p>
<pre><code class="language-typescript">&#39;use client&#39; // Error components must be Client Components

export default function Error({error,reset}: {error: Error, reset: () =&gt; void}) {
  useEffect(() =&gt; {
    // Log the error to an error reporting service
    console.error(error)
  }, [error])

  return (
    &lt;div&gt;
      &lt;button
        onClick={() =&gt; reset()}
      &gt;
      &lt;/button&gt;
    &lt;/div&gt;
  )
}</code></pre>
<p>error : 에러 정보를 담고 있음</p>
<p>reset : 에러 바운더리를 초기화 할 수 있는 함수</p>
<h4 id="11114-not-foundjs">11.1.1.4 not-found.js</h4>
<pre><code class="language-typescript">export default function NotFound() {
  return &#39;404 Not Found&#39;
}</code></pre>
<p>찾을 수 없는 페이지를 렌더링 할 때 사용된다.</p>
<p><strong>클라이언트 사이드:</strong> 사용자가 없는 페이지에 접근하려 할 때 not-found 페이지가 표시된다.</p>
<p><strong>서버 사이드:</strong> 서버에서도 요청받은 URL이 유효하지 않을 경우 not-found 페이지를 렌더링하여 응답한다.</p>
<h4 id="11115-loadingjs">11.1.1.5 loading.js</h4>
<pre><code class="language-typescript">export default function Loading() {
  return &#39;Loading...&#39;
}</code></pre>
<p>리액트 Suspense를 기반으로 해당 컴포넌트가 불러오는 중임을 나타낸다.</p>
<p><strong>클라이언트 사이드:</strong> loading은 사용자가 새 페이지로 이동하는 동안 보여지는 상태이다. 페이지 로딩 중 사용자 경험을 개선하기 위해 사용된다.</p>
<p><strong>서버 사이드:</strong> 서버 사이드에서는 loading 상태가 존재하지 않는다. 페이지 로딩 상태는 클라이언트에서 관리된다.</p>
<h4 id="11116-routejs">11.1.1.6 route.js</h4>
<p>이것에 앞서 잠시 /app/api에 대해 살펴본다.</p>
<h3 id="appapi-디렉토리">/app/api 디렉토리</h3>
<p>/app/api 내부에 파일을 배치함으로써, 개발자는 서버 사이드 로직을 구현할 수 있다. 예를 들어, /app/api/user.js 파일을 생성하면, 이 파일은 <a href="http://myDomain/api/user">http://myDomain/api/user</a> 주소로 접근할 수 있는 API 엔드포인트가 된다. 이 파일 내에서는 데이터베이스 조회, 데이터 처리, 외부 API 호출 등 서버 사이드에서 필요한 작업을 수행할 수 있다.</p>
<p><strong>API 라우트 파일</strong>
API 라우트 파일에서는 Next.js의 API 라우트 기능을 활용하여 HTTP 요청을 처리한다. 각 API 라우트 파일은 기본적으로 다음과 같은 구조를 가질 수 있다:</p>
<pre><code class="language-javascript">  export default function handler(req, res) {
  if (req.method === &#39;GET&#39;) {
    // GET 요청 처리 로직
    res.status(200).json({ message: &#39;This is a GET request&#39; });
  } else if (req.method === &#39;POST&#39;) {
    // POST 요청 처리 로직
    res.status(201).json({ message: &#39;This is a POST request&#39; });
  } else {
    // 지원하지 않는 HTTP 메소드에 대한 응답
    res.status(405).end();
  }
}</code></pre>
<p><strong>다시 돌아와서,</strong> 파일명 라우팅이 없어지고 위와 같은 내용은 디렉터리 라우팅으로 변경되었다고 한다. 즉 /pages/api를 기준으로 디렉터리를 추가하여 api 엔드포인트의 주소를 구성해야 하는 것이다. 다만 여기서 api 디렉터리를 사용하는 것은 컨벤션으로, 사실은 어떤 디렉터리를 사용하여도 route.ts가 있는 경우 해당 디렉터리는 라우팅 포인트로 작동한다.</p>
<blockquote>
<p>/apps/internal-api/hello/route.ts</p>
<p>&quot;curl -X GET &quot;<a href="http://localhost:3000/internal-api/hello&quot;">http://localhost:3000/internal-api/hello&quot;</a></p>
</blockquote>
<p>다만 page.tsx와 공존할 수 없다.</p>
<hr>
<h2 id="112-리액트-서버-컴포넌트">11.2 리액트 서버 컴포넌트</h2>
<p>서버사이드 렌더링과 다른 개념이다.</p>
<h3 id="1121-기존-리액트-컴포넌트와-서버사이드-렌더링의-한계">11.2.1 기존 리액트 컴포넌트와 서버사이드 렌더링의 한계</h3>
<p>리액트의 모든 컴포넌트는 클라이언트 사이드에서 작동하였다. 이는 즉 모든 코드가 클라이언트로 다운로드 되고, 클라이언트 사이드에서 리액트 돔을 구성한 뒤 작동하는 것을 의미한다.</p>
<p>서버사이드 렌더링에서는 서버에서 필요한 데이터를 모아 HTML을 생성하고, 클라이언트에서는 전송된 HTML을 렌더링 한 후 만들어진 DOM을 기준으로 하이드레이션을 진행한다. 이러한 구조에는 다음과 같은 한계점들이 존재한다.</p>
<ul>
<li><p><strong>자바스크립트 번들 크기가 0인 컴포넌트를 만들 수 없다.</strong> 즉, 컴포넌트가 클라이언트 사이드에서 실행되므로 실행에 필요한 자바스크립트 번들 파일을 포함하게 된다. 이것을 서버측에서 수행하길 원할 수 있다.</p>
</li>
<li><p><strong>백엔드 리소스에 대한 직접적인 접근이 불가능하다.</strong> API를 이용하여야 한다. 클라이언트에서 백엔드 리소스에 직접 접근할 수 있을 수도 있다?</p>
</li>
<li><p><strong>자동 코드 분할(code split)이 불가능하다.</strong> 코드가 필요하게 되는 시점에 동적으로 게으른 로딩을 하는것을 의미한다. 개발자가 일일히 설정해주고, 분기 등 처리가 일어난 후에야 로딩을 시작하기 때문에 분할의 이점이 없어지게 된다.</p>
</li>
<li><p><strong>연쇄적인 로딩</strong> 중첩된 구조의 컴포넌트 로딩이 있는 경우, 그리고 각 컴포넌트들이 서버에 요청을 해야 하는 경우, 그 수만큼의 지연과 요청이 발생한다. 이러한 모든 과정이 서버에서 일어난다면 효율적일 것이다.</p>
</li>
</ul>
<p>이러한 문제점들이 모두 리액트가 클라이언트를 중심으로 돌아가기 때문에 발생한다고 이야기 할 수 있다고 한다. </p>
<h3 id="1122-서버-컴포넌트란">11.2.2 서버 컴포넌트란?</h3>
<p>서버 컴포넌트(Server Component)란 하나의 언어, 하나의 프레임워크, 하나의 API와 개념을 사용하면서 서버와 클라이언트 모두에서 컴포넌트를 렌더링 할 수 있는 기법.</p>
<p>다음과 같이 세 종류로 이루어진다.</p>
<p><strong>서버 컴포넌트</strong>
서버 수준에서 실행되어 그 결과값으로 정적인 결과물을 반환하는 컴포넌트로 다음과 같은 특성을 갖는다.</p>
<ul>
<li>상태를 가질 수 없다.</li>
<li>렌더링 생명주기를 사용할 수 없다.</li>
<li>DOM API에 접근할 수 없다.</li>
<li>서버에 있는 데이터에 접근할 수 있다.</li>
<li>다른 서버 컴포넌트를 렌더링하거나, (클라이언트 컴포넌트를 렌더링 할 수 있다)&lt;-?</li>
</ul>
<p><strong>클라이언트 컴포넌트</strong>
클라이언트에서 실행되어 렌더링되는 컴포넌트</p>
<ul>
<li>서버 컴포넌트를 불러오거나, 서버 전용 훅/유틸리티를 사용할 수 없다.</li>
<li>서버 컴포넌트를 자식으로 가질 수 있다. 서버 컴포넌트는 결과값 트리로 반환되기 때문이다.</li>
<li>상태나 생명주기 등을 가질 수 있다.</li>
</ul>
<p><strong>공용 컴포넌트</strong>
서버와 클라이언트 모두에서 사용할 수 있으며, 두 제약을 동시에 받는다.</p>
<p>리액트는 모든 컴포넌트를 공용컴포넌트로 판단한다(안전).</p>
<p>다만 파일의 첫 줄에 &#39;use client&#39;를 작성하는 경우 클라이언트 컴포넌트로 간주한다.</p>
<h3 id="1123-서버-사이드-렌더링과-서버-컴포넌트의-차이">11.2.3 서버 사이드 렌더링과 서버 컴포넌트의 차이</h3>
<p>서버 사이드 렌더링의 장점을 사용할 수 있는 컴포넌트를 의미하는 것이 서버 컴포넌트이다.</p>
<p>기본적으로 작동이 클라이언트일 것으로 예상되기 때문에, 서버 컴포넌트라는 이름이 붙었다.</p>
<p>서버 작동이 기본일 것이라고 생각하는 경우, 양쪽의 장점을 취하기 위해 클라이언트 컴포넌트가 되었을 것이다.</p>
<h3 id="1124-서버-컴포넌트는-어떻게-작동하는가">11.2.4 서버 컴포넌트는 어떻게 작동하는가?</h3>
<ul>
<li>서버가 렌더링 요청을 받는다.</li>
<li>서버는 받은 요청에 따라 컴포넌트를 JSON으로 직렬화한다.</li>
<li>빈 부분은 플레이스 홀더 형식으로 남겨둔 채 결과물을 보낸다.</li>
<li>클라이언트 사이드에서 결과물을 역직렬화 한 후 렌더링을 수행한다.</li>
<li>브라우저가 리액트 컴포넌트 트리를 구성한다.</li>
<li>트리를 렌더링한다.</li>
<li>DOM에 커밋한다.</li>
</ul>
<p>여기서 특별한 점</p>
<ul>
<li>클라이언트로 정보를 스트리밍 형태로 보내 빠르게 반응할 수 있다.</li>
<li>컴포넌트별로 번들링이 별개로 되어 있다.</li>
<li>HTML이 아니라 JSON 방식으로 보내진다. 이는 복잡하게 구성된 형태를 조화롭게 구성하기 위해서이다.</li>
</ul>
<h2 id="113-nextjs에서의-리액트-서버-컴포넌트">11.3 Next.js에서의 리액트 서버 컴포넌트</h2>
<p>위에서 살펴본 것과 같이</p>
<p>서버 컴포넌트는 클라이언트 컴포넌트를 불러올 수 없다.
클라이언트 컴포넌트는 서버 컴포넌트를 내용으로 포함할 수 있다.</p>
<h3 id="1131-새로운-fetch-도입과-getserversideprops-getstaticprops-getinitial-props의-삭제">11.3.1 새로운 fetch 도입과 getServerSideProps, getStaticProps, getInitial Props의 삭제</h3>
<p>fetch가 데이터 요청의 표준으로서 사용된다.
비동기적으로 요청하며 다음과 같이 사용한다.</p>
<pre><code class="language-typescript">async function getData() {
  const result = await fetch(&#39;https://api.imagoworks.com&#39;)

  return result.json()
}

export default function Page() {
  const data = await getData()

  return(
    &lt;main&gt;
        &lt;Children data={data} /&gt;
    &lt;/main&gt;
}</code></pre>
<p>내부적으로 캐싱을 하기 때문에 동일한 요청이 서버 컴포넌트 트리 내에 있을 경우, 중복 요청을 방지한다.
<img src="https://velog.velcdn.com/images/velog_sp/post/20a76cb5-62a3-4701-b923-285f089575e5/image.png" alt=""></p>
<h3 id="1132-정적-렌더링과-동적-렌더링">11.3.2 정적 렌더링과 동적 렌더링</h3>
<p>정적 렌더링은 미리 해놓는것 - 캐싱 활용</p>
<p>동적 렌더링은 서버에서 요청이 올때마다 렌더링 하는 것</p>
<p>이것은 모두 결국 fetch가 동작시에 캐싱을 하는지 아닌지에 따라 결정되는데, 그 명세는 다음과 같다.</p>
<ul>
<li>fetch(URL, { cache: &#39;force-cache&#39; }) : 캐싱한다.</li>
<li>fetch(URL, { cache: &#39;no-store}) : 매번 새로운 데이터를 불러온다.</li>
<li>fetch(URL, { next: { revalidate: 10 } }) : 일정 기간동안만 캐싱을 유지한다.</li>
</ul>
<h3 id="1133-캐시와-mutating-그리고-revalidating">11.3.3 캐시와 mutating 그리고 revalidating</h3>
<blockquote>
<p>export const revalidate = 60</p>
</blockquote>
<p>위와 같이 루트에 설정해 놓는 경우, 위의 기간에 따라 캐시를 갱신한다. 갱신 과정에서 공백이 생기지 않도록 다음과 같이 한다.</p>
<p>기간 내엔 캐시된 데이터 보여준다 - 해당시간이 지나도 데이터를 불러오기 전까진 캐싱된 데이터를 보여준다 - 데이터가 불러와지면 데이터를 캐싱하고, 실패했을 경우 이전에 캐시된 데이터를 보여준다.</p>
<h3 id="1134-스트리밍을-활용한-점진적인-페이지-불러오기">11.3.4 스트리밍을 활용한 점진적인 페이지 불러오기</h3>
<p>TTFB(Time To First Byte)의 시간을 줄여주고, 최초 콘텐츠풀 페인팅(FCP; First Contentful Paint)을 개선하는데 큰 도움을 준다.</p>
<h2 id="114-웹팩의-대항마-터보팩의-등장beta">11.4 웹팩의 대항마, 터보팩의 등장(beta)</h2>
<p>기존 자바스크립트로 만들어지고 제공되는 기능을 Rust나 Go등 다른 언어를 사용해 제공
많은 프로젝트에서 바벨을 대신해 사용하고 있다. 웹팩 대비 700배 Vite보다 10배 빠르다고 소개하고 있다고 한다.</p>
<h2 id="115-서버-액션alpha">11.5 서버 액션(alpha)</h2>
<p>API를 생성하지 않고 함수 수준에서 직접 서버에 접근해 데이터 요청 등을 수행할 수 있는 기능이다. 책 기준으로는 서버 액션을 활성화하기 위해 <code>next.config.js</code>에서 실험 기능을 활성화해야 한다고 하고 있으며, &quot;use server&quot;키워드를 사용해야 한다고 한다.</p>
<p>아래와 같은 자세한 내용은 생략한다.</p>
<h3 id="1151-form의-액션">11.5.1 form의 액션</h3>
<h3 id="1152-input의-submit과-image의-formaction">11.5.2 input의 submit과 image의 formAction</h3>
<h3 id="1153-starttransition과의-연동">11.5.3 startTransition과의 연동</h3>
<h3 id="1154-server-mutation이-없는-작업">11.5.4 server mutation이 없는 작업</h3>
<h3 id="1155-서버-액션-사용-시-주의할-점">11.5.5 서버 액션 사용 시 주의할 점</h3>
<h2 id="116-그-밖의-변화">11.6 그 밖의 변화</h2>
<p>이 부분은 책에서도 알아서 찾아보라고 하면서 생략한다. 나도 생략한다.</p>
<p>서버 컴포넌트 등은 단순하게 프로젝트를 구성해서는 사용하기 어렵기 때문에, 프레임워크를 통한 적용이 거의 필수적이며, 리액트 팀도 이러한 부분을 구현하기 위해서는 프레임워크와의 협업이 필요하다고 판단, Vercel등과 활발이 협업하고 있다고 한다. 고려하자.</p>
<h2 id="117-맛보기는-생략한다">11.7 맛보기는 생략한다.</h2>
<h2 id="근황-알아보기">근황 알아보기</h2>
<h3 id="트랜스파일러--컴파일러">트랜스파일러 / 컴파일러</h3>
<p><strong>SWC(Speedy Web Compiler)</strong>
JavaScript 및 TypeScript 컴파일러로, 특히 Babel과 같은 기존 도구들에 비해 그 성능과 속도에서 두드러진 차이를 보인다. Rust로 작성되어 있어 싱글 스레드에서는 Babel보다 최대 20배, 멀티 코어 환경에서는 최대 70배 빠른 속도를 제공한다 
<a href="https://blog.logrocket.com/why-you-should-use-swc/">https://blog.logrocket.com/why-you-should-use-swc/</a></p>
<p><strong>주요 특성 및 비교 :</strong>
성능: SWC는 빌드 시간이 중요한 프로젝트에 적합할 만큼 빠른 속도로 컴파일을 수행한다. Babel, Sucrase, 심지어 esbuild보다도 빠를 수 있는 성능을 자랑한다</p>
<p>*<em>호환성: *</em>
SWC는 최신 JavaScript 기능을 포함한 JSX 및 TypeScript를 지원한다. 주로 새로운 브라우저에 최적화되어 있으며, 구형 브라우저와의 호환성을 위해서는 추가 설정이 필요할 수 있다</p>
<p><strong>인테그레이션:</strong>
SWC는 개발 환경에 통합하기가 비교적 간단하다. Webpack과 같은 인기 있는 번들러와 빌드 시스템에 swc-loader를 사용하거나 Jest의 성능을 향상시키기 위한 플러그인을 제공한다. 설정은 주로 .swcrc 파일을 통해 코드의 변환 방법을 지정함으로써 이루어진다</p>
<p><strong>커뮤니티 및 지원:</strong>
SWC는 Babel에 비해 상대적으로 신생이지만, 주요 프로젝트와 회사에서의 사용 증가로 인해 커뮤니티가 성장하고 있다. </p>
<p>아래 벤치마크 영상을 확인한 결과 바벨보다는 확연히 뛰어난 성능을 보이나 경합은 있는것으로 보인다. 추후 커뮤니티 활성도 등을 고려하여 선택하면 될 것으로 생각된다.
<a href="https://www.youtube.com/watch?v=1p-Vjle0vZ0">https://www.youtube.com/watch?v=1p-Vjle0vZ0</a>
<img src="https://velog.velcdn.com/images/velog_sp/post/bddcc6e9-2090-4ee1-989e-d70f13ba3815/image.png" alt="">
<img src="https://velog.velcdn.com/images/velog_sp/post/6aa54cfc-cf48-4cba-9530-24a2ab26d1ae/image.png" alt="">
<img src="https://velog.velcdn.com/images/velog_sp/post/7b2c3721-366e-4d82-bcac-ed1629623f5b/image.png" alt="">
<img src="https://velog.velcdn.com/images/velog_sp/post/558bb0bf-d05d-40e6-acea-32e444592680/image.png" alt=""></p>
<h3 id="nextjs-버전">NextJS 버전</h3>
<p><a href="https://nextjs.org/blog">https://nextjs.org/blog</a>
위 블로그에서 아주 간략하게 축약된 주요 변경사항들을 확인할 수 있다.
2022.10.25 : 13
2022.12.22 : 13.1
2023.02.23 : 13.2
2023.04.06 : 13.3
2023.05.04 : 13.4
2023.10.19 : 13.5</p>
<p>2023.10.26 : 14
2024.01.18 : 14.1
2024.04.11 : 14.2</p>
<p>현재에는 TurboPack이 정식 적용되었고, ServerAction이 안정화되었으며 여러가지 기능들이 추가되었다.</p>
<h3 id="서버컴포넌트">서버컴포넌트</h3>
<p>Next.js 13의 서버컴포넌트 - <a href="https://blog.logrocket.com/react-server-components-next-js-13/">https://blog.logrocket.com/react-server-components-next-js-13/</a>
2024.02 리액트 트렌드 - <a href="https://www.robinwieruch.de/react-trends/">https://www.robinwieruch.de/react-trends/</a>
2024.02 리액트팀 무슨일하고 있나 - <a href="https://chatgpt.com/c/3d223760-aa69-4356-bd72-abf44306ead3">https://chatgpt.com/c/3d223760-aa69-4356-bd72-abf44306ead3</a></p>
<p>리액트 서버 컴포넌트(React Server Components, RSC)는 성능 향상과 네트워크 요청 감소에 기여한다.</p>
<p>Next.js 13에서는 RSC가 기본적으로 활성화되어 있으며, 데이터를 서버에서 가져오고 이를 스트리밍하는 방식으로 구현되어 있다. 이 방식은 전통적인 SSR과 SSG의 의 장점을 취하고 단점을 상쇄하여 새로운 방향성으로 제안되고 있다.</p>
<p>RSC의 도입은 데이터를 서버에서 컴포넌트 수준에서 가져오는 새로운 아키텍처를 가능하게 한다. 이는 클라이언트와 서버 간의 &#39;워터폴&#39; 요청 방식을 개선하며, 서버에서 데이터 처리가 진행되고 클라이언트는 최종적으로 컴포넌트를 받아 렌더링만 수행함으로써 응답 시간과 성능이 크게 향상된다.</p>
<p>위 링크를 참조하여서 보면, 리액트 팀은 RSC를 더욱 발전시키기 위해 지속적으로 연구하고 개선할 예정이라고 한다. 이에 따라 서버와 클라이언트 간에 일관된 프로그래밍 모델을 사용할 수 있게 하며, 다양한 환경에서 애플리케이션을 운영할 수 있도록 지원할 것으로 예상된다.</p>
<h2 id="리액트-19-1">리액트 19</h2>
<p><strong>동시 렌더링 지원:</strong> 
React 19는 동시 렌더링을 기본 모드로 지원한다. 이는 UI 업데이트를 더 작은 비동기 작업으로 세분화하여, 우선순위가 높은 업데이트를 먼저 처리함으로써 사용자 경험을 개선한다.</p>
<p><strong>Suspense 개선:</strong> 
React 19는 Suspense 기능을 개선하여, 로딩 상태와 데이터 종속성을 선언적으로 처리할 수 있다. 이를 통해 데이터 기반 애플리케이션 개발이 간소화된다.</p>
<p><strong>서버 측 렌더링 개선:</strong>
React 19는 서버 측 렌더링을 통해 TTFB(Time to First Byte)와 SEO 성능을 향상한다. 서버에서의 렌더링 개선은 클라이언트로의 응답 속도를 빠르게 하여 사용자 경험을 향상시킨다.</p>
<p><strong>점진적 도입:</strong> 
React 19는 기존 React 프로젝트와의 호환성을 유지하면서 점진적으로 업그레이드할 수 있는 환경을 제공한다. 이는 개발자가 새로운 기능을 손쉽게 도입할 수 있게 한다.</p>
<p><strong>성능 최적화 기법:</strong> 
React 19는 런타임 효율을 높이고 번들 사이즈를 줄이기 위한 다양한 성능 최적화 기술을 사용한다. 이는 애플리케이션의 렌더링 속도와 메모리 관리를 향상시킨다.</p>
<p><strong>디버깅 개발자 도구:</strong> 
React 19는 개발자가 컴포넌트의 수명 주기와 성능 문제를 보다 정밀하게 진단할 수 있도록 고급 디버깅 및 프로파일링 도구를 제공한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript 모듈과 실행시점]]></title>
            <link>https://velog.io/@velog_sp/JavaScriptModule</link>
            <guid>https://velog.io/@velog_sp/JavaScriptModule</guid>
            <pubDate>Wed, 17 Apr 2024 07:32:44 GMT</pubDate>
            <description><![CDATA[<p>JavaScript에서 모듈은 한 번만 평가된다. 즉, 모듈이 처음으로 임포트될 때 그 모듈의 모든 코드가 실행되며, 그 결과가 캐시된다. 이후 동일한 모듈이 다시 임포트되더라도, 코드는 재실행되지 않고 초기에 캐시된 결과가 재사용된다.</p>
<h2 id="모듈의-실행-시점">모듈의 실행 시점:</h2>
<p><strong>모듈 임포트 시 실행:</strong></p>
<p>모듈이 다른 파일에서 임포트될 때, 해당 모듈의 최상위 레벨 코드는 실행된다. 이 코드에는 함수, 클래스, 변수의 초기화가 포함될 수 있다. 이러한 실행은 모듈이 처음 임포트될 때 단 한 번만 발생한다.</p>
<p><strong>export만 있고 import되지 않는 모듈:</strong></p>
<p>모듈이 단지 export를 하고 다른 곳에서 명시적으로 임포트되지 않는 경우, 그 모듈의 코드는 실행되지 않는다. 모듈의 코드를 실행시키기 위해서는 어딘가에서 그 모듈을 임포트해야 한다.</p>
<p><strong>Import 시점의 실행:</strong></p>
<p>모듈이 임포트되는 순간, 해당 모듈의 코드가 실행되며, export된 객체들이 메모리에 로드된다. 이 후, 해당 모듈을 임포트한 모든 파일에서 export된 객체들을 사용할 수 있다.</p>
<p><strong>예시:</strong>
index.ts 파일이 프로그램의 진입점일 때, index.ts에서 다양한 모듈을 임포트하면, 그 모듈들의 코드는 index.ts가 실행될 때 실행된다. 예를 들어, index.ts에서 다음과 같이 모듈을 임포트하는 경우:</p>
<pre><code class="language-typescript">// index.ts
import &#39;./setup&#39;;  // setup 모듈에서 코드가 실행됨
import { functionFromModuleA } from &#39;./moduleA&#39;; // moduleA의 코드가 실행됨

functionFromModuleA();</code></pre>
<p>여기서 setup 모듈과 moduleA의 코드는 index.ts가 로드되는 시점에 실행된다. setup은 명시적으로 아무것도 import하지 않아도 그 내부의 코드가 실행되며, moduleA는 필요한 함수나 변수를 export한다.</p>
<p>결론: 모듈은 임포트된 시점에 실행되며, 해당 모듈의 모든 최상위 코드가 처리된다. export만 있고 실제로 임포트되지 않은 모듈의 코드는 실행되지 않는다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[AI]Nvidia에서 개설한 강좌]]></title>
            <link>https://velog.io/@velog_sp/AINvidia%EC%97%90%EC%84%9C-%EA%B0%9C%EC%84%A4%ED%95%9C-%EA%B0%95%EC%A2%8C</link>
            <guid>https://velog.io/@velog_sp/AINvidia%EC%97%90%EC%84%9C-%EA%B0%9C%EC%84%A4%ED%95%9C-%EA%B0%95%EC%A2%8C</guid>
            <pubDate>Wed, 27 Mar 2024 01:10:52 GMT</pubDate>
            <description><![CDATA[<p><a href="https://news.hada.io/topic?id=14007&amp;utm_source=teams&amp;utm_medium=bot&amp;utm_campaign=1566">https://news.hada.io/topic?id=14007&amp;utm_source=teams&amp;utm_medium=bot&amp;utm_campaign=1566</a></p>
<p>Self-Paced Courses 에는 유료/무료가 섞여있는데, 이쪽에도 무료 강좌들 괜찮은게 별도로 있음
무료 강좌
Generative AI Explained
Building a Brain in 10 Minutes
An Even Easier Introduction to CUDA
Essentials of Developing Omniverse Kit Applications
Building Video AI Applications at the Edge on Jetson Nano
Assemble a Simple Robot in Isaac Sim
Build Beautiful, Custom UI for 3D Tools on NVIDIA Omniverse
Develop, Customize, and Publish in Omniverse With Extensions
Disaster Risk Monitoring Using Satellite Imagery
Getting Started with AI on Jetson Nano
Getting Started with USD for Collaborative 3D Workflows
Easily Develop Advanced 3D Layout Tools on NVIDIA Omniverse
Getting Started with DOCA Flow
How to Build Custom 3D Scene Manipulator Tools on NVIDIA Omniverse
Digital Fingerprinting with MorpheusTM
Introduction to DOCA for DPUs
Self-Paced Courses의 무료 강좌들
Building RAG Agents for LLMs
Augmenting LLMs using Retrieval Augmented Generation
Accelerate Data Science Workflows with Zero Code Changes</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Jest]import 시 디렉터리 내의 index.ts를 인식하지 못하는 문제]]></title>
            <link>https://velog.io/@velog_sp/Jestimport-%EC%8B%9C-%EB%94%94%EB%A0%89%ED%84%B0%EB%A6%AC-%EB%82%B4%EC%9D%98-index.ts%EB%A5%BC-%EC%9D%B8%EC%8B%9D%ED%95%98%EC%A7%80-%EB%AA%BB%ED%95%98%EB%8A%94-%EB%AC%B8%EC%A0%9C</link>
            <guid>https://velog.io/@velog_sp/Jestimport-%EC%8B%9C-%EB%94%94%EB%A0%89%ED%84%B0%EB%A6%AC-%EB%82%B4%EC%9D%98-index.ts%EB%A5%BC-%EC%9D%B8%EC%8B%9D%ED%95%98%EC%A7%80-%EB%AA%BB%ED%95%98%EB%8A%94-%EB%AC%B8%EC%A0%9C</guid>
            <pubDate>Wed, 28 Feb 2024 07:39:56 GMT</pubDate>
            <description><![CDATA[<h1 id="01-개요">01 개요</h1>
<p>Jest에서 ModuleNameMapper를 통해 경로별칭을 이용하여 불러오는 과정에서 발생한 문제이다.
최종수정일 : 2024.02.28</p>
<hr>
<h1 id="02-source-code">02 source code</h1>
<p><strong>/src/features/featuredir/feature.spec.ts</strong></p>
<pre><code class="language-ts">import { mine } from &#39;mine&#39;;

describe(&#39;captureBatchThumbnails&#39;, () =&gt; {
  it(&#39;Initialize CrownCase&#39;, () =&gt; {
    console.log(mine(1, 2));
  });
});</code></pre>
<p><strong>/src/mine/index.ts</strong></p>
<pre><code class="language-ts">export function mine(a: number, b: number): number {
  return a + b;
}</code></pre>
<p><strong>/jest.config.js</strong></p>
<pre><code class="language-json">export default {
  preset: &#39;ts-jest&#39;,
  testMatch: [&#39;**/__tests__/**/*.+(ts|tsx|js)&#39;, &#39;**/?(*.)+(spec|test).+(ts|tsx|js)&#39;],
  transform: {
    &#39;^.+\\.(ts|tsx)$&#39;: [&#39;ts-jest&#39;, { tsconfig: &#39;tsconfig.esm.json&#39; }],
  },
  testPathIgnorePatterns: [&#39;/node_modules/&#39;, &#39;/dist/&#39;],
  roots: [&#39;&lt;rootDir&gt;&#39;],
  moduleFileExtensions: [&#39;js&#39;, &#39;mjs&#39;, &#39;cjs&#39;, &#39;jsx&#39;, &#39;ts&#39;, &#39;tsx&#39;, &#39;json&#39;, &#39;node&#39;],
  moduleNameMapper: {
    &#39;^@constants/(.*)$&#39;: &#39;&lt;rootDir&gt;/src/constants/$1&#39;,
    &#39;^@types/(.*)$&#39;: &#39;&lt;rootDir&gt;/src/types/$1&#39;,
    &#39;^classes/(.*)$&#39;: &#39;&lt;rootDir&gt;/src/classes/$1&#39;,
    &#39;^features/(.*)$&#39;: &#39;&lt;rootDir&gt;/src/features/$1&#39;,
    &#39;^lib/(.*)$&#39;: &#39;&lt;rootDir&gt;/src/lib/$1&#39;,
    &#39;^managers/(.*)$&#39;: &#39;&lt;rootDir&gt;/src/managers/$1&#39;,
    &#39;^modules/(.*)$&#39;: &#39;&lt;rootDir&gt;/src/modules/$1&#39;,
    &#39;^utils/(.*)$&#39;: &#39;&lt;rootDir&gt;/src/utils/$1&#39;,
    &#39;^mine/(.*)$&#39;: &#39;&lt;rootDir&gt;/src/mine/$1&#39;,
  },
};</code></pre>
<hr>
<h1 id="03-문제">03 문제</h1>
<p><img src="https://velog.velcdn.com/images/velog_sp/post/71a82854-e7b9-4fa8-954e-1327306de902/image.png" alt=""></p>
<hr>
<h1 id="04-해결">04 해결</h1>
<p>ModuleNameMapper에서 하위항목이 있어야하도록 정의되었기 때문이다. 다음과 같이 변경하였다.
<strong>/jest.config.js</strong></p>
<pre><code class="language-json">export default {
  preset: &#39;ts-jest&#39;,
  testMatch: [&#39;**/__tests__/**/*.+(ts|tsx|js)&#39;, &#39;**/?(*.)+(spec|test).+(ts|tsx|js)&#39;],
  transform: {
    &#39;^.+\\.(ts|tsx)$&#39;: [&#39;ts-jest&#39;, { tsconfig: &#39;tsconfig.esm.json&#39; }],
  },
  testPathIgnorePatterns: [&#39;/node_modules/&#39;, &#39;/dist/&#39;],
  roots: [&#39;&lt;rootDir&gt;&#39;],
  moduleFileExtensions: [&#39;js&#39;, &#39;mjs&#39;, &#39;cjs&#39;, &#39;jsx&#39;, &#39;ts&#39;, &#39;tsx&#39;, &#39;json&#39;, &#39;node&#39;],
  moduleNameMapper: {
    &#39;^@constants(.*)$&#39;: &#39;&lt;rootDir&gt;/src/constants$1&#39;,
    &#39;^@types(.*)$&#39;: &#39;&lt;rootDir&gt;/src/types$1&#39;,
    &#39;^classes(.*)$&#39;: &#39;&lt;rootDir&gt;/src/classes$1&#39;,
    &#39;^features(.*)$&#39;: &#39;&lt;rootDir&gt;/src/features$1&#39;,
    &#39;^lib(.*)$&#39;: &#39;&lt;rootDir&gt;/src/lib$1&#39;,
    &#39;^managers(.*)$&#39;: &#39;&lt;rootDir&gt;/src/managers$1&#39;,
    &#39;^modules(.*)$&#39;: &#39;&lt;rootDir&gt;/src/modules$1&#39;,
    &#39;^utils(.*)$&#39;: &#39;&lt;rootDir&gt;/src/utils$1&#39;,
    &#39;^mine(.*)$&#39;: &#39;&lt;rootDir&gt;/src/mine$1&#39;,
  },
};</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DevLog]Velog to Notion]]></title>
            <link>https://velog.io/@velog_sp/DevLogVelog-to-Notion</link>
            <guid>https://velog.io/@velog_sp/DevLogVelog-to-Notion</guid>
            <pubDate>Wed, 03 Jan 2024 10:06:53 GMT</pubDate>
            <description><![CDATA[<p>Post와 Series 2계층의 형태에 비해 지식을 정리하기에 좋은
다계층 상하위관계, 문서간 참조가 쉬운 Wiki 형태를 갖춘 Notion으로 기술 블로그를 이전한다.
링크는 아래와 같다.</p>
<p>(이전 작업 진행중)</p>
<p><a href="https://philipsung.notion.site/f1bdfa4049c3418b995fef803882a542?v=42fee1ecdb0b46e09e6419a31c533c6c&amp;pvs=4">https://philipsung.notion.site/f1bdfa4049c3418b995fef803882a542?v=42fee1ecdb0b46e09e6419a31c533c6c&amp;pvs=4</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ML·DL]Recommender System Basics]]></title>
            <link>https://velog.io/@velog_sp/MLDLRecommender-System-Basics</link>
            <guid>https://velog.io/@velog_sp/MLDLRecommender-System-Basics</guid>
            <pubDate>Thu, 23 Nov 2023 13:42:22 GMT</pubDate>
            <description><![CDATA[<h2 id="01-개요">01 개요</h2>
<p>본 문서에서는 딥러닝 기반 추천 시스템을 다루기 위해, 추천 시스템 일반에 대하여 개괄적인 내용을 다룬다.</p>
<p>최종수정일 : 2023.11.23
<br><br></p>
<hr>
<h2 id="02-추천시스템-구조">02 추천시스템 구조</h2>
<p>참조 : <a href="https://yamalab.tistory.com/117">https://yamalab.tistory.com/117</a></p>
<p>2019년 기준 추천 시스템은 일반적으로 아래와 같은 절차를 따른다고 한다.
<img src="https://velog.velcdn.com/images/velog_sp/post/eab20c08-c2f1-4770-920d-5171fbc732bc/image.png" alt=""></p>
<p><strong>Candidate generate part</strong></p>
<p>수많은 상품 중, 후보가 될 만한 상대적으로 적은 수의 상품으로 선택지를 줄이는 것을 목적으로 한다. 후보군 산출 단계에서는 여러 개의 전략들을 합쳐서(merge) 유저의 관심사가 최대한 많이 포함되도록 coverage를 넓히는 것이 좋다.</p>
<p><strong>Intention prediction part</strong></p>
<p>의도 예측 단계에서는 유저의 ‘최신 행동’에 기반하여 click, buy 등의 다음 행동을 예측한다.</p>
<p><strong>Ranking part(prediction CTR/CR)</strong></p>
<p>의도 예측 단계 후에, 지금까지 선정된 수백 개의 candidate를 내로우 다운(Narrow down) 형식으로 추려낼 필요가 있다. 이를 위해 CTR/CR(Click-Through Rate/ Click Rate)를 예측하는 모델을 통해 상품이 노출될 순위를 결정한다.</p>
<p><img src="https://velog.velcdn.com/images/velog_sp/post/2f3d7343-869e-489f-a43a-9dfca051f16d/image.png" alt=""></p>
<p><br><br></p>
<hr>
<h2 id="03-추천시스템의-평가">03 추천시스템의 평가</h2>
<h3 id="0301-basics">03.01 Basics</h3>
<p>추천시스템을 평가하기 위하여는 아래 개념들에 대해 알아야 한다.</p>
<p><strong>Precision</strong>
$Precision = \frac{True Positive}{TruePositive + False Positive}$</p>
<p>e.g. 범죄자라고 판단한 사람 중 진짜 범죄자가 몇명인가에 대한 비율이다.
e.g. 우리가 추천한 아이템 중에 사용자가 정말 관심있어하는 아이템의 비율이다.</p>
<p><strong>Recall</strong>
$Recall = \frac{True Positive}{True Positive + False Negative}$</p>
<p>e.g. 현재까지 본 범죄자들 중에서 실제로 범죄자라고 판단한 경우가 몇명인가에 대한 비율이다.
e.g. 실제로 사용자가 관심있어하는 아이템 중에 우리가 추천한 아이템의 비율이다.</p>
<blockquote>
<p>우리가 추천한 아이템 개수: 5
추천한 아이템 중 사용자가 관심있어하는 아이템 개수 : 2
실제로 사용자가 관심있어하는 아이템 개수 : 3</p>
<p>Precision = 2/5
Recall = 2/3</p>
</blockquote>
<p><strong>~@K</strong>
추천된 리스트 중에서 상위 K개만큼만 추출하여 평가하겠다는 의미이다.</p>
<hr>
<h3 id="0302-precisionk">03.02 Precision@K</h3>
<p>$Precision@K = \frac{user;interested;items}{recommended;k;items}$</p>
<p>추천한 K개의 아이템 중 사용자가 관심있어하는 아이템의 수이며, 순서 등은 고려되지 않는다.</p>
<hr>
<h3 id="0303-recallk">03.03 Recall@K</h3>
<p>$Recall@K = \frac{recommended;interested;item}{all;interested;items;of;user}$</p>
<p>사용자가 관심있어하는 아이템의 수 대비 추천된 실제 관심있는 아이템의 수이며, @K의 경우 K개를 넘을 수 없다.</p>
<hr>
<h3 id="0304-mrr--mean-reciprocal-rank">03.04 MRR : Mean Reciprocal Rank</h3>
<p>$MRR = \frac{1}{Q}\sum_{i}^Q \frac{1}{rank_{i}}$</p>
<p>MRR은 각각의 질의 Q에 대해, 추천해 준 품목 중 사용자의 선호가 있는 항목이 최초로 등장한 것이 몇번째인지 파악하고, 그 역수를 취한다. 첫번째만 취하므로, 최적의 상품이 무엇인가에 대해 초점을 둔다.</p>
<p>첫번째 질의에서, 사용자가 선호하는 아이템이 두번째에, 두번째 질의에서 사용자가 선호하는 아이템이 세번째에 있었다면 계산식은 다음과 같다.</p>
<p>$MRR = \frac{1}{2}*(\frac{1}{2} + \frac{1}{3})$</p>
<hr>
<h3 id="0305-map--mean-average-precision">03.05 MAP : Mean Average Precision</h3>
<p><strong>Average Precision</strong></p>
<p>$AP@K = \frac{1}{K}\sum_{i=1}^K P(i)*rel(i)$</p>
<p>P(i) : 해당 인덱스 i까지의 Precision
rel(i) : 해당 인덱스 i에서 user engagement가 일어났는지 여부(0 | 1)</p>
<table>
<thead>
<tr>
<th>Recommandations</th>
<th>Precision@K(k=3)</th>
<th>AP@K(k=3)</th>
</tr>
</thead>
<tbody><tr>
<td>[0, 0, 1] 추천 3, 선택1(3번)</td>
<td>[0, 0, 1/3]</td>
<td>(1/3)(1/3) = 0.11</td>
</tr>
<tr>
<td>[0, 1, 1] 추천 3, 선택2(2,3번)</td>
<td>[0, 1/2, 2/3]</td>
<td>(1/3)(1/2+2/3) = 0.38</td>
</tr>
<tr>
<td>[1, 1, 1] 추천 3, 선택3(1,2,3번)</td>
<td>[1/1, 2/2, 3/3]</td>
<td>(1/3)(1+1+1) = 1</td>
</tr>
<tr>
<td>[0, 1, 0] 추천 3, 선택1(2번)</td>
<td>[0, 1/2, 0]</td>
<td>(1/3)(1/2) = 0.17</td>
</tr>
</tbody></table>
<p>위 AP는 한명의 사용자에 대한 것으로, 전체 사용자에 대해 AP를 평균 낸 것을 mAP라고 한다.</p>
<p>$MAP@K = \frac{1}{|U|}\sum_{u = 1}^{|U|}(AP@K)_u$</p>
<hr>
<h3 id="0306-ndcgk--normalized-discounted-cumulative-gain">03.06 nDCG@K : Normalized Discounted Cumulative Gain</h3>
<p><strong>DCG</strong></p>
<p>$DCG_p = \sum_{i=1}^{p}\frac{rel_i}{\log_2(i+1)}$ 또는 $DCG_p = \sum_{i=1}^{p}\frac{2^{rel_i}-1}{\log_2(i+1)}$</p>
<p>DCG는 추천항목의 관련성(별점 등)을 순위에 로그를 취해 나눈 값으로 나누어 순차적으로 합한 값이다. 후순위의 항목일수록 분모가 커지고, 관련성이 높을수록 분자가 커지므로  점수가 높을수록 더 뛰어난 성능을 나타낸다.</p>
<p><strong>IDCG(Ideal DCG)</strong>
IDCG는 연관성이 높은 항목 순으로 높은 순위에 배치한 이상적인 DCG값을 이야기 한다. 연관성이 [5,4,3,2,1]인 항목이 있는 경우, IDCG는 다음과 같다.</p>
<p>$IDCG = \frac{5}{\log_2{2}}+\frac{4}{\log_2{3}}+\frac{3}{\log_2{4}}+\frac{2}{\log_2{5}}+\frac{1}{\log_2{6}}$</p>
<p><strong>nDCG</strong></p>
<p>$nDCG_p = \frac{DCG_p}{IDCG_p}$</p>
<p>DCG를 IDCG로 나누어 얻은 정규화된 값을 nDCG라고 부른다.</p>
<hr>
<h3 id="0308-mae--mean-absolute-error">03.08 MAE : Mean Absolute Error</h3>
<p>$MAE = \frac{1}{|\hat{R}|}\sum_{\hat{r}<em>{ui}\in\hat{R}} |r</em>{ui} - \hat{r}_{ui}|$</p>
<p>$_{\hat{R} = 예측한;평점의;개수}$</p>
<p>MAE는 추천항목의 적절성을 평가하는 것이 아니고, 항목의 평점예측을 수행하여 평가한다.</p>
<hr>
<h3 id="0307-rmse--root-mean-square-error">03.07 RMSE : Root Mean Square Error</h3>
<p>$RMSE = \sqrt{\frac{1}{|\hat{R}|}\sum_{\hat{r}<em>{ui}\in\hat{R}} (r</em>{ui} - \hat{r}_{ui})^2}$</p>
<p>RMSE는 추천항목의 적절성을 평가하는 것이 아니고, 항목의 평점예측을 수행하여 평가한다.</p>
<p><br><br></p>
<hr>
<h2 id="04-추천시스템-종류-및-방법론">04 추천시스템 종류 및 방법론</h2>
<p><strong>[ 추천을 받는 대상자 / 추천되는 대상 / 추천 규칙 자체]</strong> 중 어느쪽에 중점을 두는지에 따라 크게 <strong>[ Collaborative / Content-based / Rule-based ]</strong> 로 나뉜다. 조합되는 경우 Hybrid로 부른다. 이에 대한 내용은 깊게 다루지 않는다.</p>
<p>대신, 위 분류와 상관 없이, 독립적으로 또는 복합적으로 적용되는 추천 방법론들에 대해 다룬다. 아래 방법론들은 중복되거나 서로 포함관계에 있을 수 있다.</p>
<p>(작성중 - 예상되는 주요 방법론 :)</p>
<h3 id="0401-simple-rule-based">04.01 Simple Rule based</h3>
<h3 id="0402-matrix-factorization-based">04.02 Matrix factorization based</h3>
<h3 id="0403-sequential-based">04.03 Sequential based</h3>
<h3 id="0404-embedding-based">04.04 Embedding based</h3>
<h3 id="0405-deep-learning-based">04.05 Deep Learning based</h3>
<h3 id="0406-transformer-based">04.06 Transformer based</h3>
<h3 id="0407-generative-model-based">04.07 Generative model based</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[(작성중)[CodeConvention]ESLint]]></title>
            <link>https://velog.io/@velog_sp/CodeConventionESLint</link>
            <guid>https://velog.io/@velog_sp/CodeConventionESLint</guid>
            <pubDate>Thu, 23 Nov 2023 04:11:34 GMT</pubDate>
            <description><![CDATA[<h2 id="01-개요">01 개요</h2>
<p>ESLint는 코딩 컨벤션에 위배되는 코드나 안티 패턴을 자동 검출하는 도구다. 코딩 컨벤션은 사전에 작성된 특정 형태를 따를 수도 있고, 사용자가 직접 작성할 수 있다.</p>
<h2 id="02-생성">02 생성</h2>
<blockquote>
<p>npx eslint --init</p>
</blockquote>
<h2 id="03-규칙rules">03 규칙(Rules)</h2>
<p><strong>no-unused-vars</strong></p>
<blockquote>
<pre><code class="language-js">module.exports = {
 ...
 rules: {
   &quot;no-unused-vars&quot;: &quot;off&quot;
 }</code></pre>
</blockquote>
<h2 id="99">99</h2>
<p>React에서 chrome API를 사용하려 하면 다음과 같은 오류를 확인할 수 있다.</p>
<blockquote>
<p>&#39;chrome&#39; is not defined  no-undef</p>
</blockquote>
<p>이는 다음과 같은 세 가지 방법으로 해결할 수 있다.</p>
<p><strong>01. add <code>/*global chrome*/</code> at top</strong></p>
<blockquote>
<pre><code class="language-js">/*global chrome*/
import React, { Component } from &#39;react&#39;;
import &#39;./App.css&#39;;</code></pre>
</blockquote>
<p><strong>02. modify eslint rule locally</strong></p>
<blockquote>
<p>/* eslint-disable no-undef */</p>
<pre><code class="language-js">function callback(val) {
   console.log(val)
}

chrome.topSites.get(callback);
/* eslint-enable no-undef */</code></pre>
</blockquote>
<p><strong>03. modify eslint config</strong></p>
<blockquote>
<pre><code class="language-js">module.exports = {
 ...otherConfigs,
 globals: {
   chrome: true
 }
}</code></pre>
</blockquote>
<p>리액트를 사용할 때 처음에 ESLint configuration이 숨겨진 채로 내부적으로 작동하는데, 이 때 no-undef rule이 활성화되어 있기 때문에 발생하는 문제이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[(작성중)[WEBDEV]Chrome Extension Basics]]></title>
            <link>https://velog.io/@velog_sp/WEBDEVChrome-Extension-Basics</link>
            <guid>https://velog.io/@velog_sp/WEBDEVChrome-Extension-Basics</guid>
            <pubDate>Thu, 23 Nov 2023 04:02:06 GMT</pubDate>
            <description><![CDATA[<h2 id="01-개요">01 개요</h2>
<p>본 문서에서는 크롬 익스텐션 개발을 위한 개괄적인 내용을 다룬다.</p>
<p>(작성중)</p>
<h2 id="02-구조">02 구조</h2>
<p><img src="https://velog.velcdn.com/images/velog_sp/post/50414989-1107-4d73-bb4f-6ff751d355f1/image.png" alt=""></p>
<p>크롬익스텐션은 크게 <code>background</code>,<code>content-script</code>,<code>popup</code>세 가지 요소로 구성되며, 이 세 가지 구성요소를 포함하여 extenstion에 관한 사항들은 <code>manifest.json</code>에 명기된다.</p>
<p><strong>manifest.json</strong></p>
<p><strong>background</strong>
크롬 익스텐션이 실제로 동작하는데 필요한 스크립트이다
storage에 저장하거나하는 등의 액션은 모두 background 스크립트에서만 동작 가능하다
별도의 개발자 도구 창을 제공한다.</p>
<p><strong>content-script</strong>
사용자 화면의 DOM에 접근할 수 있는 유일한 스크립트</p>
<p><strong>popup</strong>
크롬 익스텐션 버튼을 눌렀을 때 아래에 뜨는 팝업창을 위한 스크립트 및 html</p>
<h3 id="0201-manifestjson">02.01 manifest.json</h3>
<p>기본정보 등록
service-worker 등록
content-script 등록
popup 등록
permissions</p>
<h2 id="03">03</h2>
<p>크롬 익스텐션을 구성하고 있는 세 가지 요소는 Message Passing 방식으로 소통한다.
참조 : <a href="https://velog.io/@broccolism/%ED%81%AC%EB%A1%AC-%EC%9D%B5%EC%8A%A4%ED%85%90%EC%85%98-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EB%81%BC%EB%A6%AC-%ED%86%B5%EC%8B%A0%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95">https://velog.io/@broccolism/%ED%81%AC%EB%A1%AC-%EC%9D%B5%EC%8A%A4%ED%85%90%EC%85%98-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EB%81%BC%EB%A6%AC-%ED%86%B5%EC%8B%A0%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</a></p>
<h3 id="0301-popup---background">03.01 popup - background</h3>
<blockquote>
<pre><code class="language-js">//sender
chrome.runtime.sendMessage(&quot;message&quot;);

//receiver
chrome.runtime.onMessage.addListener((message, sender, sendResponse) =&gt; {
   console.log(message);
});</code></pre>
</blockquote>
<h3 id="0302-contentscript---background">03.02 contentScript - background</h3>
<blockquote>
<pre><code class="language-js">// content-script.js
chrome.runtime.sendMessage({ &quot;key&quot;: &quot;value&quot; });

// background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) =&gt; {
   console.log(message);
});</code></pre>
</blockquote>
<h2 id="99-참조자료">99 참조자료</h2>
<p>익스텐션개요 <a href="https://tidyline.gitbook.io/today-i-learned/etc/chromeextension">https://tidyline.gitbook.io/today-i-learned/etc/chromeextension</a>
네이버카페글제목가져오는Extension만들기 <a href="https://m.blog.naver.com/siryua/221496597007">https://m.blog.naver.com/siryua/221496597007</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[pandas]판다스 자료구조]]></title>
            <link>https://velog.io/@velog_sp/pandasDataStructure</link>
            <guid>https://velog.io/@velog_sp/pandasDataStructure</guid>
            <pubDate>Wed, 22 Nov 2023 11:23:14 GMT</pubDate>
            <description><![CDATA[<h2 id="01-개요">01 개요</h2>
<p>판다스에는 크게 세 가지 자료구조가 존재한다. 1차원 자료구조인 Series, 2차원 자료구조인 DataFrame, 3차원 자료구조인 Panel이 있다. 본 문서에서는 판다스에서 사용하는 자료구조와 그 속성, 메서드 등에 대해서 다룬다.</p>
<p>최종수정일 : 2023.11.22
<br><br></p>
<hr>
<h2 id="02-자료구조">02 자료구조</h2>
<h3 id="0201-series">02.01 Series</h3>
<p>Series는 value와 index의 형태를 지니는 Pandas의 자료 구조이다. 일련의 시퀀스 데이터를 받아들이는데, 별도의 인덱스 레이블을 지정하지 않으면 자동적으로 0부터 시작되는 디폴트 정수 인덱스를 사용한다.</p>
<blockquote>
<pre><code class="language-python">import pandas as pd

dict = {&#39;a&#39;:1, &#39;b&#39;:2, &#39;c&#39;:3}
list = [1,3,7]

indexed_series = pd.Series(dict)
unindexed_series = pd.Series(list)

print(indexed_series)
print(unindexed_series)

#result
a  1
b  2
c  3
dtype: int64

0  1
1  3
2  7
dtype: int64</code></pre>
</blockquote>
<h3 id="0202-dataframe">02.02 DataFrame</h3>
<p>DataFrame은 시퀀스 데이터를 받아 column과 row로 구성된 2차원 자료구조를 형성한다.</p>
<blockquote>
<pre><code class="language-python">import pandas as pd

df_dictionary = pd.DataFrame({&#39;a&#39;: [1,2,3], &#39;b&#39; : [4,6,8]})
df_list = pd.DataFrame([3,6,9],[4,8,12])

#result
   a  b
0  1  4
1  2  6
2  3  8

   0  1  2
0  3  6  9
1  4  8  12</code></pre>
</blockquote>
<p>딕셔너리로 생성할 경우 딕셔너리 키가 column index가 되며, 값은 해당 열의 원소가 된다. 리스트로 생성할 경우 하나의 리스트가 하나의 행이 된다.</p>
<h3 id="0203-panel">02.03 Panel</h3>
<p>Panel은 3차원 자료구조이다.</p>
<p><br><br></p>
<hr>
<h2 id="03-연산">03 연산</h2>
<h3 id="0301-indexing">03.01 Indexing</h3>
<h4 id="030101-series-indexing">03.01.01 Series Indexing</h4>
<blockquote>
<pre><code class="language-python">dict = {&#39;a&#39;:1, &#39;b&#39;:2, &#39;c&#39;:3}
list = [1,3,7]

indexed_series = pd.Series(dict)
unindexed_series = pd.Series(list)

indexed_series[&#39;a&#39;]
#result : 1

unindexed_series[3]
#result : 7</code></pre>
</blockquote>
<p>Series는 일반 리스트나 딕셔너리처럼 접근할 수 있다.</p>
<h4 id="030102-dataframe-indexing">03.01.02 DataFrame Indexing</h4>
<blockquote>
<pre><code class="language-python">df_dictionary = pd.DataFrame({&#39;a&#39;: [4,8,12], &#39;b&#39; : [3,6,9]})

#column indexing
df_dictionary[&#39;a&#39;]
#result : 
0    4
1    8
2    12

#iloc value indexing
df_dictionary.iloc[1,1]
#result : 6

#iloc range indexing
df_dictionary.iloc[0:2,0:2]
#result :
   a  b
0  4  3
1  8  6

#sequence indexing
boolean_series = pd.Series([True,True,False])
df_dictionary[boolean_series]
#result :
   a  b
0  4  3
1  8  6</code></pre>
</blockquote>
<p><strong>column indexing</strong>
DataFrame에서 열 인덱스로 인덱싱할 경우 해당 열 전체가 추출된다.</p>
<p><strong>iloc indexing</strong>
위치를 지정할 경우 해당 위치의 값이,
범위를 지정할 경우 해당 지점 왼쪽 위까지의 프레임이 포함된다.</p>
<p><strong>sequnce indexing</strong>
데이터프레임의 행 수와 같은 크기의 boolean sequence(series, list)를 인덱싱에 사용할 경우, 사용된 시퀀스의 값이 True인 행만을 반환한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python]개발환경 설정]]></title>
            <link>https://velog.io/@velog_sp/PythonDevEnv</link>
            <guid>https://velog.io/@velog_sp/PythonDevEnv</guid>
            <pubDate>Sat, 18 Nov 2023 02:44:38 GMT</pubDate>
            <description><![CDATA[<h2 id="01-개요">01 개요</h2>
<p>대부분의 프로젝트에서는 외부 라이브러리의 목록과 버전을 별도로 관리하여 언제나 같은 실행환경을 구축하는 방법을 가지고 있다. JavaScript기반 프로젝트는 일반적으로 package.json을 통해 관리한다.</p>
<p>파이썬 도한 마찬가지로 이렇게 라이브러리 목록을 가지고 있으며, 이를 실행하기 위한 실행 환경을 프로젝트마다 별도로 구축하는 것이 가능하다. 본 문서에서는 이와 관련된 내용을 정리한다.</p>
<p>최종수정일 : 2023.12.01</p>
<p><br><br></p>
<hr>
<h2 id="02-현재-환경-확인">02 현재 환경 확인</h2>
<h3 id="0201-파이썬의-설치-경로-확인">02.01 파이썬의 설치 경로 확인</h3>
<blockquote>
<pre><code class="language-py">import sys
sys.executable

#result : &#39;C:\\Users\\myPC\\.virtualenvs\\myPC-aubkC56d\\Scripts\\python.exe&#39;</code></pre>
</blockquote>
<h3 id="0202-모듈-경로-확인">02.02 모듈 경로 확인</h3>
<blockquote>
<pre><code class="language-py">import numpy

print(np)

#result : &lt;module &#39;numpy&#39; from &#39;C:\\Users\\myPC\\.virtualenvs\\myPC-aubkC56d\\Lib\\site-packages\\numpy\\__init__.py&#39;&gt;</code></pre>
</blockquote>
<p><br><br></p>
<hr>
<h2 id="03-python-버전-관리">03 Python 버전 관리</h2>
<h3 id="0301-pyenv">03.01 pyenv</h3>
<p>모듈에 따라 사용 가능한 다양한 Python의 버전을 유동적으로 사용하기 위해서 pyenv를 사용한다. windows 운영체제의 경우 2023년 11월 기준 정식으로 지원하지는 않으나, kirankotari의 pyenv-win의 fork를 사용한다.</p>
<blockquote>
<pre><code class="language-sh">Invoke-WebRequest -UseBasicParsing -Uri &quot;https://raw.githubusercontent.com/pyenv-win/pyenv-win/master/pyenv-win/install-pyenv-win.ps1&quot; -OutFile &quot;./install-pyenv-win.ps1&quot;; &amp;&quot;./install-pyenv-win.ps1&quot;
</code></pre>
</blockquote>
<p>about_Execution_Policies오류가 발생할 경우 아래와 같은 방법을 사용한다.</p>
<blockquote>
<pre><code class="language-sh">Get-ExecutionPolicy
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned</code></pre>
</blockquote>
<p>pyenv가 설치된 경우, 아래와 같은 명령어로 사용할 파이썬의 버전을 선택한다.</p>
<blockquote>
<pre><code class="language-bash">#show installable versions of python
pyenv install -l 

#install python version 3.11.6
pyenv install 3.11.6

#set global python version 3.11.6
pyenv global 3.11.6

#set directory&#39;s local python version 3.9.13
mkdir myDirectory
cd ./myDirectory
pyenv local 3.9.13

#show installed python versions
pyenv versions</code></pre>
</blockquote>
<p><br><br></p>
<hr>
<h2 id="04-가상환경-설정">04 가상환경 설정</h2>
<p>Pipenv는 javascript 개발환경에서의 package.json과 같은 패키지 관리 시스템의 장점을 도입하는 것과 같은 효과를 같는다.</p>
<p>python의 다른 가상환경 설정 방법인 venv는 쉽게 가상환경을 구축할 수 있지만, 패키지 관리는 pip를 사용한다. pip는 종속성 관리를 requirementes.txt로 수동으로 관리한다. 패키지를 삭제할 때도 종속성을 수동으로 관리해야 하는 불편함이 있기 때문에 pipenv로 편리하고 안정적으로 패키지 관리를 할 수 있다.</p>
<h3 id="0401-설치">04.01 설치</h3>
<blockquote>
<pre><code class="language-bash">pip install pipenv

mkdir myDirectory
cd myDirectory

pipenv --python 3.11.6
pipenv shell
pipenv install torch
#(NewVEnv-IscNwJwu) C:\Users\myPC\Desktop\NewVEnv&gt;</code></pre>
</blockquote>
<p>위와 같은 과정을 통해 pipenv shell에 접속하여 패키지를 관리할 수 있다. <code>pipenv --python version</code>을 통해 Pipfile 파일을 생성할 수 없는 경우, 상위 폴더에 있는 Pipfile을 찾아 삭제해본다.</p>
<p>위와 같이 실행한 경우 Windows10 환경에서는 일반적으로 아래 경로에 가상환경에 대한 메타데이터가 생성된다.</p>
<blockquote>
<p>C:\Users\<em>UserName</em>\.virtualenvs</p>
</blockquote>
<p><br><br></p>
<hr>
<h2 id="05-가상환경에서-패키지-설치">05 가상환경에서 패키지 설치</h2>
<h3 id="0501-pytorch-cuda">05.01 pytorch cuda</h3>
<blockquote>
<pre><code class="language-bash">pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121</code></pre>
</blockquote>
<p>파이토치에서 제공하는 위와 같은 옵션은 보안상의 문제로 사용이 불가능 할 수 있다. 이러한 경우 Pipfile을 아래와 같이 수정하여 옵션을 적용할 수 있다.</p>
<blockquote>
<pre><code class="language-python">#Pipfile
[[source]]
url = &quot;https://pypi.org/simple&quot;
verify_ssl = true
name = &quot;pypi&quot;

[[source]]
url = &quot;https://download.pytorch.org/whl/cu121&quot;
verify_ssl = false
name = &quot;pytorch&quot;


[packages]

[dev-packages]

[requires]
python_version = &quot;3.10&quot;

pipenv install --index=pytorch torch
pipenv install --index=pytorch torchvision
pipenv install --index=pytorch torchaudio

#result
...
[packages]
torch = {version=&quot;*&quot;, index=&quot;pytorch&quot;}
torchvision = {version=&quot;*&quot;, index=&quot;pytorch&quot;}
torchaudio = {version=&quot;*&quot;, index=&quot;pytorch&quot;}
...</code></pre>
</blockquote>
<h2 id="99-참조자료">99 참조자료</h2>
<p>가장보통의파이썬 개발환경 <a href="https://jonnung.dev/python/2019/11/23/ordinary-python-development-environment/#gsc.tab=0">https://jonnung.dev/python/2019/11/23/ordinary-python-development-environment/#gsc.tab=0</a>
pyenv <a href="https://docs.kanaries.net/ko/topics/Python/python-version-manager">https://docs.kanaries.net/ko/topics/Python/python-version-manager</a>
pipenv등장배경 <a href="https://heytech.tistory.com/320">https://heytech.tistory.com/320</a>
pipenv <a href="https://medium.com/@erish/python-pipenv-%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80-961b00d4f42f">https://medium.com/@erish/python-pipenv-%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80-961b00d4f42f</a>
파이썬가상환경 비교 <a href="https://devbull.xyz/python-create-environment/">https://devbull.xyz/python-create-environment/</a>
모듈찾는 위치 <a href="https://livetodaykono.tistory.com/22">https://livetodaykono.tistory.com/22</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[3D]Camera]]></title>
            <link>https://velog.io/@velog_sp/3DCamera</link>
            <guid>https://velog.io/@velog_sp/3DCamera</guid>
            <pubDate>Mon, 06 Nov 2023 03:11:28 GMT</pubDate>
            <description><![CDATA[<h2 id="01-개요">01 개요</h2>
<p>공간에 객체가 존재한다고 하여도, 카메라로 표현되는 &quot;시점&quot;이 존재하지 않으면 이미지로 인식될 수 없다.
본 문서에서는 모든 3D 구성에서 시점의 역할을 담당하고, 보여지는 배합을 조절하는 카메라 객체에 대한 내용을 개괄적으로 다룬다.</p>
<p>최종수정일 : 2023.11.06
<br><br></p>
<hr>
<h2 id="02-기초">02 기초</h2>
<p>3D 구성요소의 카메라는 기본적으로 아래와 같은 개념에 의해 &quot;frustum&quot;을 정의한다.
<img src="https://velog.velcdn.com/images/velog_sp/post/3f8e564f-fcf5-42af-9c27-91623b19b7ce/image.png" alt=""></p>
<center>[Three.js]의 frustum</center>

<p><strong>Near</strong>
공간에 정의된 물체가 보이기 시작하는 지점</p>
<p><strong>Far</strong>
물체가 보이는 마지막 시점. 이 시점을 넘어가면 너무 멀어서 보이지 않는다.</p>
<p><strong>FOV(Field Of View)</strong>
종종 시야각이라고도 불린다. 시야의 너비를 나타내며 시야각이 너무 커지면 공간이 이미지에 표현되기 위해 어안렌즈 효과가 나타난다.</p>
<p><strong>aspect</strong>
시야각에서 높이와 너비의 비율을 나타낸다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ThreeJS]Fundamentals]]></title>
            <link>https://velog.io/@velog_sp/ThreeJSFundamentals</link>
            <guid>https://velog.io/@velog_sp/ThreeJSFundamentals</guid>
            <pubDate>Mon, 06 Nov 2023 03:03:40 GMT</pubDate>
            <description><![CDATA[<h2 id="01-개요">01 개요</h2>
<p>본 문서에서는 ThreeJS의 기본적인 사항을 다룬다.</p>
<p>최종수정일 : 2023.11.06
<br><br></p>
<hr>
<h2 id="02-구성">02 구성</h2>
<p>ThreeJS는 다음과 같은 구성요소들로 이루어진다.
<img src="https://velog.velcdn.com/images/velog_sp/post/9c395c18-3d81-485f-84ed-425f5e1cfd9e/image.png" alt=""></p>
<h3 id="0201-renderer">02.01 Renderer</h3>
<p>렌더러(renderer)는 씬과 카메라를 조합하여 3D 씬 객체를 화면에 투사시키는 역할을 한다.</p>
<h3 id="0202-camera">02.02 Camera</h3>
<p>카메라(Camera)는 공간에서 하나의 시점을 정의한다.</p>
<h3 id="0203-scene">02.03 Scene</h3>
<p>씬(Scene) 객체는 하나의 공간을 정의하며, 공간의 원점(origin)을 정의한다.</p>
<h4 id="020301-geometry">02.03.01 Geometry</h4>
<p>지오메트리(Geometry)는 구, 입방체, 사람, 강아지 등 정점(Vertex)으로 구성된 데이터를 의미한다.</p>
<h4 id="020302-texture">02.03.02 Texture</h4>
<p>텍스쳐(Texture)는 (질감을 나타내는)이미지이다.</p>
<h4 id="020303-material">02.03.03 Material</h4>
<p>재질(Material)은 지오메트리로부터 면을 구성할 때 사용되는 특성을 포함하는 객체로, 하나 이상의 텍스쳐와 반사값, 색상 등의 특성을 갖는다.</p>
<h4 id="020304-mesh">02.03.04 Mesh</h4>
<p>메쉬(Mesh) 객체는 특정한 도형(Geometry)과 특정한 재질(Material)로 이루어진 개체를 의미한다. 재질과 지오메트리는 여러 매쉬 객체에서 사용될 수 있다</p>
<h4 id="020305-light">02.03.05 Light</h4>
<p>광원(Light)은 여러 종류의 빛을 의미한다.</p>
<h4 id="020306-object3d">02.03.06 Object3D</h4>
<p>-</p>
<h4 id="020307-group">02.03.07 Group</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DevLog]블로그/Velog 백업하기]]></title>
            <link>https://velog.io/@velog_sp/DevLogBlogBackup</link>
            <guid>https://velog.io/@velog_sp/DevLogBlogBackup</guid>
            <pubDate>Mon, 30 Oct 2023 15:46:59 GMT</pubDate>
            <description><![CDATA[<h2 id="01-velog-백업-방법">01 Velog 백업 방법</h2>
<p>Velog의 마크다운 문서와 이미지를 손쉽게 로컬 스토리지로 옮길 수 있도록 한 프로젝트가 있다.
<a href="https://github.com/cjaewon/velog-backup">https://github.com/cjaewon/velog-backup</a></p>
<blockquote>
<pre><code>`
&gt; git clone https://github.com/cjaewon/velog-backup
&gt; cd velog-backup
&gt; npm install

&gt; node app.js --help
Usage: app [options]

Options:
 -V, --version              output the version number
 -u, --username &lt;username&gt;  velog 유저이름
 -d, --delay &lt;ms&gt;           요청 딜레이 시간 (글이 많은 경우 딜레이 시간을 늘려주세요)
 -c, --cert &lt;access_token&gt;  velog 유저 access_token
 -h, --help                 display help for command

&gt; node app.js -u &lt;유저 이름&gt;

📙 백업을 시작합니다 / velog-backup
✅ &lt;유저 이름&gt;님의 모든 글(3 개) 을 가져옴
✅ &quot; 🐦 serverless 로 날아다니기 &quot; 백업 완료
✅ &quot; Github Action으로 매일마다 브리핑 받기! &quot; 백업 완료
✅ &quot; Github 이스터에그 &quot; 백업 완료</code></pre><p>`</p>
</blockquote>
<p><strong>options</strong>
username : 필수 옵션으로 백업 할 유저를 선택한다.
delay : 백업 요청 딜레이 시간을 넣을 때 사용된다.
cert : 비공개 글을 같이 가져오고 싶을 때 가능하다.</p>
<p><strong>백업 위치</strong>
백업 된 파일은 backup 폴더 안에 저장되어 있다.</p>
<p>content : 백업 한 글들이 마크다운 확장자로 저장됩니다.
images : 글들이 참조하고 있는 이미지들이 다운로드 되어 저장됩니다.</p>
<h2 id="02-naver-blog-백업-방법">02 Naver Blog 백업 방법</h2>
<p><img src="https://velog.velcdn.com/images/velog_sp/post/70e5488d-730c-4bca-9d69-93d79931428f/image.png" alt=""></p>
<p>네이버 블로그에서는 글을 PDF로 백업하는 기능을 자체적으로 제공한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DevLog]개발 문서 작성]]></title>
            <link>https://velog.io/@velog_sp/DevLogDevDoc</link>
            <guid>https://velog.io/@velog_sp/DevLogDevDoc</guid>
            <pubDate>Sat, 28 Oct 2023 12:04:05 GMT</pubDate>
            <description><![CDATA[<p>그동안은 코드 작성에 중점을 두고 작동에 주안점을 두었다. </p>
<p>이제는 다음과 같은 작업이 늘어날 것으로 생각된다.</p>
<ul>
<li>다른 사람의 코드를 구조를 그려가며 읽는 작업</li>
<li>기존 코드를 확장하는 작업</li>
<li>내 코드를 설명하고 이해시키는 작</li>
<li>다양한 디자인 패턴과 아키텍쳐를 적용</li>
<li>리팩터링 등</li>
</ul>
<p>이에 따라 혼자서 한 프로젝트라고 해도 기억하기 어렵거나 구조를 명확하게 그리는 것이 모호한 채로 주먹구구식 개발을 하게될 수 있다.</p>
<p>이에 따라 이 시점부터 단계에 맞게 필요한 개발 문서를 작성해가며 작업하기로 정한다.</p>
<p>최종수정일 : 2023.10.28</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TypeScript]JavaScript Migration]]></title>
            <link>https://velog.io/@velog_sp/TypeScriptJavaScriptMigration</link>
            <guid>https://velog.io/@velog_sp/TypeScriptJavaScriptMigration</guid>
            <pubDate>Mon, 23 Oct 2023 08:35:46 GMT</pubDate>
            <description><![CDATA[<h2 id="01-개요">01 개요</h2>
<p>많은 패키지들이 자바스크립트로 만들어졌다. 이러한 경우 해당 패키지 내의 변수나 함수들은 타입을 알 수 없어 타입스크립트가 정보를 추론하기 어렵다. 본 문서에서는 이와 같은 기존의 자바스크립트 코드를 타입스크립트에서 이용하기 위하여 필요한 내용을 다룬다.</p>
<p>최종수정일 : 2023.10.25
<br><br></p>
<hr>
<h2 id="02-dts--declaration-file">02 d.ts : declaration file</h2>
<p><strong>MyPackage.js</strong></p>
<blockquote>
<pre><code class="language-js">export function init(config) {
   return true;
}

export function exit(code) {
   return code + 1;
}

</code></pre>
</blockquote>
<p><strong>useMyPackage.ts : Dummy Code</strong></p>
<blockquote>
<pre><code class="language-ts">import { init, exit } from &quot;MyPackage&quot;

init({
   url:&quot;true&quot;
})

exit(1)

</code></pre>
</blockquote>
<p><strong>MyPackage.d.ts : declaration file</strong></p>
<blockquote>
<pre><code class="language-ts">interface Config {
   url: string;
}
declare module &quot;MyPackage&quot; {
   function init(config: Config):boolean;
   function exit(code: number): number;
}</code></pre>
</blockquote>
<p>Javascript로 작성된 라이브러리를 타입스크립트에서 타입안정성 있게 사용하기 위해서 타입에 대해 서술한 추가적인 파일이다.</p>
<h2 id="03-jsdoc--ts-check">03 JSDoc : @ts-check</h2>
<p><strong>tsconfig.json</strong></p>
<blockquote>
<pre><code class="language-ts">{
   &quot;include&quot;: [&quot;src&quot;],
   &quot;compilerOptions&quot;: {
       ...
       &quot;allowJS&quot;: true
   }
}</code></pre>
</blockquote>
<p><strong>myPackage.js</strong></p>
<blockquote>
<pre><code class="language-js">// @ts-check

/**
* Initialize the project
*@param {object} config
*@param {boolean} config.debug
*@param {string} config.url
*@return boolean
*/
export function init(config) {
   return true;
}

/**
* Exit the project
*@param {number} code
*@return number
*/
export function exit(code) {
   return code + 1;
}</code></pre>
</blockquote>
<p>위와 같이 작성하면 JSDoc 문법을 통해 자바스크립트 파일의 변형이나 오작동 없이 타입스크립트에서 임포트했을 때 타입을 안내해준다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TypeScript]TS Configuration]]></title>
            <link>https://velog.io/@velog_sp/TypeScriptTS-Configuration</link>
            <guid>https://velog.io/@velog_sp/TypeScriptTS-Configuration</guid>
            <pubDate>Fri, 20 Oct 2023 01:52:58 GMT</pubDate>
            <description><![CDATA[<h2 id="01-개요">01 개요</h2>
<p>타입스크립트 컴파일러는 100개 이상의 다양한 설정을 가지고 있다. 그 외에도 타입스크립트에서 사용할 다양한 옵션이 존재한다. 본 문서에서는 tsconfig.json을 파일을 주로 커맨드라인에서도 사용가능한 타입스크립트의 자주 사용되는 설정에 대해서 다룬다.</p>
<p>최종수정일 : 2023.10.20</p>
<p><br><br></p>
<hr>
<h2 id="02-compile-options">02 Compile Options</h2>
<p><a href="https://www.typescriptlang.org/tsconfig#strictNullChecks">https://www.typescriptlang.org/tsconfig#strictNullChecks</a></p>
<blockquote>
<pre><code class="language-ts">{
   &quot;compilerOptions&quot;: {
//        &quot;strict&quot;: true            - automatically set true on following options
//            &quot;strict&quot;: true,
//            &quot;strictNullChecks&quot;: true,
//            &quot;strictFunctionTypes&quot;: true,
//            &quot;strictBindCallApply&quot;: true,
//            &quot;strictPropertyInitialization&quot;: true,
//            &quot;noImplicitThis&quot;: true,
//            &quot;alwaysStrict&quot;: true,

       &quot;noImplicitAny&quot;: true
       &quot;strictNullChecks&quot;: true
       ...
   }
}</code></pre>
</blockquote>
<h3 id="0201-strict">02.01 strict</h3>
<p><strong>Default</strong> : false
<strong>Released</strong> : 2.3
엄격한 타입스크립트 룰을 적용한다.</p>
<h3 id="0202-noimplicitany">02.02 noImplicitAny</h3>
<p><strong>Default</strong> : true if strict; false otherwise.
<strong>Related</strong> : strict</p>
<p>암묵적으로 타입이 지정되지 않은 변수에 any타입을 적용할 것인지를 결정한다.</p>
<h3 id="0203-strictnullchecks">02.03 strictNullChecks</h3>
<p><strong>Default</strong> : true if strict; false otherwise.
<strong>Related</strong> : strict
<strong>Released</strong> : 2.0</p>
<p><code>null</code>과 <code>undefined</code>가 모든 타입에 할당하는 것이 허용되는지 확인한다.</p>
<h3 id="0204-noemitonerror">02.04 noEmitOnError</h3>
<p><strong>Default</strong> : false
<strong>Released</strong> : 1.4</p>
<p>타입 오류가 있을 경우에, 해당 옵션이 false일 경우 컴파일이 가능하다. 해당 옵션을 설정하면 타입 오류가 있을 때 컴파일이 불가능해진다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DEVENV]Visual Studio Code 설정]]></title>
            <link>https://velog.io/@velog_sp/DEVENVVSCode</link>
            <guid>https://velog.io/@velog_sp/DEVENVVSCode</guid>
            <pubDate>Thu, 19 Oct 2023 05:50:13 GMT</pubDate>
            <description><![CDATA[<h2 id="01-개요">01 개요</h2>
<p>본 문서에서는 Visual Studio Code에 대한 환경설정과 사용자 최적화에 관한 내용을 다룬다.</p>
<p>최종수정일 : 2023.10.19
<br><br></p>
<hr>
<h2 id="02-초기-설정">02 초기 설정</h2>
<h3 id="0201-extension">02.01 Extension</h3>
<p>VScode Pet 설치</p>
<h3 id="0202-환경설정">02.02 환경설정</h3>
<p><strong>터미널 한글 사용</strong></p>
<blockquote>
<p>vscode settings &gt; encoding(settings.json에서 직접 수정 가능)
제어판 &gt; 시계 및 국가 &gt; 국가 또는 지역 &gt; 관리자 옵션 &gt; 시스템 로캘 변경 &gt; 세계 언어 지원을 위해 Unicode UTF-8 사용 활성화</p>
</blockquote>
<p><strong>자동완성 기능 사용</strong></p>
<blockquote>
<p>code &gt; settings &gt; Trigger Suggest</p>
</blockquote>
<p><br><br></p>
<hr>
<h2 id="03-단축키">03 단축키</h2>
<h3 id="0301-코드-작성">03.01 코드 작성</h3>
<p><strong><code>Ctrl + K C</code> <code>Ctrl + K U</code> : 주석처리</strong>
선택한 영역을 주석처리/해제한다.</p>
<p><strong><code>Ctrk + L</code> : 선택 줄 삭제</strong>
선택된 줄을 삭제한다.</p>
<p><strong><code>Ctrk + D</code> : 다중선택(순차)</strong>
선택한 변수와 같은 변수를 하나씩 동시수정 가능하게 추가한다.</p>
<p><strong><code>Ctrk + Shift + L</code> : 다중선택(순차)</strong>
선택한 변수와 같은 변수 전체를 동시수정 가능하게 추가한다.</p>
<h3 id="0302-추가설정">03.02 추가설정</h3>
<p><strong><code>Ctrl+(number)</code> : 해당 번호 탭으로 이동</strong>
Code -&gt; Preferences -&gt; Keyboard Shortcurs -&gt; 우측상단 keybindings.json
아래 내용 추가</p>
<blockquote>
<pre><code class="language-json">[
   {
       &quot;key&quot;: &quot;ctrl+0&quot;,
       &quot;command&quot;: &quot;workbench.action.openLastEditorInGroup&quot;
   },
   {
       &quot;key&quot;: &quot;ctrl+1&quot;,
       &quot;command&quot;: &quot;workbench.action.openEditorAtIndex1&quot;
   },
   {
       &quot;key&quot;: &quot;ctrl+2&quot;,
       &quot;command&quot;: &quot;workbench.action.openEditorAtIndex2&quot;
   },
   {
       &quot;key&quot;: &quot;ctrl+3&quot;,
       &quot;command&quot;: &quot;workbench.action.openEditorAtIndex3&quot;
   },
   {
       &quot;key&quot;: &quot;ctrl+4&quot;,
       &quot;command&quot;: &quot;workbench.action.openEditorAtIndex4&quot;
   },
   {
       &quot;key&quot;: &quot;ctrl+5&quot;,
       &quot;command&quot;: &quot;workbench.action.openEditorAtIndex5&quot;
   }
]</code></pre>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DevOps]GitHub 관리 기술]]></title>
            <link>https://velog.io/@velog_sp/DevOpsGitHubManageTechnic</link>
            <guid>https://velog.io/@velog_sp/DevOpsGitHubManageTechnic</guid>
            <pubDate>Mon, 16 Oct 2023 06:19:06 GMT</pubDate>
            <description><![CDATA[<h2 id="01-개요">01 개요</h2>
<p>본 문서에서는 GitHub를 관리하는 과정에서 필요한 여러가지 테크닉에 대해 다룬다.</p>
<p>최종수정일 :2023.10.16</p>
<p><br><br></p>
<hr>
<h2 id="02-과거-커밋-이력-공개-없이-공개범위-변경">02 과거 커밋 이력 공개 없이 공개범위 변경</h2>
<p><a href="https://stackoverflow.com/questions/39336842/make-git-repo-public-without-revealing-past-commits">https://stackoverflow.com/questions/39336842/make-git-repo-public-without-revealing-past-commits</a></p>
<blockquote>
<p><strong>git checkout</strong> <em>UserCommitHash</em></p>
</blockquote>
<p>원하는 커밋으로 이동한다.</p>
<blockquote>
<p><strong>git reset</strong> <em>InitialCommitHash</em> --soft</p>
</blockquote>
<p>초기 커밋으로 이동한다.</p>
<blockquote>
<p><strong>git commit</strong> --amend -m &quot;<em>My new initial commit</em>&quot;</p>
</blockquote>
<p>amend 옵션과 함께 커밋한다.</p>
<blockquote>
<p><strong>git push</strong> <em>your_remote</em> main</p>
</blockquote>
<p>퍼블릭 리포지토리에 푸시한다.</p>
<p>클론한 리포지토리를 푸시할 수도 있지만 이렇게 진행할 경우, <code>git reflog</code> 명령어를 통해 조회할 수 있지만 원격 저장소에 푸시되지는 않는다.</p>
<p>또한 첫번째 커밋의 아이디를 얻기 위해서는 아래 글에 나온 명령어를 사용할 수 있다.
(<a href="https://stackoverflow.com/questions/5188914/how-to-show-the-first-commit-by-git-log/5189296#5189296">https://stackoverflow.com/questions/5188914/how-to-show-the-first-commit-by-git-log/5189296#5189296</a>)</p>
<blockquote>
<p><strong>git rev-list</strong> --max-parents=0 HEAD</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ReactNative]스타일 관리(Style)]]></title>
            <link>https://velog.io/@velog_sp/ReactNativeStyle</link>
            <guid>https://velog.io/@velog_sp/ReactNativeStyle</guid>
            <pubDate>Fri, 22 Sep 2023 02:29:09 GMT</pubDate>
            <description><![CDATA[<h2 id="01-개요">01 개요</h2>
<p>리액트 네이티브의 스타일에 관한 내용 전반을 다룬다.</p>
<p>최종수정일 : 2023.09.22</p>
<p><br><br></p>
<hr>
<h2 id="02-스타일-관리-방법">02 스타일 관리 방법</h2>
<h3 id="0201-inline-style">02.01 inline-style</h3>
<blockquote>
<pre><code class="language-js">&lt;Text style={{color:&#39;#000&#39;}}&gt;My Text&lt;/Text&gt;</code></pre>
</blockquote>
<h3 id="0202-stylesheet">02.02 stylesheet</h3>
<blockquote>
<pre><code class="language-js">
import { StyleSheet } from &#39;react-native&#39;;
const LotsOfStyles = () =&gt; {
 return (
   &lt;View style={styles.container}&gt;
     &lt;Text style={styles.red}&gt;just red&lt;/Text&gt;
     &lt;Text style={styles.bigBlue}&gt;just bigBlue&lt;/Text&gt;
     &lt;Text style={[styles.bigBlue, styles.red]}&gt;bigBlue, then red&lt;/Text&gt;
     &lt;Text style={[styles.red, styles.bigBlue]}&gt;red, then bigBlue&lt;/Text&gt;
   &lt;/View&gt;
 );
};

const styles = StyleSheet.create({
 container: {
   marginTop: 50,
 },
 bigBlue: {
   color: &#39;blue&#39;,
   fontWeight: &#39;bold&#39;,
   fontSize: 30,
 },
 red: {
   color: &#39;red&#39;,
 },
});</code></pre>
</blockquote>
<h3 id="0203-styled-component">02.03 styled component</h3>
<blockquote>
<pre><code class="language-js">import styled from &#39;styled-components&#39;

const Button = styled.button``</code></pre>
</blockquote>
<p><br><br></p>
<hr>
<h2 id="03-세부사항">03 세부사항</h2>
<h3 id="0301-font-설정">03.01 Font 설정</h3>
<p>참조링크 : <a href="https://dev-yakuza.posstree.com/ko/react-native/react-native-custom-font/">https://dev-yakuza.posstree.com/ko/react-native/react-native-custom-font/</a></p>
<h4 id="030101-android">03.01.01 Android</h4>
<p>android/app/src/main/assets/fonts에 폰트 파일을 추가한다.</p>
<h4 id="030102-ios">03.01.02 iOS</h4>
<p>ios/Fonts에 폰트 파일을 추가한다.</p>
<p>xcode &gt; project명 우클릭 &gt; Add Files to &quot;project_name&quot;... &gt; ios/Fonts 선택 &gt; Create folder references를 선택 &gt; Add</p>
<p>왼쪽 상단 프로젝트명을 선택 &gt; TARGETS 프로젝트명을 선택 &gt;상단 메뉴에서 Info 선택 &gt; Info.plist의 내용을 확인 &gt; Info.plist에 Fonts provided by application 추가 &gt; 폰트 파일을 추가</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ReactNative]HTML 렌더 라이브러리]]></title>
            <link>https://velog.io/@velog_sp/ReactNativeHTMLRender</link>
            <guid>https://velog.io/@velog_sp/ReactNativeHTMLRender</guid>
            <pubDate>Fri, 22 Sep 2023 01:55:00 GMT</pubDate>
            <description><![CDATA[<h2 id="01-개요">01 개요</h2>
<p>경우에 따라 리액트 네이티브 앱 내부에서 html 문서를 렌더링 해야 할 필요가 있는 경우가 있다. 이러한 경우 사용할 수 있는 라이브러리는 2023년 09월 현재 크게 두가지가 있다.</p>
<p><code>react-native-render-html</code>
<code>react-native-webview</code></p>
<p>본 문서에서는 위 두 라이브러리를 포함하여 HTML문서를 리액트 네이티브 내부에서 렌더하는 방법에 대해서 다룬다.</p>
<p>최종수정일 : 2023.09.22
<br><br></p>
<hr>
<h2 id="02-작동방식">02 작동방식</h2>
<h3 id="0201-react-native-render-html">02.01 react-native-render-html</h3>
<p><img src="https://velog.velcdn.com/images/velog_sp/post/553cb236-b562-4887-871b-69c6f7bdbdf6/image.jpg" alt=""></p>
<p><br><br></p>
<hr>
<h2 id="03-기본적인-사용법">03 기본적인 사용법</h2>
<h3 id="0301-react-native-render-html">03.01 react-native-render-html</h3>
<blockquote>
<pre><code class="language-js">import React from &#39;react&#39;;
import { useWindowDimensions } from &#39;react-native&#39;;
import RenderHtml from &#39;react-native-render-html&#39;;

const source = {
 html: `
&lt;p style=&#39;text-align:center;&#39;&gt;
 Hello World!
&lt;/p&gt;`
};

//` &lt;- Markdown edtorial requirement
export default function App() {
 const { width } = useWindowDimensions();
 return (
   &lt;RenderHtml
     contentWidth={width}
     source={source}
   /&gt;
 );
}
//`</code></pre>
</blockquote>
<h3 id="0302-react-native-webview">03.02 react-native-webview</h3>
<blockquote>
<pre><code class="language-js">import React, { Component } from &#39;react&#39;;
import { StyleSheet, Text, View } from &#39;react-native&#39;;
import { WebView } from &#39;react-native-webview&#39;;

// ...
const MyWebComponent = () =&gt; {
 return &lt;WebView source={{ uri: &#39;https://reactnative.dev/&#39; }} style={{ flex: 1 }} /&gt;;
}</code></pre>
</blockquote>
<h2 id="99-참조링크">99 참조링크</h2>
<h3 id="9901-react-native-render-html">99.01 react-native-render-html</h3>
<p><a href="https://blog.logrocket.com/how-render-html-react-native/">https://blog.logrocket.com/how-render-html-react-native/</a>
<a href="https://www.npmjs.com/package/react-native-render-html">https://www.npmjs.com/package/react-native-render-html</a></p>
<h3 id="9902-react-native-webview">99.02 react-native-webview</h3>
<p><a href="https://github.com/react-native-webview/react-native-webview">https://github.com/react-native-webview/react-native-webview</a></p>
]]></description>
        </item>
    </channel>
</rss>