<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>yeonjeong.log</title>
        <link>https://velog.io/</link>
        <description>Backend 개발자로 거듭나는 그 날까지 !</description>
        <lastBuildDate>Fri, 20 Jun 2025 08:54:09 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>yeonjeong.log</title>
            <url>https://velog.velcdn.com/images/nancy_yeonjeong/profile/aa5f93eb-0b18-4468-8ff9-1c273e3ddbb6/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. yeonjeong.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/nancy_yeonjeong" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[🌳 고급 프로젝트 : Decimal type ]]></title>
            <link>https://velog.io/@nancy_yeonjeong/%EA%B3%A0%EA%B8%89-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-Decimal-type</link>
            <guid>https://velog.io/@nancy_yeonjeong/%EA%B3%A0%EA%B8%89-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-Decimal-type</guid>
            <pubDate>Fri, 20 Jun 2025 08:54:09 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/e7de7f33-cd4f-41e4-a5f1-ebffd02fe3d5/image.jpeg" alt=""></p>
<p>이번에 고급 프로젝트를 진행하면서 새로 알게된 Type에 대해서 몇 줄 작성하려고 한다.</p>
<p>원화(₩)는 10원이 현금으로 가장 작은 단위이고, 인터넷 결제 혹은 이자를 받다보면 1원 단위도 볼 수 있다. 하지만 달러($)의 경우에는 달러를 기준으로 $1.2 여기서 소수점 단위는 센트이다.</p>
<p>지금 우리는 한국에서만 결제를 유도하는 시스템을 만들지만, 
비지니스의 영역이 확장되어서 혹은 한국 고객 뿐 아니라 해외 고객 유치가 가능하다면?
전세계 공용으로 통용되는 달러 결제 시스템을 준비해야 한다.</p>
<p>여기서 적용해 볼 수 있는 type이 바로 <code>Deciml</code>이다.</p>
<h3 id="1-영어로-보는-숫자-타입">1. 영어로 보는 숫자 타입</h3>
<p>정수: integer(1,2,3,0,-1,-2) 
실수: real number(-2.5, 0, 3.14)
분수: fraction(1/2, 3/4)
소수: decimal(0.2, 2.718)
자연수: natural number(1,2,3)</p>
<p>위의 내용을 보았을 때 decimal은 0이상의 소수를 나타낼 수 있는 타입이라는 것을 알 수 있다.</p>
<p>그러면 왜 소수 뿐 아니라 금융 데이터를 다룰 때는 <code>decimal</code>을 사용해야 할까?</p>
<p>일반적으로 사용하는 <code>부동 소수점(float, double)</code>은 계산 과정에서 미세한 오파가 발생 할 수 있어서 돈과 관련된 계산에는 적합하지 않기 때문이다.</p>
<h3 id="2-decimal-타입에-대한-이해">2. <code>Decimal</code> 타입에 대한 이해</h3>
<p><code>DECIMAL(P,S)</code> 타입은 고정 소수점 숫자를 저장할 수 있다. </p>
<ul>
<li><code>P</code>(Precision, 정밀도): 숫자의 총 자릿수를 의미. 소수점 왼쪽과 오른쪽을 모두 포함한 자릿수 -&gt; 1-65까지 지정 가능하지만 데이터 베이스마다 다를 수 있음</li>
<li><code>S</code>(Scale, 스케일): 소수점 이하의 자릿수를 의미. -&gt; 0~P까지 가능</li>
</ul>
<blockquote>
<p>example. 
<code>DECIMAL(10, 2)</code>: 총 10자리 숫자 중 소수점 이하 2자리를 저장합니다. 표현 가능한 범위는 -99999999.99부터 99999999.99까지입니다. (총 8자리 정수부 + 2자리 소수부)</p>
</blockquote>
<h3 id="3-prisma-적용-및-활용">3. Prisma 적용 및 활용</h3>
<pre><code>model Order {
  id        String   @id @default(uuid())
  userId    String
  totalAmount Decimal @db.Decimal(19, 4)
  createdAt DateTime @default(now())
}</code></pre><ul>
<li><code>Decimal</code>: Prisma 내부에서 사용하는 타입 이름</li>
<li><code>@db.Decimal(P, S)</code>: 데이터베이스에 실제 생성될 컬럼의 타입을 지정</li>
<li><code>P (Precision)</code>: 숫자의 총 자릿수 (소수점 왼쪽 + 소수점 오른쪽).</li>
<li><code>S (Scale)</code>: 소수점 이하 자릿수.
이 값들은 사용하려는 데이터베이스의 DECIMAL 타입 규칙을 따르기(예: MySQL은 최대 65, 30)</li>
</ul>
<ol start="4">
<li>타입스크립트 Type 지정
Prisma는 Decimal 타입 필드를 처리할 때, JavaScript의 기본 number 타입이 아닌, Decimal.js 라이브러리의 Decimal 객체를 사용하도록 타입 정의를 생성한다.. 따라서 TypeScript 코드에서는 Decimal.js의 Decimal 타입을 import.</li>
</ol>
<h4 id="1-decimal-라이브러리-이용">1) decimal 라이브러리 이용</h4>
<p><strong>a) decimal.js 라이브러리 설치</strong></p>
<pre><code>pm install decimal.js
npm install -D @types/decimal.js</code></pre><p><strong>b) TypeScript 코드에서 사용하기</strong>
Decimal 타입의 값을 다룰 때는 항상 Decimal.js 객체로 생성하고, 계산하며, 문자열로 변환하여 사용</p>
<pre><code>import { PrismaClient, Prisma } from &#39;@prisma/client&#39;;
import Decimal from &#39;decimal.js&#39;; // Decimal.js 라이브러리 임포트


const prisma = new PrismaClient();

async function createAndGetProduct() {
  // 1. Prisma에 데이터 생성/업데이트 시 Decimal 값 처리
  // Decimal 값을 넘겨줄 때는 문자열 또는 Decimal.js 객체로 넘겨줘야 합니다.
  const newProduct = await prisma.product.create({
    data: {
      name: &#39;Smart Watch&#39;,
      price: new Decimal(&#39;199.99&#39;), // Decimal.js 객체로 생성하여 전달 (가장 안전)
      // price: &#39;199.99&#39;, // 문자열로 전달해도 Prisma가 Decimal.js 객체로 변환해줍니다.
    },
  });

  console.log(&#39;Created Product:&#39;, newProduct);
  // newProduct.price는 Decimal.js의 Decimal 객체 타입입니다.
  // console.log(typeof newProduct.price); // object
  // console.log(newProduct.price instanceof Decimal); // true

  // 2. Prisma에서 Decimal 값을 가져왔을 때
  const product = await prisma.product.findUnique({
    where: { id: newProduct.id },
  });

  if (product) {
    // product.price는 Decimal.js의 Decimal 객체입니다.
    console.log(&#39;Product Price (Decimal object):&#39;, product.price);

    // 3. Decimal 값으로 계산 수행 시 (반드시 Decimal.js 메서드 사용)
    const taxRate = new Decimal(&#39;0.10&#39;); // 10%
    const priceWithTax = product.price.t
```imes(taxRate).plus(product.price);

    console.log(&#39;Price with Tax (Decimal object):&#39;, priceWithTax);

    // 4. Decimal 값을 문자열로 변환하여 출력하거나 API 응답으로 보낼 때
    console.log(&#39;Price with Tax (string, 2 decimal places):&#39;, priceWithTax.toFixed(2)); // &quot;219.99&quot;
    console.log(&#39;Price with Tax (full string):&#39;, priceWithTax.toString()); // &quot;219.989&quot; (정확한 값)

    // 5. 숫자로 변환해야 할 경우 
    // 필요한 경우가 아니라면 Number()로 변환하지 마세요.
    // console.log(&#39;Price with Tax (number - potentially imprecise):&#39;, Number(priceWithTax.toString()));
  }
}</code></pre><h4 id="2-prisma---decimal-끌어오기">2) prisma - decimal 끌어오기</h4>
<pre><code> import { Decimal } from &quot;@prisma/client/runtime/library&quot;;

export const buyerUser = {
  id: &quot;user_buyer_001&quot;,
  email: &quot;buyer@example.com&quot;,
  name: &quot;파는사람&quot;,
  password: &quot;password1234&quot;,
  type: UserType.BUYER,
  point: 0,
  totalAmount: new Decimal(0),
  createdAt: new Date(),
  updatedAt: new Date(),
};</code></pre><p>-&gt; prisma 라이브러리를 활용한 Decimal 타입을 참조</p>
<p><strong>(1) Prisma의 타입 정의와 일치</strong>
Prisma는 schema.prisma 파일에 Decimal 타입으로 정의된 필드를 가져오거나 생성할 때, JavaScript의 기본 number 타입이 아닌 decimal.js 라이브러리의 Decimal 객체로 변환하여 처리
-&gt; totalAmount: new Decimal(0)은 Prisma가 예상하는 타입(Decimal.js의 Decimal 객체)에 맞춰 데이터를 제공하는 것입니다.</p>
<p><strong>(2) 부동 소수점 오차 방지</strong>
JavaScript의 기본 number 타입은 64비트 부동 소수점(float)으로 표현되기 때문에, 0.1 + 0.2가 0.30000000000000004와 같이 미세한 오차를 가질 수 있다. 돈과 관련된 계산에서는 이러한 작은 오차도 허용되지 않기에 new Decimal(0)을 사용함으로써 0이라는 값을 정확한 십진수로 표현하고, 앞으로 이 totalAmount 필드에 대한 모든 계산(덧셈, 뺄셈 등)도 Decimal.js의 메서드(plus(), minus(), times() 등)를 사용하여 오차 없이 이루어지도록 준비하는 것입니다.</p>
<p><strong>(3) 일관된 데이터 처리</strong></p>
<blockquote>
<p>데이터베이스에서 Decimal 타입으로 관리하기로 했다면, 애플리케이션 계층에서도 일관되게 관리해야 하는데 new Decimal(0)은 이러한 일관된 처리 방식의 시작점</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[🌳 고급프로젝트: middleWare(1)]]></title>
            <link>https://velog.io/@nancy_yeonjeong/%EA%B3%A0%EA%B8%89%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-middleWare1</link>
            <guid>https://velog.io/@nancy_yeonjeong/%EA%B3%A0%EA%B8%89%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-middleWare1</guid>
            <pubDate>Fri, 20 Jun 2025 07:21:44 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/c2b90d17-3cc6-4f38-a7b7-fc2f3b7a4db4/image.jpeg" alt=""></p>
<p>이번에 진행하는 고급 프로젝트에서는 로그인한 유저 뿐 아니라 로그인하지 않은 유저도 접속하여 내용을 볼 수 있도록 구현해야 하는 부분이 몇 있다.</p>
<ul>
<li>로그인 시에는 해당 유저에 맞춤형으로 변환</li>
<li>로그인을 안할 경우 일반 페이지 보여줌</li>
</ul>
<p>그러면 로그인을 할 때는 <strong>header에 있는 토큰을 확인 -&gt; 로그인 id 추출 -&gt; 사용자 정보 반영</strong>과 같은 로직으로 갈 수 있다. </p>
<p>하지만 로그인 하지 않은 유저가 접속했을 때는 토큰이 없기에 토큰을 확인하는 미들웨어를 통과 할 수 없다. <code>UnauthError</code>가 발생할 수 있기에 로그인을 진행하여 토큰이 있다면 토큰을 확인하여 유저 정보를 반환하도록, 토큰이 없다면 일반 페이지가 보이도록 optional이 필요하였다. </p>
<p>원래 로그인한 유저만 접근 가능한 페이지에서는</p>
<pre><code>const extractToken = (req: Request): string | null =&gt; {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith(&quot;Bearer &quot;)) {
    return null;
  }
  return authHeader.split(&quot; &quot;)[1];
};

export const authMiddleware = async (
  req: Request,
  res: Response,
  next: NextFunction
) =&gt; {
  try {
    const token = extractToken(req);
    if (!token) {
      throw new UnauthError();
    }

    const { id } = verifyAccessToken(token);
    const user = await userService.getById(id);
    if (!user) {
      throw new UnauthError();
    }

    req.user = user;
    next();
  } catch {
    next(new UnauthError());
  }
};</code></pre><p>이와 같이 토큰 정보가 없다면 &quot;당신은 이 페이지에 접근할 수 없습니다. 로그인 상태를 확인해주세요&quot; 의 의미의 <code>error</code>를 뱉으며 <code>status = 401</code>이 되어야 한다. </p>
<p>그러면 이제 이것을 로그인하지 않은 유저 또한도 접근하게 하려면 어떻게 해야할까? </p>
<pre><code>export const optionalAuthMiddleware = async (
  req: Request,
  res: Response,
  next: NextFunction
) =&gt; {
  try {
    const token = extractToken(req);
    if (!token) {
      return next();
    }
    const { userId } = verifyAccessToken(token);
    const user = await userService.getById(userId);
    if (user) {
      req.user = user;
    }
  } catch {
  } finally {
    next();
  }
};</code></pre><p>위와 같이 토큰이 없을 경우에는 이 미들웨어를 그냥 통과하도록 <code>next()</code>로 다른 로직으로 넘겨주면 된다. </p>
<p>하지만 위의 코드만 보았을 때 맥락은 맞지만 틀린 부분이 있었다. </p>
<h3 id="1-유저-정보-찾을시-next-누락">1. 유저 정보 찾을시, <code>next()</code> 누락</h3>
<p>만약에 로그인을 한 유저인 경우, </p>
<pre><code>    const user = await userService.getById(userId);
    if (user) {
      req.user = user;
    }</code></pre><p>유저의 정보를 가져왔지만, 미들웨어에서 가져온 정보이기에 다음 로직으로 넘겨줘야 하는데 <code>next()</code>가 누락되어 넘겨주지 못하고 미들웨어에 남아있는다.</p>
<h3 id="2-error-미처리">2. <code>error</code> 미처리</h3>
<p>해당 미들웨어에서는 <code>try-catch문</code>을 통해서 에러가 생기면 잡아서 전역 <code>error</code> 함수로 넘겨주도록 설계하였다. </p>
<pre><code>  } catch {
  } finally {
    next();
  }
};</code></pre><p>하지만 코드를 다시 보니 정작 <code>error</code>를 잡아줘야 하는 <code>catch</code>에는 <code>next</code>가 없어서 <code>error</code>를 넘겨주지 못하고 있다. 이렇게 되면 </p>
<p><strong>1) <code>verifyAccessToken</code>에서 토큰이 있지만 유효하지 않은 경우
2) 토큰은 유효하지만 <code>userId</code>를 통해서 유저를 찾으려고 할때 해당 유저가 데이터 베이스에 없는 경우</strong></p>
<p>위와 같은 상황에서는 에어가 잇음에도 이를 무시해버리게 된다.
다음 서비스에서는 중복 에러 코드를 피하기 위해서 만약에 에러를 잡는 조건문을 넣지 않았다면 에러가 발생해도 정확한 원인 및 위치를 확인하기 힘들 것이다. </p>
<h3 id="3-finally-next-중복-호출">3. <code>finally</code> <code>next()</code> 중복 호출</h3>
<pre><code>    if (!token) {
      return next();
    }</code></pre><p>토큰이 없을 때는 원래 해당 미들웨어를 종료하고, 다음 서비스 로직으로 넘어가는 것이 이 미들웨어의 특징이기에 여기서의 <code>next()</code> 무조건 위치되어야 합니다.</p>
<p>하지만,</p>
<pre><code>  } catch {
  } finally {
    next();
  }
};</code></pre><p>try 블록 내부가 아닌 끝인 finally에서 next가 호출된다면 어떻게 될까? 
try 내부에 next가 존재하지 않고 만약 에러가 있다고 해도 catch 문 안에서는 아무것도 없어서 에러를 찾을 수 없기에 finally에서의 next()는 무조건 호출이 될 것입니다.</p>
<p><em>[예상 사고 상황]</em></p>
<ol>
<li>토큰이 존재하여 <code>if(!token)</code>을 통과</li>
<li><code>verfyAccessToken(token)</code>에서 유효하지 않은 토큰으로 인한 에러 발생</li>
<li><code>catch</code>에서는 아무것도 잡을 수 없음</li>
<li><code>finally</code> 블록으로 와서 <code>next()</code> 호출</li>
<li><code>optionalAuthMiddleware</code> 함수 종료 -&gt; <code>next()</code> 호출</li>
</ol>
<p>만약에 이 미들웨어 다음에 또 다른 미들웨어나 라우트 핸들러가 <code>next()</code>를 호출하는 로직을 가지고 있다면, 
<code>next()</code>가 한 요청에 대해 두 번 이상 호출될 수 있다. 혹은 라우트에서 클라이언트로 정보를 보낸다면 <code>res.status.send</code> 이러한 상황에서는 아래와 같은 <code>error</code> 메시지를 마주할 수 있다. </p>
<p><code>Cannot set headers after they are sent to the client</code> 오류
-&gt; 이미 클라이언트에게는 응답이 전송되었지만 다시 응답을 보내려고 시도할 때 발생하는 에러</p>
<p>이외에도 요청 처리 흐름이 꼬여서 의도치 않은 미들웨어가 실행되거나, 데이터베이스 작업이 중복으로 발생하거나 서버가 불안정해질 수 있다. </p>
<p><code>finally</code>은 <code>try</code>안에서 실행이 되든 <code>catch</code>로 에러를 넘기든 실행되는 블록이기에 <code>try</code> 안에서 해결되어 클라이언트로 응답을 보내게 되고 -&gt; <code>next()</code>가 한 번 더 실행이 된다. 이럴 경우 중복 호출로 이미 응답이 완료된 다음 또 다시 헤더를 설정하거나 응답을 보내려고 시도하게 된다.</p>
<p><strong>꼭 미들웨어에서 사용할 시에는,,, <code>catch</code>까지만 작성 + <code>try</code> 안에서 <code>return next()</code>를 통해서 이후 불필요한 코드 실행을 막아주자!</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[6월 1째주 위클리페이퍼_HTTPS 적용과 로드밸런서]]></title>
            <link>https://velog.io/@nancy_yeonjeong/6%EC%9B%94-1%EC%A7%B8%EC%A3%BC-%EC%9C%84%ED%81%B4%EB%A6%AC%ED%8E%98%EC%9D%B4%ED%8D%BCHTTPS-%EC%A0%81%EC%9A%A9%EA%B3%BC-%EB%A1%9C%EB%93%9C%EB%B0%B8%EB%9F%B0%EC%84%9C</link>
            <guid>https://velog.io/@nancy_yeonjeong/6%EC%9B%94-1%EC%A7%B8%EC%A3%BC-%EC%9C%84%ED%81%B4%EB%A6%AC%ED%8E%98%EC%9D%B4%ED%8D%BCHTTPS-%EC%A0%81%EC%9A%A9%EA%B3%BC-%EB%A1%9C%EB%93%9C%EB%B0%B8%EB%9F%B0%EC%84%9C</guid>
            <pubDate>Sun, 08 Jun 2025 14:24:00 GMT</pubDate>
            <description><![CDATA[<h1 id="🔒-웹-서버에-https를-적용하는-방법">🔒 <strong>웹 서버에 HTTPS를 적용하는 방법</strong></h1>
<p><strong>HTTP</strong>는 암호화되지 않은 방식으로 데이터를 주고받기 때문에 <strong>민감한 정보 유출 위험</strong>이 큽니다. 이를 해결하기 위해 등장한 것이 바로 <strong><em>HTTPS(Hypertext Transfer Protocol Secure)</em></strong> 입니다.</p>
<h2 id="🌐-https란-무엇인가요">🌐 <strong>HTTPS란 무엇인가요?</strong></h2>
<blockquote>
<p><strong>HTTPS</strong> = <strong>HTTP + SSL/TLS</strong></p>
</blockquote>
<ul>
<li>데이터를 암호화하여 <strong>기밀성(Confidentiality)</strong> 확보  </li>
<li>위/변조 방지로 <strong>무결성(Integrity)</strong> 보장  </li>
<li>인증서를 통해 <strong>서버 인증(Authentication)</strong> 수행</li>
</ul>
<h2 id="💡-왜-https를-사용해야-하나요">💡 <strong>왜 HTTPS를 사용해야 하나요?</strong></h2>
<ul>
<li>🔐 <strong>데이터 암호화</strong>: 제3자가 볼 수 없도록 보호</li>
<li>🧱 <strong>무결성 보장</strong>: 중간에서 데이터가 변경되는 것을 방지</li>
<li>✅ <strong>서버 인증</strong>: 위조 서버에 접속하는 것을 방지</li>
<li>📈 <strong>SEO 향상</strong>: 구글 등 검색 엔진에서 가산점</li>
<li>👥 <strong>사용자 신뢰 증가</strong>: 자물쇠 아이콘이 보안 신뢰도 상승</li>
</ul>
<h2 id="📜-ssltls-인증서란">📜 <strong>SSL/TLS 인증서란?</strong></h2>
<p>HTTPS 적용에 <strong>가장 핵심적인 요소</strong>는 바로 <strong>SSL/TLS 인증서</strong>입니다.</p>
<h3 id="🔐-대표적인-인증서-발급-기관-ca">🔐 <strong>대표적인 인증서 발급 기관 (CA)</strong></h3>
<table>
<thead>
<tr>
<th>CA</th>
<th>특징</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Let&#39;s Encrypt</strong></td>
<td>무료, 자동화 지원</td>
</tr>
<tr>
<td><strong>DigiCert, Sectigo</strong></td>
<td>유료, 높은 신뢰성</td>
</tr>
</tbody></table>
<h2 id="⚙️-https-적용-단계">⚙️ <strong>HTTPS 적용 단계</strong></h2>
<h3 id="1️⃣-도메인-준비--dns-설정">1️⃣ <strong>도메인 준비 &amp; DNS 설정</strong></h3>
<ul>
<li>도메인 이름 구입 (예: <code>example.com</code>)</li>
<li>해당 도메인이 웹 서버의 IP 주소를 <strong>정확히 가리키도록 설정</strong></li>
</ul>
<h3 id="2️⃣-ssltls-인증서-발급">2️⃣ <strong>SSL/TLS 인증서 발급</strong></h3>
<pre><code class="language-bash"># CSR 생성 예시 (OpenSSL)
openssl req -new -newkey rsa:2048 -nodes -keyout your_private.key -out your_domain.csr</code></pre>
<ul>
<li><strong>CSR(Certificate Signing Request)</strong> 생성</li>
<li><strong>CA에 제출 및 도메인 소유권 검증</strong></li>
<li><strong>서버 인증서(.crt) + 중간 인증서(Chain) 발급</strong></li>
</ul>
<h3 id="3️⃣-웹-서버-설정-apachenginx">3️⃣ <strong>웹 서버 설정 (Apache/Nginx)</strong></h3>
<h4 id="✅-apache-설정-예시">✅ Apache 설정 예시</h4>
<pre><code class="language-apache">&lt;VirtualHost *:80&gt;
    ServerName your_domain.com
    Redirect permanent / https://your_domain.com/
&lt;/VirtualHost&gt;

&lt;VirtualHost *:443&gt;
    ServerName your_domain.com

    SSLEngine on
    SSLCertificateFile /path/to/your_certificate.crt
    SSLCertificateKeyFile /path/to/your_private.key
    SSLCertificateChainFile /path/to/your_chain.crt

    DocumentRoot /var/www/your_website
&lt;/VirtualHost&gt;</code></pre>
<h4 id="✅-nginx-설정-예시">✅ Nginx 설정 예시</h4>
<pre><code class="language-nginx">server {
    listen 443 ssl;
    server_name your_domain.com;

    ssl_certificate /path/to/your_certificate.crt;
    ssl_certificate_key /path/to/your_private.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers &#39;ECDHE-ECDSA-AES128-GCM-SHA256:...&#39;;
    ssl_prefer_server_ciphers on;

    location / {
        root /var/www/your_website;
        index index.html;
    }
}

server {
    listen 80;
    server_name your_domain.com;
    return 301 https://$host$request_uri;
}</code></pre>
<h3 id="4️⃣-방화벽-포트-개방">4️⃣ <strong>방화벽 포트 개방</strong></h3>
<pre><code class="language-bash"># HTTPS 포트 허용 (UFW 기준)
sudo ufw allow 443/tcp</code></pre>
<h3 id="5️⃣-웹-서버-재시작">5️⃣ <strong>웹 서버 재시작</strong></h3>
<pre><code class="language-bash">sudo systemctl restart nginx

또는

sudo systemctl restart apache2</code></pre>
<h3 id="6️⃣-https-적용-확인">6️⃣ <strong>HTTPS 적용 확인</strong></h3>
<ul>
<li>웹 브라우저로 <code>https://your_domain.com</code> 에 접속  </li>
<li>주소창에 <strong>🔒 자물쇠 모양</strong>이 나타나는지 확인  </li>
<li>인증서 정보를 클릭하여 <strong>정상적으로 발급된 인증서인지 확인</strong></li>
</ul>
<blockquote>
<p>🔧 <a href="https://www.ssllabs.com/ssltest/">SSL Labs의 SSL Server Test</a>를 이용해 SSL/TLS 설정의 <strong>보안 점수 및 취약점</strong>을 점검할 수 있다.</p>
</blockquote>
<hr>
<h3 id="🛠️-nodejs-express-서버에서의-https-적용-예시">🛠️ <strong>Node.js (Express) 서버에서의 HTTPS 적용 예시</strong></h3>
<p>Node.js 환경에서 Express 앱을 직접 HTTPS로 실행할 수 있습니다. 다만 <strong>실제 운영환경에서는 Nginx, Apache를 리버스 프록시로 사용하는 방식</strong>이 더 일반적입니다.</p>
<pre><code class="language-javascript">// server.js
const express = require(&#39;express&#39;);
const https = require(&#39;https&#39;);
const fs = require(&#39;fs&#39;);

const app = express();

// SSL/TLS 인증서 파일 경로
const privateKey = fs.readFileSync(&#39;/path/to/your_private.key&#39;, &#39;utf8&#39;);
const certificate = fs.readFileSync(&#39;/path/to/your_certificate.crt&#39;, &#39;utf8&#39;);
const ca = fs.readFileSync(&#39;/path/to/your_chain.crt&#39;, &#39;utf8&#39;); // (선택 사항)

const credentials = { key: privateKey, cert: certificate, ca: ca };

// HTTP 서버 (옵션: HTTPS로 리다이렉트)
app.listen(80, () =&gt; {
  console.log(&#39;HTTP Server running on port 80&#39;);
});

// HTTPS 서버
const httpsServer = https.createServer(credentials, app);

httpsServer.listen(443, () =&gt; {
  console.log(&#39;HTTPS Server running on port 443&#39;);
});</code></pre>
<h3 id="🌐-로드-밸런서load-balancer란">🌐 <strong>로드 밸런서(Load Balancer)란?</strong></h3>
<blockquote>
<p>로드 밸런서는 <strong>트래픽을 여러 서버에 분산</strong>하여 시스템의 <strong>성능, 안정성, 확장성</strong>을 높이는 핵심 구성 요소입니다.</p>
</blockquote>
<h4 id="💡-주요-역할">💡 <strong>주요 역할</strong></h4>
<ul>
<li>📶 <strong>트래픽 분산</strong>  </li>
<li>🚀 <strong>성능 최적화</strong>  </li>
<li>⚙️ <strong>고가용성 (High Availability)</strong>  </li>
<li>📈 <strong>확장성 (Scalability)</strong>  </li>
<li>🔐 <strong>보안 강화 (SSL Offloading, DDoS 방어 등)</strong></li>
</ul>
<h3 id="🔁-로드-밸런싱-알고리즘">🔁 <strong>로드 밸런싱 알고리즘</strong></h3>
<table>
<thead>
<tr>
<th>알고리즘</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><strong>라운드 로빈</strong></td>
<td>서버에 순차적으로 요청 분배</td>
</tr>
<tr>
<td><strong>가중치 라운드 로빈</strong></td>
<td>성능에 따라 비중 조절</td>
</tr>
<tr>
<td><strong>최소 연결</strong></td>
<td>현재 연결 수가 가장 적은 서버로</td>
</tr>
<tr>
<td><strong>최소 응답 시간</strong></td>
<td>응답 속도가 빠른 서버 우선</td>
</tr>
<tr>
<td><strong>IP 해시</strong></td>
<td>같은 클라이언트는 같은 서버로 유지</td>
</tr>
<tr>
<td><strong>최소 대역폭</strong></td>
<td>트래픽 양이 적은 서버로 우선 배정</td>
</tr>
</tbody></table>
<h3 id="⚙️-로드-밸런서-종류">⚙️ <strong>로드 밸런서 종류</strong></h3>
<h4 id="✅-하드웨어-기반">✅ 하드웨어 기반</h4>
<ul>
<li>F5 BIG-IP, Citrix NetScaler 등  </li>
<li>고성능/고신뢰성, <strong>높은 비용과 복잡한 관리</strong></li>
</ul>
<h4 id="✅-소프트웨어-기반">✅ 소프트웨어 기반</h4>
<ul>
<li><strong>오픈소스</strong>: Nginx, HAProxy 등  </li>
<li><strong>클라우드형</strong>:  <ul>
<li>AWS ELB (ALB, NLB)  </li>
<li>Azure Load Balancer  </li>
<li>Google Cloud Load Balancer  </li>
</ul>
</li>
</ul>
<h3 id="☁️-클라우드-로드-밸런서의-작동-방식-예-aws-alb">☁️ <strong>클라우드 로드 밸런서의 작동 방식 (예: AWS ALB)</strong></h3>
<ol>
<li><strong>DNS 등록</strong>: 도메인이 로드 밸런서를 가리킴  </li>
<li><strong>클라이언트 요청</strong>: 도메인 접속 시 로드 밸런서로 전달  </li>
<li><strong>리스너</strong>: 80/443 포트 등에서 요청 수신  </li>
<li><strong>대상 그룹(Target Group)</strong>: 연결된 백엔드 서버 모음  </li>
<li><strong>헬스 체크</strong>: 비정상 서버는 자동 제외  </li>
<li><strong>라우팅 규칙</strong>: 경로, 호스트, 헤더 기반 분배  </li>
<li><strong>응답</strong>: 결과를 클라이언트에게 전달</li>
</ol>
<h3 id="🔐-로드-밸런서--https--ssltls-오프로딩">🔐 <strong>로드 밸런서 + HTTPS = SSL/TLS 오프로딩</strong></h3>
<blockquote>
<p><strong>SSL/TLS 오프로딩(Offloading)</strong>:  
<strong>로드 밸런서가 HTTPS 암호화를 처리하고</strong>, 백엔드 서버에는 <strong>복호화된 평문 요청을 전달</strong>하는 방식.</p>
</blockquote>
<ul>
<li><strong>클라이언트 ↔ 로드 밸런서</strong>: HTTPS  </li>
<li><strong>로드 밸런서 ↔ 백엔드 서버</strong>: HTTP  </li>
<li><strong>장점</strong>: 백엔드 서버의 부하 감소, 암호화 비용 분산  </li>
<li><strong>보안</strong>: VPC 내부 통신으로 <strong>HTTP 사용에도 안전</strong></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[5월 5째주 Weekly paper_webSocket]]></title>
            <link>https://velog.io/@nancy_yeonjeong/5%EC%9B%94-5%EC%A7%B8%EC%A3%BC-Weekly-paperwebSocket</link>
            <guid>https://velog.io/@nancy_yeonjeong/5%EC%9B%94-5%EC%A7%B8%EC%A3%BC-Weekly-paperwebSocket</guid>
            <pubDate>Mon, 26 May 2025 00:00:47 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/5f54ce0a-906f-40f9-b0ff-6c61c83068e6/image.png" alt=""></p>
<h2 id="🇶-어떤-기능을-구현할-때-websocket을-사용하는-것이-적절한가요">🇶 어떤 기능을 구현할 때 WebSocket을 사용하는 것이 적절한가요?</h2>
<table>
<thead>
<tr>
<th>상황</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>🔄 <strong>실시간 양방향 통신이 필요한 경우</strong></td>
<td>클라이언트와 서버가 지속적으로 데이터를 주고받아야 할 때 (예: 채팅, 게임, 주식 시세 등)</td>
</tr>
<tr>
<td>🚫 <strong>HTTP Polling의 비효율성 극복</strong></td>
<td>서버에 주기적으로 요청을 보내는 방식보다 효율적이며 트래픽 감소 효과가 있음</td>
</tr>
<tr>
<td>📡 <strong>Push 알림 기능 구현</strong></td>
<td>서버가 클라이언트에 이벤트 발생 시 실시간으로 데이터를 푸시할 수 있음</td>
</tr>
<tr>
<td>🔧 <strong>지속적인 연결 유지 필요</strong></td>
<td>클라이언트와 서버 간 연결을 끊지 않고 상태를 유지하는 애플리케이션에 적합 (예: 협업 도구, IoT 기기 등)</td>
</tr>
</tbody></table>
<h2 id="🇶-실시간-서비스-구현에-사용되는-webrtc와-grpc에-대해-설명해-주세요">🇶 실시간 서비스 구현에 사용되는 WebRTC와 gRPC에 대해 설명해 주세요.</h2>
<table>
<thead>
<tr>
<th>항목</th>
<th>WebRTC</th>
<th>gRPC</th>
</tr>
</thead>
<tbody><tr>
<td>📌 <strong>정의</strong></td>
<td>브라우저 간 <strong>실시간 미디어(P2P) 스트리밍</strong> 기술</td>
<td>Google에서 개발한 고성능 <strong>원격 프로시저 호출(RPC)</strong> 프레임워크</td>
</tr>
<tr>
<td>🎯 <strong>주 용도</strong></td>
<td>실시간 <strong>영상 통화, 음성 채팅</strong>, 화면 공유 등</td>
<td>마이크로서비스 간 통신, 클라이언트-서버 간 데이터 교환</td>
</tr>
<tr>
<td>🔄 <strong>통신 방식</strong></td>
<td>주로 <strong>P2P</strong> 연결 (시그널링 서버는 필요)</td>
<td><strong>클라이언트-서버</strong> 모델 기반</td>
</tr>
<tr>
<td>📦 <strong>데이터 처리</strong></td>
<td>미디어(음성, 영상) 중심</td>
<td>구조화된 데이터 중심 (Protocol Buffers 사용)</td>
</tr>
<tr>
<td>🧩 <strong>특징</strong></td>
<td>낮은 지연, 실시간 미디어 전송에 최적화</td>
<td>빠르고 경량, 양방향 스트리밍 가능</td>
</tr>
<tr>
<td>🌐 <strong>언어/환경 지원</strong></td>
<td>웹 브라우저, 모바일 앱 등 다양한 환경 지원</td>
<td>Go, Java, Python 등 다양한 언어 지원</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[💡5월 4째주 Weekly paper_관계형데이터베이스]]></title>
            <link>https://velog.io/@nancy_yeonjeong/5%EC%9B%94-4%EC%A7%B8%EC%A3%BC-Weekly-paper%EA%B4%80%EA%B3%84%ED%98%95%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4</link>
            <guid>https://velog.io/@nancy_yeonjeong/5%EC%9B%94-4%EC%A7%B8%EC%A3%BC-Weekly-paper%EA%B4%80%EA%B3%84%ED%98%95%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4</guid>
            <pubDate>Sun, 18 May 2025 17:09:26 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/e799054c-5b1e-470c-bbf0-e852f2de4aea/image.png" alt=""></p>
<h1 id="💡-관계형-데이터베이스-무결성-integrity">💡 관계형 데이터베이스: 무결성 (Integrity)</h1>
<h2 id="✅-데이터의-무결성이란">✅ 데이터의 무결성이란?</h2>
<ul>
<li><strong>정확성</strong>, <strong>일관성</strong>, <strong>유효성</strong>이 유지되는 상태를 의미합니다.  </li>
<li>데이터의 연산이나 입력에 제한을 두어 무결성을 유지합니다.</li>
</ul>
<h2 id="🔒-무결성의-종류">🔒 무결성의 종류</h2>
<table>
<thead>
<tr>
<th>무결성 종류</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><strong>1. 개체 무결성</strong></td>
<td>모든 테이블은 <strong>기본 키</strong>를 가져야 하며, <strong>고유한 값</strong>을 가지며 <strong>NULL을 허용하지 않음</strong></td>
</tr>
<tr>
<td><strong>2. 참조 무결성</strong></td>
<td>외래 키는 <strong>존재하지 않는 값</strong>을 참조할 수 없음 → <strong>일관된 참조 유지</strong></td>
</tr>
<tr>
<td><strong>3. 도메인 무결성</strong></td>
<td>필드의 <strong>데이터 타입</strong>, <strong>NULL 허용 여부</strong> 등을 통해 유효한 값만 입력되도록 제한</td>
</tr>
<tr>
<td><strong>4. 사용자 정의 무결성</strong></td>
<td>사용자가 정의한 <strong>제약 조건</strong>을 만족해야 함 (예: 나이는 0 이상 등)</td>
</tr>
<tr>
<td><strong>5. NULL 무결성</strong></td>
<td>특정 속성 값은 <strong>NULL이 될 수 없음</strong></td>
</tr>
<tr>
<td><strong>6. 고유 무결성</strong></td>
<td>하나의 속성에 대해 각 튜플이 <strong>서로 다른 값</strong>을 가져야 함</td>
</tr>
<tr>
<td><strong>7. 키 무결성</strong></td>
<td>하나의 relation에는 <strong>적어도 하나의 키(Primary Key)</strong>가 있어야 함</td>
</tr>
<tr>
<td><strong>8. 관계 무결성</strong></td>
<td>relation 간 <strong>적절한 삽입/참조/관계 조건</strong>이 만족되어야 함</td>
</tr>
</tbody></table>
<hr>
<h1 id="💡-관계형-데이터베이스-마이그레이션-migration">💡 관계형 데이터베이스: 마이그레이션 (Migration)</h1>
<p>관계형 데이터베이스 마이그레이션은 한 DB 시스템에서 <strong>다른 시스템으로 데이터 및 구조를 이전</strong>하는 과정을 말합니다.</p>
<h2 id="필요성">필요성</h2>
<ul>
<li><strong>업데이트</strong>: 구버전 DBMS의 지원 중단</li>
<li><strong>성능 향상</strong>: 더 빠르고 효율적인 DBMS로 이동</li>
<li><strong>클라우드 이전</strong>: 클라우드로 이동하여 관리 용이성 확보</li>
<li><strong>데이터베이스 통합</strong>: 여러 시스템을 하나로 통합</li>
<li><strong>구조 변경</strong>: 스키마나 모델 변경 필요 시</li>
</ul>
<h2 id="과정">과정</h2>
<ol>
<li><p><strong>계획 및 분석</strong>  </p>
<ul>
<li>기존 시스템과 대상 시스템 파악  </li>
<li>데이터 양, 구조, 스키마 분석  </li>
</ul>
</li>
<li><p><strong>데이터 추출 및 변환</strong>  </p>
<ul>
<li>데이터를 추출하고, 새 시스템에 맞게 변환  </li>
</ul>
</li>
<li><p><strong>스키마 변환</strong>  </p>
<ul>
<li>기존 스키마 → 새로운 DBMS에 맞는 스키마로 변환  </li>
</ul>
</li>
<li><p><strong>데이터 로드</strong>  </p>
<ul>
<li>변환된 데이터를 새 DB에 로드  </li>
</ul>
</li>
<li><p><strong>테스트 및 검증</strong>  </p>
<ul>
<li>정확성, 일관성, 성능 테스트  </li>
</ul>
</li>
<li><p><strong>최종 전환</strong>  </p>
<ul>
<li>새 시스템으로 완전 전환하고 기존 시스템 종료 </li>
</ul>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[💡 4월 3째주 Weekly paper_REST API]]></title>
            <link>https://velog.io/@nancy_yeonjeong/4%EC%9B%94-3%EC%A7%B8%EC%A3%BC-Weekly-paperREST-API</link>
            <guid>https://velog.io/@nancy_yeonjeong/4%EC%9B%94-3%EC%A7%B8%EC%A3%BC-Weekly-paperREST-API</guid>
            <pubDate>Mon, 07 Apr 2025 14:46:08 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/8750072d-cc38-47ad-8027-1a4647c87dfe/image.png" alt=""></p>
<h1 id="💡rest">💡REST</h1>
<h2 id="1-의미">1. 의미</h2>
<ul>
<li>REspresentational Status Transfer</li>
<li>자원의 상태를 주고받는 모든 것을 의미</li>
<li>HTTp URI를 통해서 자원(Resource)를 명시하고, HTTP Method를 통해서 해당 자원에 대한 CRUD Operation을 적용하는 것</li>
</ul>
<h2 id="2-구성요소">2. 구성요소</h2>
<h3 id="1-resource">1) Resource</h3>
<p> : 서버는 Unique한 ID를 가지는 Resource를 가지고 있으며, 클라이언트는 이러한 Resource에 요청을 보내고 이러한 Resource는 URL에 해당한다.</p>
<h3 id="2-행위verb">2) 행위(Verb)</h3>
<ul>
<li>HTTP 프로토콜의 Method를 사용</li>
<li>HTTP 프로토콜은 GET/POST/PUT/DELETE와 같은 메서드를 제공<h3 id="3-표현representation-of-resource">3) 표현(Representation of Resource)</h3>
: 클라이언트와 서버가 데이터를 주고받는 형태로 json, xml, text, rss 등이 있다. 최근에는 Key, Value를 활용하는 json을 주로 사용</li>
</ul>
<h2 id="3-특징">3. 특징</h2>
<h3 id="1-server-client서버-클라이언트-구조">1) Server-Client(서버-클라이언트 구조)</h3>
<ul>
<li><p>클라이언트에서 자원이 있는 서버에 자원을 요청하는 구조</p>
</li>
<li><p>REST Server: API를 제공하고 비즈니스 로직 처리 및 저장</p>
</li>
<li><p>Client : 사용자 인증이나 context(세션, 로그인 정보) 등을 직접 관리</p>
<h3 id="2-stateless무상태">2) Stateless(무상태)</h3>
</li>
<li><p>HTTP 프로토콜은 Stateless Protocol이므로 REST 역시 무상태성을 갖음</p>
</li>
<li><p>Client의 context를 Server에 저장하지 않음 -&gt; 세션/쿠키와 같은 context 정보를 신경쓰지 않아도 되서 구현이 단순</p>
</li>
<li><p>Server는 각각의 요청을 완전히 별개의 것으로 인식하고 처리 -&gt; 이전의 요청이 다음 요청의 처리에 연관되어서는 안됨</p>
</li>
<li><p>Server의 처리 방식에 일관성을 부여하고 부담이 줄어들며, 서비스의 자유도가 높아짐</p>
<h3 id="3-cacheable캐시-처리-기능">3) Cacheable(캐시 처리 기능)</h3>
</li>
<li><p>웹 표준 HTTP 프로토콜을 그대로 사용하므로 웹에서 사용하는 기존의 인프라를 그대로 활용할 수 있기에 캐싱 기능을 적용 가능</p>
</li>
<li><p>Last-Modified 태그나 E-Tag를 이용하면 캐싱 구현이 가능하므로 대량의 요청을 효율적으로 처리 가능</p>
</li>
<li><p>캐시 사용을 통해 응답시간이 빨라지고 REST Server 트랜잭션이 발생하지 않기 때문에 전체 응답시간, 성능, 서버의 자원 이용률 향상 가능</p>
<h3 id="4-layeres-system계층화">4) Layeres System(계층화)</h3>
</li>
<li><p>Cilent 는 RESt Server만 호출 -&gt; REST Server는 다중 계층으로 구성 가능</p>
</li>
<li><p>API Server는 순수 비즈니스 로직을 수행하고 그 앞단에 보안, 로드밸런싱, 암호화, 사용자 인증 등을 추가하여 구조상의 유연성 부여 + 로드밸런싱, 공유 캐시등을 통해서 확장성과 보안성을 향상 가능</p>
</li>
<li><p>RROXY, 게이트웨이 같은 네트워크 기반의 중간 매체 사용 가능</p>
<blockquote>
<ul>
<li><strong>로드밸런싱</strong> : 서버가 처리해야할 업무 혹은 요청(Load)를 여러 대의 서버로 나누어 (Balancing) 처리하는 것을 의미</li>
<li><strong>PROXY(&#39;대신&#39;의 의미를 가짐)</strong>: 중계 기능을 하는 것 -&gt; 보안 상의 문제로 직접 통신 할 수 없을 때 중계해주는 서버를 프록시 서버라고 부름<ul>
<li><strong>게이트웨이</strong> : 한 네트워크(segment)에서 다른 네트워크로 이동하기 위하여 거쳐야 하는 지점. 서로 다른 네트워크를 연결함 </li>
</ul>
</li>
</ul>
</blockquote>
<h3 id="5-code-on-demandoptional">5) Code-On-Demand(optional)</h3>
</li>
<li><p>Server로부터 스크립트를 받아서 Cilent 에서 실행</p>
<h3 id="6-uniform-interface인터페이스-일관성">6) Uniform Interface(인터페이스 일관성)</h3>
</li>
<li><p>URI로 지정한 Resource에 대한 조작을 통일되고 한정적인 인터페이스로 수행</p>
</li>
<li><p>HTTP 표준 프로토콜에 따르는 모든 플랫폼에서 사용 가능 </p>
</li>
<li><p>특정 언어나 기술에 종속되지 않음</p>
</li>
</ul>
<h2 id="4-설계-규칙">4. 설계 규칙</h2>
<p> 1) URI는 명사를 사용 
 2) 슬래시(/)로 계층 관계를 표현
 3) URI의 마지막에는 슬래시(/)를 붙이지 않음 
 4) URI는 소문자로만 구성
 5) 가독성이 떨어지는 경우 하이픈을 사용 
 6) 대문자와 소문자로 URI를 정의하면 기억하기 어려우며 잘못 적을 가능성이 높아짐</p>
<blockquote>
<p><strong>RESTful</strong> </p>
<ul>
<li>REST라는 아키텍처를 구현하는 웹 서비스를 나타내기 위해 사용되는 용어</li>
<li>이해와 사용이 쉬운 REST API를 만드는 것</li>
</ul>
</blockquote>
<h1 id="💡무상태성stateless">💡무상태성(Stateless)</h1>
<p>: 서버와 클라언트 간의 요청이 독립적이라는 것을 의미 
-&gt; <em>각 요청은 서버가 클라이언트의 상태를 저장하지 않아 이전 요청의 상태에 의존 ❌</em></p>
<h2 id="사용의-필요성">사용의 필요성</h2>
<h3 id="1-서버의-확장성을-높임">1) 서버의 확장성을 높임</h3>
<p>서버는 각 요청을 독립적으로 처리할 수 있기 때문에, 여러 서버에 요청을 분산시킬 수 있음 </p>
<h3 id="2-클라이언트와-서버-간의-통신을-단순화">2) 클라이언트와 서버 간의 통신을 단순화</h3>
<p>클라이언트는 각 요청에 필요한 모든 정보를 포함시켜야하며, 서버는 이를 기반으로 요청을 처리</p>
<h3 id="3-서버의-복잡성-완화">3) 서버의 복잡성 완화</h3>
<p>서버가 클라이언트의 상태를 저장하지 않기 때문에 서버의 상태를 관리할 필요성 없어짐</p>
<h3 id="4-클라이언트와-서버를-독립적으로-개발하고-배포-가능">4) 클라이언트와 서버를 독립적으로 개발하고 배포 가능</h3>
<p>클라이언트와 서버 간의 통신이 독립적</p>
<h2 id="유지-방법">유지 방법</h2>
<h3 id="1-각-요청에-필요한-모든-정보-포함">1) 각 요청에 필요한 모든 정보 포함</h3>
<p>클라이언트는 각 요청에 인증 정보를 포함</p>
<h3 id="2-서버는-요청을-모두-독립적으로-처리">2) 서버는 요청을 모두 독립적으로 처리</h3>
<p>서버는 클라이언트의 상태를 저장하지 않으며 각 요청을 독립적으로 처리</p>
<h3 id="3-클라이언트와-서버-간의-통신-단순화">3) 클라이언트와 서버 간의 통신 단순화</h3>
<p> 클라이언트는 각 요청에 필요한 모든 정보를 포함시켜야하며, 서버는 이를 기반으로 요청을 처리</p>
<h1 id="💡-cors">💡 CORS</h1>
<ul>
<li>교차 출처 리소스 공유(Cross-Origin Resource Sharing)</li>
<li>브라우저가 자신의 출처가 아닌 다른 어떤 출처(도메인, 스킴 혹은 포트)로부터 자원을 로딩하는 것을 허용하도록 서버가 허가해주는 HTTP 헤더 기반 메커니즘<ul>
<li>도메인(Hostname): naver.com</li>
<li>출처(Origin): <a href="https://www.naver.com">https://www.naver.com</a><blockquote>
<p><strong>Example.</strong>
<a href="https://domain-a.com">https://domain-a.com</a> 에서 제공되는 프론트엔드JavaScript 코드가 fetch()를 사용하여 <a href="http://domain-b.com/data.json%EC%97%90">http://domain-b.com/data.json에</a> 요청하는 경우</p>
</blockquote>
</li>
</ul>
</li>
</ul>
<h2 id="cors-에러-대응">CORS 에러 대응</h2>
<p><strong>1. 서버에서 <code>Access-Control-Allow-Origin</code> 헤더 설정 -&gt; 수락할 출처 명시적 지정 가능</strong> </p>
<pre><code>&#39;Access-Control-Allow-Origin&#39;: &lt;origin&gt; | * // 출처상관 없이 리소스 접근 가능
&#39;Access-Control-Allow-Origin&#39;: &lt;origin&gt; | https://naver.com // 네이버만 접근 가능</code></pre><p>** 2. 프락시 서버 사용하기**</p>
<ul>
<li>웹 애플리케이션이 리소스와 동일한 출처에서 요청을 보내는 것처럼 보여서 CORS 에러 방지 가능</li>
</ul>
<blockquote>
<p>출처
<a href="https://velog.io/@gomuzom/RESTful-Api">https://velog.io/@gomuzom/RESTful-Api</a>
<a href="https://f-lab.kr/insight/understanding-restful-api-20240617">https://f-lab.kr/insight/understanding-restful-api-20240617</a>
<a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Guides/CORS">https://developer.mozilla.org/ko/docs/Web/HTTP/Guides/CORS</a>
<a href="https://docs.tosspayments.com/resources/glossary/cors#%EC%84%9C%EB%B2%84%EC%97%90%EC%84%9C-access-control-allow-origin-%EC%9D%91%EB%8B%B5-%ED%97%A4%EB%8D%94-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0">https://docs.tosspayments.com/resources/glossary/cors#%EC%84%9C%EB%B2%84%EC%97%90%EC%84%9C-access-control-allow-origin-%EC%9D%91%EB%8B%B5-%ED%97%A4%EB%8D%94-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[💡 4월 2째주 Weekly paper_로그인]]></title>
            <link>https://velog.io/@nancy_yeonjeong/4%EC%9B%94-2%EC%A7%B8%EC%A3%BC-Weekly-paper%EB%A1%9C%EA%B7%B8%EC%9D%B8</link>
            <guid>https://velog.io/@nancy_yeonjeong/4%EC%9B%94-2%EC%A7%B8%EC%A3%BC-Weekly-paper%EB%A1%9C%EA%B7%B8%EC%9D%B8</guid>
            <pubDate>Mon, 07 Apr 2025 00:19:45 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/10a313dc-0580-4499-beef-706a4047cc0f/image.png" alt=""></p>
<h1 id="세션-기반-인증-vs-토큰-기반-인증">세션 기반 인증 vs 토큰 기반 인증</h1>
<h2 id="세션-기반-인증-session-based-authentication">세션 기반 인증 (Session-based Authentication)</h2>
<p><strong>개념:</strong></p>
<ul>
<li>서버 측에서 사용자의 인증 정보를 저장하고 관리하는 방식입니다.</li>
<li>사용자가 로그인하면 서버는 세션(Session)이라는 고유한 정보를 생성하여 저장합니다.</li>
<li>이 세션 ID를 클라이언트(웹 브라우저 등)에 쿠키 형태로 전달합니다.</li>
<li>클라이언트는 이후 요청 시마다 이 쿠키를 서버에 함께 전송하여, 서버는 쿠키에 담긴 세션 ID를 통해 사용자를 식별하고 인증 상태를 유지합니다.</li>
</ul>
<p><strong>작동 방식:</strong></p>
<ol>
<li><strong>로그인 요청:</strong> 사용자가 아이디와 비밀번호 등 인증 정보를 서버에 전송합니다.</li>
<li><strong>인증 및 세션 생성:</strong> 서버는 받은 정보를 검증하고, 유효한 경우 세션을 생성하여 서버의 저장소 (메모리, 데이터베이스 등)에 저장합니다. 이 세션에는 사용자 정보, 로그인 시간, 만료 시간 등이 포함될 수 있습니다.</li>
<li><strong>세션 ID 전달:</strong> 서버는 생성된 세션의 고유한 ID를 쿠키에 담아 클라이언트에게 응답으로 보냅니다.</li>
<li><strong>쿠키 저장 및 전송:</strong> 클라이언트는 받은 쿠키를 저장하고, 이후 서버에 요청을 보낼 때마다 해당 쿠키를 HTTP 헤더에 담아 함께 전송합니다.</li>
<li><strong>세션 ID 확인 및 인증 유지:</strong> 서버는 요청에 포함된 쿠키에서 세션 ID를 추출하여 서버에 저장된 세션 정보와 비교합니다. 일치하는 세션이 있다면 해당 사용자를 인증된 것으로 간주하고 요청을 처리합니다.</li>
<li><strong>로그아웃:</strong> 사용자가 로그아웃하면 서버는 해당 세션을 무효화하거나 삭제하고, 클라이언트 측의 쿠키를 삭제하거나 만료시킵니다.</li>
</ol>
<p><strong>장점:</strong></p>
<ul>
<li><strong>간단한 구현:</strong> 비교적 구현이 간단하고 직관적입니다.</li>
<li><strong>중앙 집중식 관리:</strong> 서버에서 사용자 세션을 중앙에서 관리하므로 보안 정책 적용 및 사용자 정보 관리가 용이합니다.</li>
<li><strong>세션 제어 용이:</strong> 서버에서 세션의 만료 시간을 설정하거나 강제로 로그아웃시키는 등 세션 관리가 용이합니다.</li>
<li><strong>상태 유지 (Stateful):</strong> 서버가 세션 정보를 기억하므로 각 요청마다 사용자 정보를 다시 확인할 필요가 없습니다.</li>
</ul>
<p><strong>단점:</strong></p>
<ul>
<li><strong>서버 자원 사용 증가:</strong> 많은 사용자의 세션 정보를 서버가 저장하고 관리해야 하므로 서버 부하가 증가할 수 있습니다.</li>
<li><strong>확장성 문제:</strong> 여러 대의 서버를 사용하는 환경 (로드 밸런싱)에서 세션 동기화 문제가 발생할 수 있습니다. 이를 해결하기 위해 세션 공유 메커니즘 (예: Redis, Memcached)이 필요합니다.</li>
<li><strong>CORS (Cross-Origin Resource Sharing) 문제:</strong> 쿠키 기반 인증은 다른 도메인 간 요청에서 제약이 있을 수 있습니다.</li>
<li><strong>CSRF (Cross-Site Request Forgery) 공격에 취약:</strong> 쿠키를 이용하므로 CSRF 공격에 취약할 수 있으며, 이를 방지하기 위한 추가적인 보안 대책 (예: CSRF 토큰)이 필요합니다.</li>
</ul>
<h2 id="토큰-기반-인증-token-based-authentication">토큰 기반 인증 (Token-based Authentication)</h2>
<p><strong>개념:</strong></p>
<ul>
<li>클라이언트 측에서 토큰을 저장하고 사용하여 사용자를 인증하는 방식입니다.</li>
<li>사용자가 로그인하면 서버는 인증 성공 시 클라이언트에게 토큰 (일반적으로 JWT - JSON Web Token)을 발급합니다.</li>
<li>이 토큰은 클라이언트 측 (로컬 스토리지, 쿠키 등)에 저장됩니다.</li>
<li>클라이언트는 이후 요청 시마다 이 토큰을 HTTP 헤더 (Authorization 헤더에 Bearer 스키마를 사용하여 포함)에 담아 서버에 전송합니다.</li>
<li>서버는 토큰의 유효성을 검증하여 사용자를 인증합니다. 서버는 토큰 정보를 저장하지 않는 Stateless 방식입니다.</li>
</ul>
<p><strong>작동 방식:</strong></p>
<ol>
<li><strong>로그인 요청:</strong> 사용자가 아이디와 비밀번호 등 인증 정보를 서버에 전송합니다.</li>
<li><strong>인증 및 토큰 생성:</strong> 서버는 받은 정보를 검증하고, 유효한 경우 접근 토큰 (Access Token)을 생성하여 클라이언트에게 응답으로 보냅니다. 필요에 따라 갱신 토큰 (Refresh Token)도 함께 발급될 수 있습니다.</li>
<li><strong>토큰 저장:</strong> 클라이언트는 받은 토큰을 안전한 저장소 (예: Local Storage, HttpOnly 쿠키)에 저장합니다.</li>
<li><strong>요청 시 토큰 전송:</strong> 클라이언트는 보호된 리소스에 접근할 때마다 HTTP 요청 헤더의 Authorization 필드에 Bearer 스키마와 함께 토큰을 담아 전송합니다 (예: <code>Authorization: Bearer &lt;token&gt;</code>).</li>
<li><strong>토큰 검증:</strong> 서버는 요청 헤더에서 토큰을 추출하여 서명 (Signature)을 검증하고, 만료 여부 등을 확인하여 토큰의 유효성을 검증합니다.</li>
<li><strong>인증 및 권한 부여:</strong> 토큰이 유효하면 토큰에 포함된 정보 (Payload)를 기반으로 사용자를 식별하고 권한을 확인하여 요청을 처리합니다.</li>
<li><strong>로그아웃 (선택적):</strong> 토큰 기반 인증은 Stateless하므로 명시적인 로그아웃 과정이 필수는 아닙니다. 클라이언트 측에서 토큰을 삭제하면 더 이상 인증된 요청을 보낼 수 없습니다. 서버 측에서 토큰을 무효화하는 메커니즘 (예: 블랙리스트 관리)을 구현할 수도 있습니다.</li>
<li><strong>토큰 갱신 (Refresh Token 사용 시):</strong> 접근 토큰이 만료되면 클라이언트는 갱신 토큰을 서버에 보내 새로운 접근 토큰을 발급받을 수 있습니다.</li>
</ol>
<p><strong>장점:</strong></p>
<ul>
<li><strong>확장성:</strong> 서버가 토큰 정보를 저장하지 않으므로 여러 대의 서버를 사용하는 환경에서 확장성이 뛰어납니다 (Stateless).</li>
<li><strong>다양한 플랫폼 지원:</strong> 토큰은 쿠키에 의존하지 않으므로 웹 브라우저뿐만 아니라 모바일 앱, 데스크톱 앱 등 다양한 플랫폼에서 사용 가능합니다.</li>
<li><strong>CORS 문제 해결 용이:</strong> HTTP 헤더를 통해 토큰을 전달하므로 CORS 제약에서 비교적 자유롭습니다.</li>
<li><strong>보안성:</strong> JWT는 서명을 통해 위변조를 방지할 수 있으며, 필요한 정보만 토큰에 담아 전송하여 보안성을 높일 수 있습니다.</li>
<li><strong>API 서버에 적합:</strong> RESTful API와 같은 Stateless 환경에 적합합니다.</li>
</ul>
<p><strong>단점:</strong></p>
<ul>
<li><strong>구현 복잡성:</strong> 세션 기반 인증에 비해 구현이 다소 복잡할 수 있습니다.</li>
<li><strong>토큰 탈취 위험:</strong> 토큰이 클라이언트 측에 저장되므로 토큰이 탈취될 경우 보안에 취약해질 수 있습니다. 토큰의 유효 기간을 짧게 설정하고 안전한 저장 방식을 사용하는 것이 중요합니다.</li>
<li><strong>토큰 무효화의 어려움:</strong> 일단 발급된 토큰은 만료될 때까지 유효하므로, 서버 측에서 강제로 특정 토큰을 무효화하기 어려울 수 있습니다. 이를 해결하기 위해 추가적인 메커니즘 (예: 블랙리스트 관리)이 필요합니다.</li>
<li><strong>토큰 크기:</strong> 토큰에 많은 정보를 담을 경우 크기가 커져 네트워크 트래픽을 증가시킬 수 있습니다.</li>
</ul>
<h2 id="요약-비교">요약 비교</h2>
<table>
<thead>
<tr>
<th align="left">특징</th>
<th align="left">세션 기반 인증 (Session-based Authentication)</th>
<th align="left">토큰 기반 인증 (Token-based Authentication)</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>상태 유지</strong></td>
<td align="left">Stateful (서버가 세션 정보 저장)</td>
<td align="left">Stateless (서버는 토큰 정보 저장 안 함)</td>
</tr>
<tr>
<td align="left"><strong>저장 위치</strong></td>
<td align="left">세션 정보: 서버, 세션 ID: 쿠키</td>
<td align="left">토큰: 클라이언트 (로컬 스토리지, 쿠키 등)</td>
</tr>
<tr>
<td align="left"><strong>확장성</strong></td>
<td align="left">제한적 (세션 동기화 필요)</td>
<td align="left">우수</td>
</tr>
<tr>
<td align="left"><strong>플랫폼 지원</strong></td>
<td align="left">웹 브라우저에 최적화</td>
<td align="left">다양한 플랫폼 지원</td>
</tr>
<tr>
<td align="left"><strong>CORS</strong></td>
<td align="left">문제 발생 가능성 있음</td>
<td align="left">비교적 자유로움</td>
</tr>
<tr>
<td align="left"><strong>보안</strong></td>
<td align="left">CSRF 공격에 취약, 세션 관리 중요</td>
<td align="left">토큰 탈취 위험 존재, 토큰 관리 및 유효 기간 중요</td>
</tr>
<tr>
<td align="left"><strong>구현 난이도</strong></td>
<td align="left">비교적 간단</td>
<td align="left">다소 복잡</td>
</tr>
<tr>
<td align="left"><strong>API 적합성</strong></td>
<td align="left">전통적인 웹 애플리케이션에 주로 사용</td>
<td align="left">RESTful API 등 Stateless 환경에 적합</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[💡 3월 4째주 Weekly paper_Prisma]]></title>
            <link>https://velog.io/@nancy_yeonjeong/3%EC%9B%94-4%EC%A7%B8%EC%A3%BC-Weekly-paperPrisma</link>
            <guid>https://velog.io/@nancy_yeonjeong/3%EC%9B%94-4%EC%A7%B8%EC%A3%BC-Weekly-paperPrisma</guid>
            <pubDate>Sun, 23 Mar 2025 05:32:04 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/62c59729-1aab-407b-8439-27741a2dfda4/image.webp" alt=""></p>
<h1 id="🔖-웹-서비스에서-관계형-데이터베이스를-사용하는-이유-중-하나를-설명해-주세요">🔖 웹 서비스에서 관계형 데이터베이스를 사용하는 이유 중 하나를 설명해 주세요.</h1>
<h2 id="databasedb">DataBase(DB)</h2>
<ul>
<li>데이터를 담아두는 저장소<h3 id="1-sql-방식">1) SQL 방식</h3>
</li>
<li>데이터들을 엑셀과 비슷한 표에 정리해두는 방식</li>
<li>표 사이에 관계성을 부여 가능 -&gt; 관계성을 mapping해주는 ORM 사용</li>
<li>Oracle, MySQL, Postgres<h3 id="2-nosql">2) NoSQL</h3>
</li>
<li>서류 봉투에 문서를 모아두는 방식</li>
<li>서류봉투 = 컬렉션 -&gt; ODM</li>
<li>MongoDB, FireBase</li>
</ul>
<h2 id="관계형비관계형-데이터베이스">관계형/비관계형 데이터베이스</h2>
<h3 id="1-관계형-데이터베이스rdbms">1. 관계형 데이터베이스(RDBMS)</h3>
<ul>
<li>테이블과 로우, 칼럼으로 구성</li>
<li>정해진 틀 안에서 데이터를 저장하고 관리</li>
<li>데이터들 사이의 관계를 정의</li>
<li>데이터가 중복되거나 잘못된 데이터가 저장되는 것 방지 가능</li>
<li>여러 데이터 포인트 간의 관계를 쉽게 이해하고 유효한 정보 확인 가능</li>
</ul>
<h4 id="1-장점">1) 장점</h4>
<ul>
<li>직관적인 데이터 표현 방법을 제공하고, 관련 데이터 포인트에 쉽게 액세스 가능</li>
<li>인벤토리 추적, 트랜잭션 데이터 처리, 애플리케이션 로깅 등 대량의 정형 데이터를 관리하는 조직에서 많이 사용</li>
<li>유연성: 전체 데이터베이스 구조를 변경하거나 기존 애플리케이션에 영향을 주지 않고 필요할 때마다 건편하게 테이블 추가, 관계 추가, 업데이트 및 삭제, 데이터 변경 용이</li>
<li>ACID 규정 준수: ACID(원자성, 일관성, 격리, 내구성) 성능을 지원하며 오류, 실패 또는 기타 잠재적 오작동에 관계없이 데이터 유효성 보장</li>
<li>사용 편의성: 기술자가 아닌 사용자도 데이터 베이스와 상호작용하는 방법을 배울 수 있는 SQL을 사용하여 복잡한 쿼리를 쉽게 실행 가능</li>
<li>데이터베이스 정규화: 데이터 중보성을 줄이고 데이터 무결성을 향상시키는 정규화라고 하는 설계 기법 사용</li>
</ul>
<h4 id="2-단점">2) 단점</h4>
<ul>
<li>대용량 데이터 처리에 한계가 있음 </li>
<li>복잡한 데이터 구조 처리가 어려움 </li>
<li>테이블 간의 관계가 복잡해질수록 성능이 저하될 수 있음</li>
<li>테이터 베이스 모델링이 개발 전에 완료되어야해서 개발속도가 더뎌짐</li>
</ul>
<h3 id="2-비관계형-데이터베이스">2. 비관계형 데이터베이스</h3>
<ul>
<li>규칙 기반의 테이블 형식 방식으로 데이터를 구성XX</li>
<li>데이터를 연결되지 않은 개별 파일로 저장하며 문서 또는 리치 미디어 파일과 같은 복잡한 비정형 데이터 유형에서 사용 가능</li>
</ul>
<h4 id="1-장점-1">1) 장점</h4>
<ul>
<li>스키마가 없기 때문에 훨씬 유연하여 데이터 조정에 용이함</li>
<li>가변성 있는 데이터의 저장이 쉬움</li>
<li>데이터베이스 모델링이 완료되기 전에도 테스트 데이터 조회 가능 </li>
<li>응용프로그램이 요구하는 형식으로 저장되어 데이터를 읽는 속도가 빠름 </li>
<li>수직적/수평적 확장이 모두 가능</li>
</ul>
<h4 id="2-단점-1">2) 단점</h4>
<ul>
<li>유연성으로 인해 데이터 구조 결정이 어려울 수 있음 </li>
<li>NoSQL마다 쿼리 언어를 다르게 사용하는 경우가 많아 이식성이 낮음 </li>
<li>데이터베이스의 컬렉션이 다양한 경우 수정시 모든 컬렉션의 데이터를 수정해야함</li>
<li>문서 저장에 단위 요소 수준에서 세밀한 보안을 제공하지 않음</li>
</ul>
<h2 id="🔖-primary-key와-foreign-key에-대해-설명해-주세요">🔖 Primary Key와 Foreign Key에 대해 설명해 주세요.</h2>
<h3 id="1-primary-keypk-기본키">1. Primary Key(PK) 기본키</h3>
<ul>
<li>데이터베이스 테이블 내의 모든 레코드에서 고유한 아이디를 제공</li>
<li>테이블에서 각 로우를 식별할 수 있는 칼럼</li>
<li>모든 레코드가 서로 다른 값을 가지고 있어 각 레코드를 식별할 수 있다</li>
<li>Null 값이 존재할 수 없음</li>
<li>중복이 불가능</li>
<li>테이블에서는 하나의 기본키만 가질 수 있지만 경우에 따라 1개 이상의 기본키를 정의 가능<h3 id="2-foreign-keyfk-외래키">2. Foreign Key(FK) 외래키</h3>
</li>
<li>다른 테이블의 PK를 참조하는 컬럼 -&gt; 관계를 만드는 작업</li>
<li>데이터가 일관될 수 있도록 돕는 역할</li>
<li>외부 키는 한 테이블의 필드로, 다른 테이블의 기본을 나타냄</li>
<li>외래 키를 가지고 있는 테이블을 하위 케이블, 기본 키를 가지고 있는 테이블을 참조 테이블또는 상위 테이블이라고 함</li>
<li>각 외부키와 기본 키는 1:1 관계로 매칭 -&gt; 기본 키에 존재하지 않는 값이 외부키에 존재할 수 없음</li>
</ul>
<p>출처
<a href="https://cloud.google.com/learn/what-is-a-relational-database?hl=ko">https://cloud.google.com/learn/what-is-a-relational-database?hl=ko</a>
<a href="https://excited-hyun.tistory.com/112">https://excited-hyun.tistory.com/112</a>
<a href="https://velog.io/@hiy7030/DB-Primary-key%EC%99%80-foreign-key">https://velog.io/@hiy7030/DB-Primary-key%EC%99%80-foreign-key</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Weekly Paper]]></title>
            <link>https://velog.io/@nancy_yeonjeong/Weekly-Paper</link>
            <guid>https://velog.io/@nancy_yeonjeong/Weekly-Paper</guid>
            <pubDate>Mon, 24 Feb 2025 00:14:37 GMT</pubDate>
            <description><![CDATA[<h1 id="🔹프로세스와-스레드에-대해-설명해주세요">🔹프로세스와 스레드에 대해 설명해주세요</h1>
<h2 id="1-프로세스process란">1. 프로세스(Process)란?</h2>
<p>: 프로세스는 실행 중인 프로그램을 의미하며, 운영체제(OS)에서 자원을 할당받아 독립적으로 실행되는 단위</p>
<h3 id="✅-특징">✅ 특징</h3>
<pre><code>•    운영체제로부터 독립적인 메모리 공간(코드, 데이터, 힙, 스택 등)을 할당받음
•    하나의 프로세스는 여러 개의 스레드를 가질 수 있음
•    프로세스 간에는 메모리를 공유하지 않음 (통신 시 별도의 방법이 필요함: IPC(Inter-Process Communication))</code></pre><h3 id="✅-구성--요소">✅ 구성  요소</h3>
<pre><code>•    코드(Code) 영역: 실행할 명령어가 저장됨
•    데이터(Data) 영역: 전역 변수, 정적 변수 등이 저장됨
•    힙(Heap) 영역: 동적으로 할당된 메모리 공간
•    스택(Stack) 영역: 함수 호출 시 생성되는 지역 변수, 매개변수 저장</code></pre><h3 id="✅-예시">✅ 예시</h3>
<pre><code>•    Chrome 브라우저를 실행하면 여러 개의 프로세스가 생성됨 (탭마다 독립된 프로세스일 수도 있음)
•    VS Code를 실행하면 하나의 프로세스가 생성됨</code></pre><h2 id="2-스레드thread란">2. 스레드(Thread)란?</h2>
<p>: 스레드는 프로세스 내에서 실행되는 작업의 단위야. 하나의 프로세스 안에서 여러 개의 스레드가 실행 될 수 있음</p>
<h3 id="✅-특징-1">✅ 특징</h3>
<pre><code>•    같은 프로세스 내에서 메모리(코드, 데이터, 힙)를 공유함
•    독립적인 실행 흐름(Stack을 따로 가짐)
•    프로세스보다 가볍고 빠르게 생성 및 종료됨
•    동기화 문제(데이터 충돌)가 발생할 수 있음</code></pre><h3 id="✅-구성-요소">✅ 구성 요소</h3>
<pre><code>•    PC(Program Counter): 실행할 명령어 주소 저장
•    레지스터: 연산에 필요한 데이터 저장
•    스택(Stack): 함수 호출 시 지역 변수, 매개변수 저장 (스레드마다 독립적)</code></pre><h3 id="✅-예시-1">✅ 예시</h3>
<pre><code>•    웹 브라우저에서 여러 개의 탭이 동시에 실행 (각 탭이 다른 스레드일 수 있음)
•    게임에서 화면 렌더링, 입력 처리, 네트워크 통신이 동시에 수행</code></pre><h2 id="3-프로세스와-스레드의-차이점">3. 프로세스와 스레드의 차이점</h2>
<table>
<thead>
<tr>
<th align="center">구분</th>
<th align="center">프로세스</th>
<th align="center">스레드</th>
</tr>
</thead>
<tbody><tr>
<td align="center">메모리 공유</td>
<td align="center">X (각자 독립적인 메모리)</td>
<td align="center">O (코드, 데이터, 힙 공유)</td>
</tr>
<tr>
<td align="center">생성 속도</td>
<td align="center">느림 (운영체제의 자원 할당 필요)</td>
<td align="center">빠름 (프로세스 내에서 생성)</td>
</tr>
<tr>
<td align="center">통신 방식</td>
<td align="center">IPC 필요 (파이프, 메시지 큐, 소켓 등)</td>
<td align="center">공유 메모리를 사용하여 통신 가능</td>
</tr>
<tr>
<td align="center">독립성</td>
<td align="center">개별적으로 실행 가능</td>
<td align="center">하나의 스레드가 비정상 종료되면 전체 프로세스에 영향 가능</td>
</tr>
</tbody></table>
<h2 id="4-멀티-프로세스-vs-멀티-스레드">4. 멀티 프로세스 vs. 멀티 스레드</h2>
<h3 id="✅-멀티-프로세스multi-process">✅ 멀티 프로세스(Multi-Process)</h3>
<pre><code>•    여러 개의 프로세스를 실행하는 방식
•    장점: 독립적 실행 (한 프로세스가 죽어도 다른 프로세스에는 영향 없음)
•    단점: 프로세스 간 통신이 어렵고, 메모리 사용량이 많음</code></pre><h3 id="✅-멀티-스레드multi-thread">✅ 멀티 스레드(Multi-Thread)</h3>
<pre><code>•    하나의 프로세스 내에서 여러 개의 스레드를 실행하는 방식
•    장점: 메모리 공유로 인해 자원 사용 효율이 높음, 빠른 데이터 공유 가능
•    단점: 동기화 문제 발생 가능 (하나의 스레드가 문제를 일으키면 전체 프로세스에 영향을 줄 수 있음)</code></pre><h2 id="5-언제-멀티-프로세스-vs-멀티-스레드를-사용할까">5. 언제 멀티 프로세스 vs. 멀티 스레드를 사용할까?</h2>
<h3 id="✅-멀티-프로세스가-유리한-경우">✅ 멀티 프로세스가 유리한 경우</h3>
<pre><code>•    독립적인 작업을 수행할 때 (크롬 브라우저의 각 탭)
•    자원 공유가 필요 없는 경우
•    하나의 작업이 실패해도 다른 작업에 영향을 주지 않아야 할 때</code></pre><h3 id="✅-멀티-스레드가-유리한-경우">✅ 멀티 스레드가 유리한 경우</h3>
<pre><code>•    같은 데이터를 여러 개의 작업이 동시에 처리해야 할 때
•    프로세스 간 통신 비용을 줄이고 싶을 때
•    빠른 응답 속도가 필요한 경우 (게임, 실시간 채팅)</code></pre><h2 id="➡️-정리">➡️ 정리</h2>
<pre><code>•    프로세스: 실행 중인 프로그램, 독립적인 메모리 공간을 가짐
•    스레드: 프로세스 내에서 실행되는 작업 단위, 메모리를 공유함
•    멀티 프로세스: 독립적인 작업을 여러 개 실행할 때 사용
•    멀티 스레드: 같은 데이터를 동시에 처리할 때 사용</code></pre><h1 id="🔹프레임워크와-라이브러리의-차이에-대해-설명해주세요">🔹프레임워크와 라이브러리의 차이에 대해 설명해주세요.</h1>
<h2 id="1-라이브러리library란">1. 라이브러리(Library)란?</h2>
<h3 id="✅-정의">✅ 정의:</h3>
<pre><code>•    특정 기능을 수행하는 재사용 가능한 코드 묶음
•    개발자가 필요할 때 직접 호출해서 사용하는 방식</code></pre><h3 id="✅-특징-2">✅ 특징:</h3>
<pre><code>•    필요한 기능만 골라서 사용 가능
•    애플리케이션의 흐름을 개발자가 직접 제어
•    보통 함수, 클래스의 집합 형태</code></pre><h3 id="✅-예시-2">✅ 예시:</h3>
<pre><code>•    NumPy, Pandas (데이터 분석)
•    Lodash (JavaScript 유틸리티)
•    Matplotlib (파이썬 그래프 그리기)
•    jQuery (JavaScript DOM 조작)</code></pre><h2 id="2-프레임워크framework란">2. 프레임워크(Framework)란?</h2>
<h3 id="✅-정의-1">✅ 정의:</h3>
<pre><code>•    애플리케이션 개발을 위한 전체 구조를 제공하는 틀
•    개발자가 그 틀에 맞춰 코드를 작성해야 함</code></pre><h3 id="✅-특징-3">✅ 특징:</h3>
<pre><code>•    기본적인 코드 구조가 미리 제공됨
•    개발자는 프레임워크의 규칙을 따라야 함
•    프레임워크가 애플리케이션의 흐름을 제어 (“제어의 역전” 원칙)</code></pre><h3 id="✅-예시-3">✅ 예시:</h3>
<pre><code>•    Spring (Java 웹 개발)
•    Django, Flask (Python 웹 개발)
•    React, Angular, Vue.js (JavaScript 프론트엔드)
•    Express.js (Node.js 백엔드)</code></pre><h2 id="3-프레임워크와-라이브러리의-가장-큰-차이점-제어의-흐름">3. 프레임워크와 라이브러리의 가장 큰 차이점: “제어의 흐름”</h2>
<h3 id="✅-라이브러리-개발자가-직접-호출해서-사용함">✅ 라이브러리: 개발자가 직접 호출해서 사용함</h3>
<h3 id="✅-프레임워크-프레임워크가-개발자의-코드를-호출함-제어의-역전-inversion-of-control">✅ 프레임워크: 프레임워크가 개발자의 코드를 호출함 (제어의 역전, Inversion of Control)</h3>
<p>예를 들어:
    •    jQuery (라이브러리): 개발자가 $(&#39;#button&#39;).click() 같은 코드를 직접 호출해서 사용
    •    React (프레임워크): React가 useEffect() 같은 함수를 알아서 호출</p>
<h2 id="4-프레임워크-vs-라이브러리-비교-정리">4. 프레임워크 vs. 라이브러리 비교 정리</h2>
<table>
<thead>
<tr>
<th align="center">구분</th>
<th align="center">프레임워크</th>
<th align="center">라이브러리</th>
</tr>
</thead>
<tbody><tr>
<td align="center">제어 흐름</td>
<td align="center">프레임워크가 코드 실행 흐름을 제어</td>
<td align="center">개발자가 직접 코드 실행 흐름을 제어</td>
</tr>
<tr>
<td align="center">유연성</td>
<td align="center">정해진 방식대로 개발해야 함</td>
<td align="center">필요한 기능만 가져다 사용 가능</td>
</tr>
<tr>
<td align="center">사용 방식</td>
<td align="center">코드의 큰 구조를 제공하고, 그 안에서 개발</td>
<td align="center">특정 기능을 제공하며, 필요할 때 호출</td>
</tr>
<tr>
<td align="center">예시</td>
<td align="center">Spring, Django, React</td>
<td align="center">NumPy, jQuery, Lodash</td>
</tr>
</tbody></table>
<h2 id="5-언제-프레임워크-vs-라이브러리를-사용할까">5. 언제 프레임워크 vs. 라이브러리를 사용할까?</h2>
<p>✅ 프레임워크를 선택해야 할 때
    •    프로젝트의 구조를 잡아야 할 때
    •    확장성과 유지보수가 중요한 경우
    •    일관된 개발 방식이 필요한 경우</p>
<p>✅ 라이브러리를 선택해야 할 때
    •    특정 기능만 필요할 때
    •    프로젝트 구조에 큰 영향을 주지 않고 사용하고 싶을 때</p>
<h2 id="6-한-프로젝트에서-프레임워크와-라이브러리를-함께-사용-가능">6. 한 프로젝트에서 프레임워크와 라이브러리를 함께 사용 가능</h2>
<p>예를 들어:
    •    React (프레임워크) + Lodash (라이브러리)
    •    Django (프레임워크) + NumPy (라이브러리)</p>
<p>➡️ 프로젝트의 큰 틀을 잡아주고, 라이브러리는 필요한 기능을 추가할 때 사용</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[📚모던 자바스크립트 Deep Dive (1-5장)]]></title>
            <link>https://velog.io/@nancy_yeonjeong/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-1-5%EC%9E%A5</link>
            <guid>https://velog.io/@nancy_yeonjeong/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-1-5%EC%9E%A5</guid>
            <pubDate>Thu, 20 Feb 2025 09:50:18 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/260c6ed2-57f6-46a4-84c9-4ec111cf73cd/image.png" alt=""></p>
<p>부트캠프를 수강하는 같은 팀원들끼리 나중의 면접, 수업에 대한 깊은 이해를 위해서 <strong>⌜모던 자바스크립트 Deep Dive⌟</strong>    를 특정 장까지 읽고 설명하는 Study를 진행하기로 했습니다. </p>
<p>수업을 진행하는 7개월 남짓의 시간동안 1독 할 수 있기를...!
그리고 이 내용이 프로그래밍을 시작하는 저와같은 초보들에게도 도움이 될 수 있는 글이 될 수 있도록 잘 기록으로 남겨보겠습니다.</p>
<p>오늘 정리해 볼 장은 1-5장까지의 내용을 정리해보겠습니다. </p>
<blockquote>
<p>** 주요 내용**
1장 프로그래밍
2장 자바스크립트란?
3장 자바스크립트 개발 환경과 실행 방법
4장 변수
5장 표현식과 문</p>
</blockquote>
<h1 id="1-프로그래밍">1. 프로그래밍</h1>
<ul>
<li>컴퓨터에게 실행을 요구하는 일종의 커뮤니케이션</li>
<li>0과 1밖에 알지 못하는 기계가 실행할 수 있을 정도로 정확하고 상세하게 요구사항을 설명하는 작업 -&gt; <strong>&quot;코드&quot;</strong></li>
<li>Computational thinking(컴퓨팅 사고)</li>
</ul>
<h2 id="1-컴파일러compiler--인터프리터interpreter">1) 컴파일러(Compiler) / 인터프리터(Interpreter)</h2>
<p>기계어로 직접 명령을 전달하는 것에 대한 대안으로 사람이 이해할 수 있는 약속된 구문(문법)으로 구성된 &quot;프로그래밍 언어&quot;를 사용하여 프로그램을 작성한 후, 그적을 컴퓨터가 이해할 수 있는 기계로 변환하는 일종의 번역기</p>
<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/71855446-7f21-4639-a4a2-5ef2ac5a493c/image.png" alt=""></p>
<h2 id="2-구문과-의미">2) 구문과 의미</h2>
<pre><code>console.log(&quot;Hello World&quot;)</code></pre><ul>
<li>프로그래밍의 언어는 구문과 의미로 이뤄짐</li>
<li>프로그램을 할 때 올바른 문법을 준수하는 것도 맞지만 의미가 있어야 함</li>
<li>프로그래밍은 요구사항의 집합을 분석해서 적절한 자료구조와 함수의 집합으로 변환한 후, 그 흐름을 제어하는 것</li>
</ul>
<h1 id="2-자바스크립트란">2. 자바스크립트란</h1>
<h2 id="1-자바스크립트의-변천사">1) 자바스크립트의 변천사</h2>
<h3 id="1-시작">(1) 시작</h3>
<p> 약 90%의 시장 점유율로 웹 브라우저 시장을 지배하고 있던 넷스케이프 커뮤니케이션즈는 <strong>웹페이지의 보조적인 기능을 수행하기 위해 브라우저에서 동작하는 경향 프로그래밍 언어</strong>를 도입하기로 결정하고, 그래서 탄생한 것이 &quot;브렌던 아이크&quot;가 개발한 &quot;자바스크립트&quot;</p>
<h3 id="2-이름의-변천사">(2) 이름의 변천사</h3>
<p><strong>1996년 3월, &quot;모카 Mocha&quot;</strong>
넷스케이프 커뮤니케이션즈의 웹 브라우저인 넷 스케이프 내비케이터2에 탑재
<strong>1996년 9월, &quot;라이브스크립트&quot;</strong>
<strong>1996년 12월, &quot;자바스크립트&quot;</strong></p>
<h3 id="3-표준화">(3) 표준화</h3>
<p><strong>1996년 8월,</strong> 
마이크로소프트(MS)는 자바스크립트의 파생 버전인 &quot;JScript&quot;를 인터넷 익스플로어에 탑재.</p>
<blockquote>
<p>넷스케이프 커뮤니케이션즈와 MS는 자사 브라우저의 시장 점유율을 높이기 위해 자사 브라우저에서만 동작하는 기능을 경쟁적으로 추가하여 <strong>표준화보다는 적당한 호환성을 갖춤</strong></p>
</blockquote>
<p><strong>크로스 부라우징 이슈</strong>
브라우저에 따라 웹페이지가 정상적으로 동작하지 않음. </p>
<p><strong>1996년 11월</strong>
넷스케이프 커뮤니케이션즈는 컴퓨터 시스템의 표준을 관리하는 비영리 표준화 기구인 ECMA 인터네셔널에 자바스크립트 표준화 요청</p>
<p><strong>1997년 7월 ECMAScript</strong>
ECMA-62라 불리는 자바스크립트 포반 사양이 완성되었으나, 상표권 이슈로 ECMAScript로 명명.</p>
<p>*<em>1999년 ECMAScript3 *</em>
정규 표현식, try... catch</p>
<p><strong>2009년 ECMAScript 5(EC5)와 HTML5 공개</strong>
JSON, stirt mode, 접근자 프로퍼티, 프로퍼티 어트리뷰트 제어, 향상된 배열 조작 가능(forEach, map, filtter, reduce, some, every)</p>
<p>*<em>2015년 ECMAScript 6 *</em>
let/const 키워드, 화살표 함수, 클래스, 모듈 등과 같이 범용 프로그래미밍 언어로서 갖춰야 할 기능들을 대거 도입하는 큰 변화가 생기고, 이후 버전은 비교적 작은 기능을 추가하는 수준으로 매년 공개할 것 예고</p>
<h2 id="2-자바스크립트의-성장">2) 자바스크립트의 성장</h2>
<p> 초창기 자바스크립트는 웹페이지의 보조적인 기능을 수행하기 위해 한정적인 용도로 활용되었는데 이전에는 어떤 것이 있었는지 살펴보겠습니다.</p>
<h3 id="1-ajax">(1) Ajax</h3>
<p> 1999년, 자바스크립트를 이용해 서버와 브라우가 비동기 방식으로 데이터를 교환할 수 있는 통신 기능으로 등장합니다.</p>
<p> 이전의 웹페이지는 화면이 전활 될 때마다 서버로 새로운 HTML을 전송 받아 웹페이지 전체를 처음부터 다시 렌더링하는 방식으로 구동되어서 화면이 순간적으로 깜박이는 현상이 발생하고, 변경할 필요 없는 부분도 렌더링하여 불필요한 데이터 통신과 성능면에서도 불리했습니다. </p>
<p> Ajax는 서버로부터 필요한 데이터만 전송 받아 변경해야 하는 방식이 가능해졌습니다. 빠른 성능과 부드러운 화면 전환을 제공하였습니다. </p>
<p> 2005년, 구글이 발표한 구글 맵스는 Ajax 기반으로 동작하는 대표적인 웹 애플리션 프로그래밍 언어로 자바스크립트의 가능성을 확인하는 계기를 마련하였습니다. </p>
<h3 id="2-jquery">(2) jQuery</h3>
<p> 2006년, 다소 번거롭고 논란이 있던 DOM(Document Object Model)을 더욱 쉽게 제어하고,, 크로스 브라우징 이슈도 어느 정도 해결하였습니다. jQuery는 넓은 사용자 층을 순식간에 확보하고, 자바스크립트보다 직관적인 jQuery를 선호하는 개발자가 양성되기도 했습니다.</p>
<h3 id="3-v8-자바스크립트-엔진">(3) V8 자바스크립트 엔진</h3>
<p> 2008년, 구글 맵스를 통해서 자바스크립트의 가능성을 확인하고, 더욱 빠르게 동작하는 자바스크립트의 엔진의 필요성이 대두될 때 이러한 요구를 만족하는 빠른 성을 보여주는 엔진으로 V8 자바스크립트 엔진이 등장하게 되었습니다.
 데스크톱 애플리케이션과 유사한 사용자 경험(UX)을 제공할 수 있는 웹 애플리케이션 프로그래밍 언어로 정착하게 되었습니다. 
 이 당시, 웹 서버에서 수행되던 로직이 대거 클라이언트(브라우저)로 이동했고, 웹 애플리케이션 개발 영역에서 프론트엔드 영역이 주목받는 계기로 작용하게되었습니다.</p>
<h3 id="5-nodejs">(5) Node.js</h3>
<p> 2009년, 라이언 달이 발표한 Node.js는 구글 V8자바스크립트 엔진으로 빌드된 자바스크립트 런타임 환경 입니다. 
 브라우저의 자바스크립트 엔진에서만 동작하던 자바스크립트를 브라우저 이외의 환경에서 동작할 수 있도록 자바스크립트 엔진을 브라우저에서 독립시키는 환경입니다. 
 다양한 플랫폼에 적용할 수 있지만 서버 사이드 애플리케이션 개발에 주로 사용되며, 이에 필요한 모듈, 파일 시스템, HTTP등 내장 API를 제공합니다.
 프론트엔드와 백엔드 영역에서 자바스크립트를 사용할 수 있다는 동형성은 별도의 언어를 학습하기 위한 시간을 덜 수 있다는 장점이 있습니다. 
 Node.js는 비동기I/O를 지원하며 단일 스레드 이벤트 루프 기반으로 동작함으로써 요청 처리 성능이 좋습니다. 데이터를 실시간으로 처리하기 위해 I/O가 빈번하게 발생하는 Single Page Application 에 적합하고, CPU 사용률이 높은 애플리케이션에는 권장하지 않습니다. </p>
<h3 id="6-spa-프레임워크">(6) SPA 프레임워크</h3>
<p> 모던 웹 애플리케이션은 데스크톱 애플리케이션과 비교해도 손색이 없는 성능과 사용자 경험을 제공하는 것이 필수가 되었고, 더불어 개발 규모와 복잡도도 상승되었습니다. 
  이전의 개발 방식으로는 복잡해진 개발 과정을 수행하기 어려워졌고, 이러한 니즈에 따라서 많은 패턴과 라이브러리가 출현했습니다. 하지만, 변경에 유연하면서 확장하기 쉬운 애플리케이션 아키텍처의 구축을 어렵게 했고, 필연적으로 프레인워크가 등장하였습니다. 
 Component Based Delvelopment 방법론을 기반으로 하는 SPA의 대중화가 시작되며, Angular, React, Vue.js, Sevlte등 다양한 프레임워크와 라이브러리 또한 많은 사용층을 확보하고 있습니다.</p>
<h2 id="3-자바스크립트의-특징">3) 자바스크립트의 특징</h2>
<h3 id="1-웹-브라우저에서-동작하는-유일한-프로그래밍-언어">1) 웹 브라우저에서 동작하는 유일한 프로그래밍 언어</h3>
<h3 id="2-개발자가-별도의-컴파일-작업을-수행하지-않는-인터프리터-언어">2) 개발자가 별도의 컴파일 작업을 수행하지 않는 인터프리터 언어</h3>
<ul>
<li>모던 자바스크립트 엔진은 인터프리터와 컴파일러의 장접을 겹합해 비교적 처리 속도가 느린 인터프리터의 단점 보완</li>
<li>소스코드를 즉시 실행하고 컴파일러는 빠르게 동작하는 머신 코드를 생성하고 최적화<h3 id="3-멀티-패러다임-프로그래밍-언어">3) 멀티 패러다임 프로그래밍 언어</h3>
</li>
<li>명령형, 함수형, 프로토타입 기반 객체지향 프로그래밍 지원</li>
</ul>
<h1 id="3-변수">3. 변수</h1>
<h2 id="1-변수의-필요성">1) 변수의 필요성</h2>
<pre><code>10+20</code></pre><p>위와 같은 연산이 있다고 했을 때, 자바스크립트 엔진은 + 연산을 수행하기 위해 먼저, 연산자의 좌변과 우변의 숫자 값(피연산자)를 기억합니다. </p>
<p>이 때 컴퓨터는 CPU를 통해서 연산, 메모리를 통해 데이터를 기억합니다. </p>
<p>메모리는 데이터를 저장할 수 있는 메모리 셀의 집합체이고, 셀 하나의 크기는 1바이트(8비트)이며, 컴퓨터는 셀의 크기 즉 1 바이트 잔위로 데이터를 저장하거나 읽습니다. </p>
<p>각 셀은 공유의 메모리 주소를 갖는데, 이 주소는 메모리 공간의 위치를 나타내며 0부터 시작해서 메모리의 크기만큼 정수로 표현됩니다. </p>
<blockquote>
<p>ex. 4GB -&gt; 0 ~ 4,294,967,295(0x00000000 ~ 0xFFFFFFFF)</p>
</blockquote>
<p>컴퓨터는 모든 데이터(종류 상관 없이)를 2진수 처리하여, 2진수로 저장됩니다.</p>
<p>&quot;10 + 20&quot; 을 연연산해서 만들어낸 30을 재사용 할 수 없습니다. 계속 재사용을 하거 싶다면 결과 30이 저장된 메모리 주소에 집접 접근하는 방법 밖에 없습니다. 하지만 메모리 주소에 직접 접그하는 방법은 치명적인 오류를 발생시킬 가능성이 매우 높은 위험한 일입니다. 실수로 운영체제가 사용하고 있는 값을 변경하면 시스템을 멈추게 하는 치명적인 오류가 발생할 수 있기에 자바스크립트는 직접적인 메모리 제어를 하지 않습니다.</p>
<p>만약 개발자의 직접적인 메모리 제어를 허용해도 문제가 될 수 있는데, 메모리 주소는 코드가 실행될 때 메모리 상황에 따라 임의로 결정되어 동일한 컴퓨터, 동일한 메모리에서 실행을 해도 코드가 실행될 때마다 값이 저장될 메모리 주소도 변경됩니다. </p>
<p>위와 같은 상황에서 &quot;변수&quot;를 활용합니다.</p>
<h3 id="1-변수">(1) 변수</h3>
<p>: 하나릐 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름 -&gt; 값의 위치를 가리키는 상징적인 이름</p>
<pre><code>var result = 10+20;</code></pre><p>위와 같이 코드를 작성하게되면, 30이라는 값을 result에 저장하려 재사용 할 수 있습니다.</p>
<ul>
<li><strong>변수 이름</strong> : <code>result</code></li>
<li><strong>변수 값</strong> : <code>30</code></li>
<li><strong>할당(대입, 저장)</strong> : 변수에 값을 저장하는 것</li>
<li><strong>참조</strong>: 변수에 저장된 값을 읽어 들이는 것</li>
</ul>
<p>변수 할당을 통해서 <strong>메모리에 값을 저장</strong>하고, <strong>재사용이 가능하</strong>며, 사람이 이해할 수 있는 언어로 명명한 변수 이름을 통해 변수에 <strong>저장된 값의 의미를 알고 가독성</strong>을 높일 수 있습니다.</p>
<h3 id="2-식별자">(2) 식별자</h3>
<ul>
<li><p>어떤 값을 구별해서 식별할 수 있는 고유한 이름, 변수의 또 다른 이름</p>
</li>
<li><p>값이 아니라 메모리 주소를 기억하고 있어서 메모리 공간에 저장된 값에 접근 가능
<img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/d1df899a-dfb2-4279-9fa2-0dbd36fc85b8/image.png" alt=""></p>
</li>
<li><p>변수, 함수, 클래스 등의 이름은 모두 식별자 -&gt; 메모리 상에 존재하는 어떤 값을 식별할 수 있는 이름은 모두 식.별.자.</p>
</li>
</ul>
<h3 id="3-var을-활용한-변수-선언">(3) var을 활용한 변수 선언</h3>
<p>: 값을 저장하기 위한 메모리 공간을 확보하고 변수 이름과 확보된 메모리 공간의 주소를 연결해서 값을 저장할 수 있게 준비하는 것 -&gt; 변수 생성하는것 </p>
<p>1️⃣ <strong>var 키워드 선언</strong></p>
<pre><code>var score</code></pre><blockquote>
<p>키워드 : 자바스크립트 엔진은 키워드를 만나면 자신이 수행해야할 약속된 동작을 수행</p>
</blockquote>
<p>2️⃣ <strong>변수 이름을 등록하고 값을 저장할 메모리 공간 확보</strong></p>
<ul>
<li>아직 변수에 값을 할당하지 않아서 메모리 공간이 비어있을 것으로 생각할 수 있으나, 확보된 공간에는 <code>undefined</code> 이 암묵적으로 할당되어 초기화</li>
<li>초기화를 거치지 않을 경우 이전에 다른 애플리켕션이 사용했던 값이 남아있을 수 있는데 이러한 &quot;쓰레기 값&quot; 이 출력 </li>
<li>선언하지 않은 식별자에 접근하면 <code>ReferenceError(참조 에러)</code> 발생</li>
</ul>
<blockquote>
<p><code>undefined</code> : 원시 타입의 값
<strong>실행 컨텍스트</strong> : 변수 이름을 비롯한 모든 식별자가 등록되는 곳. 자바스크립트 엔진이 소스코드를 평가하고 실행하기 위해 필요한 활용을 제공하고 코드의 실행 결과를 실제로 관리하는 영역. key, velue의 형식인 객체로 등록되어 관리</p>
</blockquote>
<p>3️⃣ <strong>변수 실행과 호이스팅</strong></p>
<pre><code>console.log(score);
var score;</code></pre><p>위와 같이 변수를 참조하는 코드가 먼저오고, 변수가 나중에 선언되면 선언되지 않는 변수로 인해 &quot;참조에러&quot;가 발생하는 것이 아니라 <code>undefined</code> 가 출력되는 것을 확인 할 수 있습니다.</p>
<p>변수 선언이 소스코드가 한 줄씩 순차적으로 실행되는 런타임이 아니라 그 이전 단계에서 먼저 실행되기 때문입니다. 자바스크립트 엔진은 아래와 같이 실행됩니다. </p>
<ul>
<li>소스코드 평가 과정 진행</li>
<li>선언문을 찾아내어 선언문 먼저 실행</li>
<li>평가 과정이 끝나면 변수 선언을 포함한 모든 선언문 제외 소스코드 실행</li>
</ul>
<blockquote>
<p><strong>호이스팅 Variable Hoisting</strong> 
: 변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징</p>
</blockquote>
<h3 id="4-값의-할당">(4) 값의 할당</h3>
<pre><code>var score; // 변수 선언
score = 80; // 변수 할당

var score = 80; // 변수 선언 + 할당</code></pre><p>위의 코드는 동일하게 동작합니다. 
자바스크립트 엔진은 변수 선언과 값의 하당을 2개의 문으로 나누어 각각 실행하기 때문입니다. </p>
<p>이때 주의할 점은 변수 선언과 값의 할당의 실행 시점이 다르다는 것입니다. </p>
<ul>
<li><strong>변수 선언 :</strong> 런타임 이전 </li>
<li><strong>값의 할당 :</strong> 소스코드가 순차적으로 실행되는 런타임에 진행</li>
</ul>
<pre><code>console.log(score); // undefined

var score = 80;

console.log(score); // 80</code></pre><h3 id="5-값의-재할당">(5) 값의 재할당</h3>
<pre><code>var score = 80; 
score = 90;</code></pre><p>위와 같이 나와져있으면, 자바스크립트 엔진은 80 받은 값을 초기화하여 <code>undefined</code>로 한 다음, 90이라는 값을 받는다. </p>
<blockquote>
<p><strong>상수</strong> : 위와 같이 재할당을 받았을 때, 변수를 변경할 수 없는 값을 지칭 
<strong>const</strong> : 재할당이 금지되어 변수를 상수로 표현 가능 -&gt; 반드시 상수만을 위해 사용하지 않음</p>
</blockquote>
<p>90이라는 값을 받았을 때, 90 이전의 값인 <code>undefined</code>, <code>80</code>은 어떤 변수도 값으로 갖고 있지 않아 식별자와 연결이 안되어있습니다. 이러한 불필요한 값들은 가비지 콜렉에 의해 메모리에서 자동 해제 되지만, 언제 해제될지 예측할 수 없습니다.</p>
<blockquote>
<p><strong>가비지 콜렉터(garbage collector)</strong> : 애플리케이션이 할당한 메모리 공간을 주기적으로 검사하여 더이상 사용되지 않는 메모리를 해제하는 기능. 이를 통해 메모리 누수를 방지</p>
</blockquote>
<blockquote>
<p><strong>언매니지드 언어와 매니지드 언어</strong>
: 자바스크립트 같이 메모리의 할당과 해제를 담당하는 가비지 콜렉터가 있는 언어를 매니지드 언어라고 부릅니다. 개발자의 역량에 의존하는 부분이 적어져 어느 정도 일정한 생산성을 확보할 수 있다는 장점이 있지만 성능면에서 손실을 감수 할 수 밖에 없다는 단점이 있습니다.
 C언어의 경우, <code>malloc()</code>, <code>free()</code> 같은 메모리 제어 기능을 제공하는 언매니지드 언어의 경우 개발자의 역량에 따라서 최적의 성능을 확보할 수 있지만, 치명적인 오류를 생산할 가능성도 있습니다.</p>
</blockquote>
<h3 id="6-식별자-네이밍-규칙">(6) 식별자 네이밍 규칙</h3>
<ul>
<li>특수문자를 제외한 문자, 숫자, 언더스코어(_), 달러기호($)를 포함 가능 </li>
<li>시작은 문자, 언더스코어(_), 달러기호($)로 가능</li>
<li>예약어(프로그래밍 언어에서 사용되고 있거나 사용될 예정의 단어)는 식별자로 사용 불가능</li>
<li>쉼표를 통해서 하나의 문에서 여러 개 한번에 선언 가능(가독성때문에 잦은 사용 ❌</li>
<li>알파벳 이외의 언어 사용 ❌</li>
<li>대소문자 구분 (아래의 예시는 각가의 별개의 변수로 인식)<pre><code>var firstname
var fristName
var FRISTNAME</code></pre></li>
</ul>
<pre><code>[4가지 유형의 네이밍 컨벤션]
// 카멜 케이스 (일반적인 변수나 함수의 이름)
var firstName; 

// 스네이크케이스 
var first_name

// 파스칼 케이스 (생성자 함수, 클래스 이름)
var FirstName 

// 헝가리언 케이스 
var strFistName; // type + identifier
var $elem = document.getElementById(&#39;myId&#39;); // DOM 노드 
var observable$ = fromEvent(document, &#39;click&#39;); // RxJS 옵저버블</code></pre><h1 id="4-표현식과-문">4. 표현식과 문</h1>
<h2 id="1-값">1) 값</h2>
<p>: 식(표현식)이 평가되어 생성된 결과</p>
<pre><code>var sum = 10+20 // 값: 30</code></pre><p>변수는 하나의 값을 저장하기 위해 확보한 메모리 공간을 식별하게 붙인 이름이고, 변수에 할되는 것은 값입니다. 위의 코드의 sum 변수에 할당되는 것은 &quot;10+20&quot;이 아니라 &quot;30&quot;입니다.</p>
<h2 id="2-리터럴">2) 리터럴</h2>
<ul>
<li>값에서 살펴본 예제와 같이 식을 생성할 수 있지만, 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법</li>
<li>사람이 이해할 수 있는 문자(아라비아 숫자, 알파벳, 한글 등) 또는 미리 약속된 기호(&#39;&#39;, &quot;&quot;, [],{})등으로 표기한 코드 <pre><code>3 // 숫자 리터널 &quot;3&quot;</code></pre></li>
</ul>
<h2 id="3-표현식">3) 표현식</h2>
<p>: 값으로 평가될 수 있는 문. 
  표현식이 평가되면 새로운 값을 생성하거나 기존 값을 참조(리터널도 표현식)</p>
<pre><code>// 리터널 표현식
10 
&#39;Hello&#39;

// 식별자 표현식(선언이 이미 존재한다고 가정)
sum
person.name
arr[1]

// 연산자 표현식
10 + 20
sum  = 20
sum != 10

// 함수/메서드 호출 표현식(선언이 이미 존재한다고 가정)
square()
person.getName()</code></pre><blockquote>
<p>동치 : 표현식과 표현식이 평가된 값은 동등한 관계
<code>1+2 =3</code>에서 <code>1+2</code> 와 <code>3</code>은 동치</p>
</blockquote>
<h2 id="4-문">4) 문</h2>
<p>: 프로그램을 구성하는 기본 단위이자 최소 실행 단위 (토큰으로 구성)</p>
<blockquote>
<p>토큰(token): 문법적인 의미를 가지며, 문법적으로 더 이상 나눌 수 없는 코드의 기본 요소</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/5c886e58-70e4-4567-ae54-0882df64f69b/image.png" alt=""></p>
<h2 id="5-세미클론">5) 세미클론(;)</h2>
<ul>
<li>문의 종료를 의미</li>
<li>자바스크립트 엔진은 세미클론을 통해서 문이 종료한 위치를 파악하고 순자적으로 하나씩 문을 실행</li>
<li>0개 이상의 문을 중괄호{} 로 묶은 코드 블록 뒤에는 ❌ -&gt; 자체 종결성을 갖기에 안 붙임 </li>
<li>세미콜론은 옵션, ASI(세미콜론 자동 삽입 기능)이 암묵적으로 수행하기에 생략 가능<ul>
<li>아직  논쟁중이나, 세미콜론이 자동으로 삽입시, 간혹 개발자의 예상과 다르게 삽입되어 다르게 동작</li>
</ul>
</li>
</ul>
<h2 id="6-표현식-구분-방법">6) 표현식 구분 방법</h2>
<ul>
<li>표현식 : 값으로 평가 될 수 있는 문</li>
<li>표현식이 아닌 문 : 값으로 평가 될 수 없는 문</li>
<li><ul>
<li>값을 넣어보고 확인</li>
</ul>
</li>
</ul>
<pre><code>// 표현식이 아닌 문
var num = 100;

// 표현식인 문
100 + num // 110

//할당문 
num = 100; //100</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[📝 Git과 GitHub는 어떻게 협업이 이루어질까?]]></title>
            <link>https://velog.io/@nancy_yeonjeong/Git%EA%B3%BC-GitHub%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%98%91%EC%97%85%EC%9D%B4-%EC%9D%B4%EB%A3%A8%EC%96%B4%EC%A7%88%EA%B9%8C</link>
            <guid>https://velog.io/@nancy_yeonjeong/Git%EA%B3%BC-GitHub%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%98%91%EC%97%85%EC%9D%B4-%EC%9D%B4%EB%A3%A8%EC%96%B4%EC%A7%88%EA%B9%8C</guid>
            <pubDate>Sun, 16 Feb 2025 17:13:14 GMT</pubDate>
            <description><![CDATA[<p>이전에는 개발을 할 때, 개발자들이 공유하는 것을 &quot;오픈 소스&quot;라고 한다고 했습니다.
이 오픈소스들을 볼 수 있는 원격 저장소는 여러가지가 있겠지만 그래도 단연 유명한 원격 저장소 &quot;Git Hub&quot;라고 볼 수 있을 것입니다.</p>
<p>우리 개인이 가지고 있는 로컬 레포지토리에서 원격 서버 저장소로 보내기 위해서 터미널에서 사용하는 것이 &quot;Git&quot;입니다. Git을 통해서 소스 코드의 버전을 관리하고, 개발 과정에서의 변경 사항을 추적하고 여러 버전 간의 차이를 관리할 수 있습니다.</p>
<p>오늘은 이 Git을 통해서 Git Hub에 보내고 협업하는 과정을
&quot;toss 오픈 소스 프로젝트&quot;를 통해서 알아보도록 하겠습니다.</p>
<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/fc33a047-111f-47ca-9e4a-ea33ebb68c62/image.png" alt=""></p>
<h1 id="1-공동-프로젝트-진행시-process">1. 공동 프로젝트 진행시 Process</h1>
<h2 id="1-팀의-대표자가-공동-레포지토리-브랜치를-생성">1) 팀의 대표자가 공동 레포지토리, 브랜치를 생성</h2>
<h3 id="1-git-flow">(1) git flow</h3>
<p>: 개발과 릴리스의 과정을 명확하게 구분하고, 각 단계에서 필요한 작업을 체계적으로 진행할 수 있도록 관리</p>
<ul>
<li>주 브랜치 : master, develop, feature, release, hotfix</li>
<li>각 개발자는 자신의 작업을 &#39;feature&#39;브랜치에서 진행 -&gt; 작업이 완료되면 &#39;develop&#39; 브랜치로 풀 리퀘스트를 생성 -&gt; 이때 코드 리뷰 과정을 거쳐, 다른 팀원들의 피드백을 받고 개선 </li>
<li>&#39;release&#39; 브랜치를 통해 릴리스 준비 과정을 관리하고, master 브랜치에 merge. 버그가 생기면 &#39;hotfix&#39;를 통해서 관리.</li>
</ul>
<h3 id="2-공동-레포지토리를-fork">2) 공동 레포지토리를 Fork</h3>
<p>-&gt; 공동 레포지토리를 복사하여 새로운 독립된 곳에 만드는 작업</p>
<h3 id="3-로컬-저장소에서-git을-통해서-clone-작업을-진행">3) 로컬 저장소에서 git을 통해서 clone 작업을 진행</h3>
<p><strong>(1) git init</strong> : 로컬 저장소를 변경 사항을 git으로 관리한다는 명령어
<strong>(2) git clone (Fork한 git hub의 https 주소)</strong> : 원격 저장소에 있는 것을 로컬 저장소에 복제하는 작업</p>
<h3 id="4-작업-후-commit-을-남기고-원격-저장소에-pull-requestpr">4) 작업 후 commit 을 남기고 원격 저장소에 Pull Request(PR)</h3>
<p><strong>(1) git push -u origin (branch)</strong> : 원격 저장소로 내보내기
*<em>(2) Git Hub에서 PR 진행 *</em> : 원본 원격 저장소에 보내기</p>
<h3 id="5-작업-내용-확인-후-관리자가-merge-request-진행">5) 작업 내용 확인 후 관리자가 merge request 진행</h3>
<h1 id="2-toss-오픈-소스-프로젝트-_-slash">2. toss 오픈 소스 프로젝트 _ slash</h1>
<h2 id="1-branches">1) Branches</h2>
<p>: 각 기능이나 변경사항을 기준으로 나눠진 브랜치
<img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/c53dc25a-721f-42c8-bc93-caacf8cfb5c6/image.png" alt=""></p>
<h2 id="2-issues">2) Issues</h2>
<p>: 토스에서 현재 개발하려는 작업들
<img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/9ababee4-401c-4d6b-8c12-07c961006df1/image.png" alt=""></p>
<h2 id="3-pr">3) PR</h2>
<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/809124bb-a85c-4b9f-a37e-2688b7fa24ea/image.png" alt=""></p>
<h1 id="3-결론">3. 결론</h1>
<h2 id="1-효율적인-협업">1) 효율적인 협업</h2>
<ul>
<li>여러 개발자가 하나의 프로젝트를 공동으로 작업해야하는 특성상, 가장 효율적으로 작업할 수 있도록 도움</li>
<li>원격 저장소를 통해서 커밋을 공유함으로 서로의 작업 내용 확인 가능<h2 id="2-자동화-배포-가능">2) 자동화 배포 가능</h2>
<h2 id="3-다양한-협업-가능">3) 다양한 협업 가능</h2>
</li>
<li>다양한 오픈소스가 존재하는만큼, 누구나 해당 프로젝트에 기여할 수 있음</li>
<li>이슈 및 질문을 통해서 좀 더 확장된 개발할 수 있음<h2 id="4-버전-관리">4) 버전 관리</h2>
</li>
<li>현재 프로젝트가 진행된 버전 관리 용이</li>
<li>프로젝트의 버그 및 새로운 기능 요청 등을 관리함으로 해결해야하는 과제 등록 가능 </li>
</ul>
<blockquote>
<p>출처
<a href="https://github.com/toss/slash/issues">https://github.com/toss/slash/issues</a>
<a href="https://blog.naver.com/jryoun1/222051293142">https://blog.naver.com/jryoun1/222051293142</a>
<a href="https://y-oni.tistory.com/84">https://y-oni.tistory.com/84</a>
<a href="https://conanmoon.medium.com/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%9D%BC%EA%B8%B0-git-31219ccc9760">https://conanmoon.medium.com/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%9D%BC%EA%B8%B0-git-31219ccc9760</a>
<a href="https://f-lab.kr/insight/understanding-git-and-github-collaboration">https://f-lab.kr/insight/understanding-git-and-github-collaboration</a>
<a href="https://aandi.tistory.com/71">https://aandi.tistory.com/71</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[📝 개발자들은 왜 CLI를 사용할까?]]></title>
            <link>https://velog.io/@nancy_yeonjeong/%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%93%A4%EC%9D%80-%EC%99%9C-CUI%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%A0%EA%B9%8C</link>
            <guid>https://velog.io/@nancy_yeonjeong/%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%93%A4%EC%9D%80-%EC%99%9C-CUI%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%A0%EA%B9%8C</guid>
            <pubDate>Sat, 15 Feb 2025 10:21:23 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/40ac4fa6-cff6-49e1-8178-9aec348e785c/image.png" alt=""></p>
<p>개발자들의 이미지를 떠올리면 위의 사진과 같은 화면을 띄운채 영어로 뭔가 입력하고 있는 모습을 떠올릴 수 있습니다.</p>
<p>위의 사진과 같이 실제로 프로그래밍 코드를 짜는 경우도 있겠지만, 
일반적으로 우리가 접근하는 것과 달리 개발자들이 파일을 보는 것, 폴더를 생성하는 법이 다른데 오늘은 그것이 어떤 것인지 왜 그렇게 사용하는지를 알아보려고 합니다 !</p>
<h2 id="1-ui">1. UI</h2>
<p>: User Interface, 사용자가 보기에 가장 적은 동작을 통해서 접근할 수 있도록 만들어진 것을 의미합니다. </p>
<p>이 UI에는 크게 3가지 종류가 있습니다. </p>
<h3 id="1-clicommand-line-inerface">1) CLI(Command Line Inerface)</h3>
<p>: 명령어를 입력하여 작업을 수행하는 방식입니다. 사용자가 명령어를 입력하여 파일 관리, 네트워크 설정, 시스템 관리 등등 다양한 작업을 수행할 수 있습니다. 그래서 마우스보다 키보드의 활용을 더 요구합니다.
ex. 폴더 생성 시 &quot;mkdir (폴더명)&quot; 명령어 사용</p>
<h3 id="2-guigraphical-user-interface">2) GUI(Graphical User Interface)</h3>
<p>: 그래픽을 사용하여 컴퓨터 시스템과 상호 작용하는 시스템입니다. CLI가 명령을 통해서 모든 것을 관리했다면, GLI를 이용하면 마우스를 통해서 아이콘을 클릭하는 작업 등 CLI의 명령어가 클릭을 통해서 진행되는 것입니다.
ex. 폴더 생성 시 내가 원하는 위치에서 마우스 우클릭 -&gt; 폴더 생성</p>
<h3 id="3-nuinatural-user-interface">3) NUI(Natural User Interface)</h3>
<p>: 사용자의 동작을 통해서 시스템을 제어하는 방식입니다. 음성 인식, 제스처 인식, 시선 인식 등을 통해서 사용자가 요청하는 작업을 수행합니다.</p>
<p>⭐️ 이 중에서 개발할 때는 &quot;CLI&quot;를 사용합니다. </p>
<h2 id="2-cli를-사용하는-이유">2. CLI를 사용하는 이유</h2>
<h3 id="1-비용-절감">1) 비용 절감</h3>
<ul>
<li>GUI를 이용할 때 필요한 디자인적 요소에 대한 비용 절감<h3 id="2-문제-해결">2) 문제 해결</h3>
</li>
<li>명령줄 인터페이스를 사용하여 기본 시스템을 더 깊이 이해하는데 도움. 다양한 도구와 유틸리티를 더 능숙하게 사용하고 오류 관리를 개선</li>
<li>시스템 로그를 보고 포괄적인 오류 메시지와 디버깅 정보를 빠르게 찾을 수 있음. 텍스트 기반 명령도 쉽게 문서화 가능<h3 id="3-원격-액세스">3) 원격 액세스</h3>
</li>
<li>GUI에 비해 네트워크 리소스를 적게 소비하는 경우가 많음. 하드웨어 기능이 제한된 시스템이나 원격 서버 환경에서 적합 <h3 id="4-효율성">4) 효율성</h3>
</li>
<li>개별 파일을 찾아서 클릭하는 시간을 소비하는 대신, CLI에서 하나의 텍스트 명령으로 여러 파일에 대한 작업을 수행.</li>
<li>여러 명령을 수행하는 스크립트를 생성하여 단조롭거나 반복적인 작업 자동화 가능</li>
</ul>
<blockquote>
<p>출처
<a href="https://brunch.co.kr/@hnjnkm/7">https://brunch.co.kr/@hnjnkm/7</a>
<a href="https://namu.wiki/w/UI">https://namu.wiki/w/UI</a>
<a href="https://aws.amazon.com/ko/what-is/cli/">https://aws.amazon.com/ko/what-is/cli/</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Fetch API vs Axios]]></title>
            <link>https://velog.io/@nancy_yeonjeong/Fetch-API-vs-Axios</link>
            <guid>https://velog.io/@nancy_yeonjeong/Fetch-API-vs-Axios</guid>
            <pubDate>Sun, 09 Feb 2025 17:34:27 GMT</pubDate>
            <description><![CDATA[<p>앞서 살펴보았던 http에 대해서 알아볼 때 서버와 클라이언트 간의 데이터 통신을 할 때
클라이언트가 리퀘스트를 보내면 서버가 여러 단계를 거쳐서 서버가 응답을 해준다는 것을 살펴보았습니다. </p>
<p>API를 통해 리퀘스트를 보내는 경우, 여러분은 fetch와 axios 어떤 것을 사용하시나요? 
오늘은 둘을 비교 분석해보는 시간을 가져보겠습니다. </p>
<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/e6d8a781-9836-4a7c-aa6d-7fe565cc08d1/image.png" alt=""></p>
<h1 id="fetch-vs-axios">Fetch vs axios</h1>
<h2 id="fetch">Fetch</h2>
<ul>
<li>2015년부터 웹 브라우저에서 사용할 수 있는 내장 함수, 별도의 설치 없이 사용 가능</li>
<li>promise 기반으로 비동기 통신을 지원</li>
</ul>
<h2 id="axios">axios</h2>
<ul>
<li>2015년 첫 릴리즈된 HTTP 클라이언트 라이브러리</li>
<li>promise 기반의 비동기 통신을 지원</li>
<li>return을 promise 객체로 해주기 때문에 response 데이터를 다루기 쉬움</li>
<li>외장 모듈이라 npm을 통한 설치가 필요</li>
</ul>
<p>두 가지 HTTP Request에 대해서 간단하게 정리해보았는데, 
실제 Request 코드를 보면서 차이점에 대해서 알아보도록 하겠습니다.</p>
<h3 id="get">GET</h3>
<p>: API 서버의 등록된 데이터를 뽑아보자 !</p>
<h4 id="fetch-1">Fetch</h4>
<pre><code>async function getProduct(id) {
  try {
    const res = await fetch(
      `https://panda-market-api-crud.vercel.app/products/${id}`
    );

    if (!res.ok) {
      throw new Error(`HTTP error! ${res.status}`);
    }

    const data = await res.json();
    return data;
  } catch (error) {
    console.log(&quot;Error!&quot;);
  } finally {
    console.log(&quot;Finished!&quot;);
  }
}</code></pre><blockquote>
<p>1) fetch는 status가 404 에러나 다른 HTTP 에러 응답을 받았다고 해서 promise를 reject 하지 않기에 별도로 &quot;if(!res.ok)&quot;와 같이 에러를 처리할 수 있는 코드가 필요함
2) json 핸들링을 위해 데이터를 return시 별도 작업 필요
3) get method가 기본 지정이라 별도 옵션을 지정하지 않아도 됨</p>
</blockquote>
<h4 id="axios-1">axios</h4>
<pre><code>import axios from &quot;axios&quot;;

const instance = axios.create({
  baseURL: &quot;https://panda-market-api-crud.vercel.app/&quot;,
  timeout: 5000,
});

function getArticle(id) {
  return instance
    .get(`/articles/${id}`)
    .then((res) =&gt; {
      return res.data;
    })
    .catch((e) =&gt; {
      if (e.response) {
        console.log(e.response.status);
        console.log(e.response.data);
      } else {
        console.log(&quot;ID 조회에 실패하였습니다.&quot;);
      }
    });
}</code></pre><blockquote>
<p>1) axios는 외장 모듈이기에 별도 설치 및 import 명령어 필요
2) 반복되는 URL은 instance 생성을 통해서 코드 단축 가능
3) 네트워크 응답 시간 Request timeout 설정 가능
4) get method가 기본값이라 옵션 설정하지 않아도 되지만, .get() 와 같이 별도의 함수를 제공하기에 명시적으로 사용 
5) 가져온 데이터는 data 프로퍼티를 통해서 접근 가능(json 핸들링 내장)
6) 리퀘스트 실패 혹은 상태 코드가 실패(4XX, 5XX)를 나타내면 Promise가 reject 하기에 별도의 에러 코드 생략 가능</p>
</blockquote>
<h3 id="post">POST</h3>
<p>: 데이터 생성하기</p>
<h4 id="fetch-2">Fetch</h4>
<pre><code>async function createProduct(name, description, price, tags, images) {
  try {
    const res = await fetch(
      &quot;https://panda-market-api-crud.vercel.app/products&quot;,
      {
        method: &quot;POST&quot;,
        body: JSON.stringify({
          name: name,
          description: description,
          price: price,
          tags: tags || [],
          images: images || [],
        }),
        headers: {
          &quot;Content-Type&quot;: &quot;application/json&quot;,
        },
      }
    );

    if (!res.ok) {
      throw new Error(`HTTP error! ${res.status}`);
    }

    const data = await res.json();
    return data;
  } catch (error) {
    console.log(&quot;Error!&quot;);
  } finally {
    console.log(&quot;Finished!&quot;);
  }
}</code></pre><blockquote>
<p>1) body 옵션을 통해서 데이터 전송
    - 데이터 타입 : applcation/json
    - 문자 변환 : JSON.stringify</p>
</blockquote>
<h4 id="axios-2">axios</h4>
<pre><code>function creatArticle(title, content, image) {
  return instance
    .post(&quot;/articles&quot;, {
      title,
      content,
      image,
    })
    .then((res) =&gt; {
      return res.data;
    })
    .catch((e) =&gt; {
      if (e.response) {
        console.log(e.response.status);
        console.log(e.response.data);
      } else {
        console.log(&quot;작성에 실패하였습니다.&quot;);
      }
    });
}</code></pre><blockquote>
<p>1) 데이터 전송을 data 옵션 사용 
2) 자동으로 JSON 문자로 변환</p>
</blockquote>
<h3 id="patch">PATCH</h3>
<p>: 생성한 데이터 수정하기</p>
<h4 id="fetch-3">Fetch</h4>
<pre><code>async function patchProduct(id, patchData) {
  try {
    const res = await fetch(
      `https://panda-market-api-crud.vercel.app/products/${id}`,
      {
        method: &quot;PATCH&quot;,
        body: JSON.stringify(patchData),
        headers: {
          &quot;Content-Type&quot;: &quot;application/json&quot;,
        },
      }
    );

    if (!res.ok) {
      throw new Error(`HTTP error! ${res.status}`);
    }

    const data = await res.json();
    return data;
  } catch (error) {
    console.log(&quot;Error!&quot;);
  } finally {
    console.log(&quot;Finished!&quot;);
  }
}
</code></pre><h4 id="axios-3">axios</h4>
<pre><code>function patchArticle(id, data) {
  return instance
    .patch(`/articles/${id}`, data)
    .then((res) =&gt; {
      return res.data;
    })
    .catch((e) =&gt; {
      if (e.response) {
        console.log(e.response.status);
        console.log(e.response.data);
      } else {
        console.log(&quot;수정에 실패하였습니다.&quot;);
      }
    });
}</code></pre><h3 id="delete">DELETE</h3>
<p>: 생성 후 수정한 데이터 삭제하기!</p>
<h4 id="fetch-4">Fetch</h4>
<pre><code>async function deleteProduct(id) {
  try {
    const res = await fetch(
      `https://panda-market-api-crud.vercel.app/products/${id}`,
      {
        method: &quot;DELETE&quot;,
        headers: {
          &quot;Content-Type&quot;: &quot;application/json&quot;,
        },
      }
    );

    if (!res.ok) {
      throw new Error(`HTTP error! ${res.ststus}`);
    }

    const data = await res.json();
    return data;
  } catch (error) {
    console.log(&quot;Error!&quot;);
  } finally {
    console.log(&quot;Finished!&quot;);
  }
}</code></pre><blockquote>
<p>1) id로 삭제할 데이터를 찾으니, 추가 필요한 데이터가 없어서 body 생략</p>
</blockquote>
<h4 id="axios-4">axios</h4>
<pre><code>function deleteArticle(id) {
  return instance
    .delete(`/articles/${id}`)
    .then((res) =&gt; {
      return res.data;
    })
    .catch((e) =&gt; {
      if (e.response) {
        console.log(e.response.satus);
        console.log(e.response.data);
      } else {
        console.log(&quot;삭제에 실패하였습니다.&quot;);
      }
    });
}</code></pre><h2 id="결론">결론</h2>
<h3 id="axios-5">axios</h3>
<h4 id="장점">장점</h4>
<ol>
<li>instance 생성을 통해 반복되는 코드 선언 및 객체 설정 가능 </li>
<li>네트워크 응답 timeout을 통해서 응답 시간 지정 가능</li>
<li>data 프로퍼티를 통해서 별도의 json 문자 변환 요청 없이 변환 가능</li>
<li>.get()/.post()/.patch()/.delete() 함수 제공</li>
<li>네트워크 응답 실패 시(4xx, 5xx) reject (오류 코드 작성 필요 X)</li>
<li>다양한 프로퍼티 제공을 통해 간결한 코드 작성 가능</li>
</ol>
<h4 id="단점">단점</h4>
<ol>
<li>외장 모듈이라 npm을 통한 설치 필요</li>
</ol>
<h3 id="fetch-5">fetch</h3>
<h4 id="장점-1">장점</h4>
<ol>
<li>내장 모듈이라 바로 사용 가능 </li>
<li>내용을 다 표시할 수 있어서 정보가 잘 표기되어있음 </li>
</ol>
<h4 id="단점-1">단점</h4>
<ol>
<li>네트워크 응답 실패 시 reject가 안되어 오류 코드 넣어야 함</li>
<li>문자 변환을 위해 json 핸들링 코드 작성 필요</li>
<li>내용을 다 명시해야해서 코드가 길어짐</li>
</ol>
<p>출처
<a href="https://www.heropy.dev/p/QOWqjV">https://www.heropy.dev/p/QOWqjV</a>
<a href="https://tlsdnjs12.tistory.com/26">https://tlsdnjs12.tistory.com/26</a>
<a href="https://velog.io/@eunbinn/Axios-vs-Fetch">https://velog.io/@eunbinn/Axios-vs-Fetch</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Node.JS] Module]]></title>
            <link>https://velog.io/@nancy_yeonjeong/Node.JS-Module</link>
            <guid>https://velog.io/@nancy_yeonjeong/Node.JS-Module</guid>
            <pubDate>Sun, 09 Feb 2025 15:53:42 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/59939466-307c-4068-8232-3a86b8936092/image.svg" alt=""></p>
<p>하나의 웹페이지를 구성한다던가, 서버에 리퀘스트를 보는 작업 등을 할 때 코딩을 하다보면 무수히 많은 코드를 작성하게됩니다. 나중에 A라는 파일에 작성했던 기능이 유용해서 찾아보거나, 혹은 수정의 작업 등을 할 때 이 많은 코드를 일일이 찾아보기란 어려운 일입니다. </p>
<p>그래서 코딩을 할 때는 main 파일에 다 작성하는 것이 아니라,
기능에 따라 파일을 나눕니다. 로그인/회원가입/글쓰기/결제 등... 이런 과정을 통해서 얻을 수 있는 부분은 </p>
<blockquote>
<p>1) 코드의 가시화 
2) 효율적인 코드 관리 
3) 다른 프로그램에서 사용 가능 </p>
</blockquote>
<p>위의 세 가지의 이유를 꼽을 수 있습니다. </p>
<p>이렇게 기능에 따라 나누는 과정을 <strong>&quot;모듈화&quot;</strong>라고 합니다. </p>
<h1 id="모듈module">모듈(Module)</h1>
<p>: 어플리케이션을 구성하는 개별적 요소로서 재사용 가능한 코드 조각</p>
<ul>
<li>외장 모듈 (local module) : 개발자들이 만들어 놓은 모듈(라이브러리), npm을 통해서 사용 가능</li>
<li>내장 모듈 (core module) : node.js에서 기본적으로 제공하여 npm 없이도 사용 가능<h3 id="오픈-소스open-source">오픈 소스(Open Source)</h3>
: 개발자들의 커뮤니티는 서로가 만들어 놓은 모듈을 공유하는 문화가 있다. 누구나 코드를 확인하고 사용할 수 있는 문화를 지칭합니다. </li>
</ul>
<h3 id="서드파티-모듈thridparty-module">서드파티 모듈(ThridParty Module)</h3>
<p>: 다른 사람들 혹은 기업에서 만들어진 기능들이 많이 있습니다. 이를 제 3자가 만들었다고 하여 위와 같이 지칭합니다.</p>
<h2 id="설치하기">설치하기</h2>
<p>: 모듈을 사용하는데 있어서 모듈이 돌아가게 하기 위해서 초기 설정이 필요합니다. 어떤 작업을 하느냐에 따라 방법이 달라 아래 두 가지 방법을 작성해두었습니다.</p>
<h3 id="💡-모듈을-내가-만들-경우">💡 모듈을 내가 만들 경우</h3>
<p>: 파일의 확장자를 .mjs 로 설정</p>
<h3 id="💡-서드파티-모듈을-사용할-경우">💡 서드파티 모듈을 사용할 경우</h3>
<p>: npm install (모듈 이름) -&gt; package.json 파일에서 [&quot;type&quot;:&quot;module&quot;] 작성하기</p>
<p>위와 같이 내가 모듈을 만드느냐 사용하느냐에 따라 달라질 수 있어서 
아래부터는 서드파티 모듈을 사용하는 방법에 대해 기술하겠습니다.</p>
<h4 id="1-모듈-설치하기">1. 모듈 설치하기</h4>
<p>: 내가 진행하는 프로젝트 디렉토리(폴더)에 사용하고자 하는 모듈을 설치합니다. 저는 예시를 위해서 axios 모듈을 하나 설치하도록 하겠습니다.</p>
<blockquote>
<p>터미널 -&gt; 명령어: npm install axios</p>
</blockquote>
<h4 id="2-packagejson">2. package.json</h4>
<p>해당 명령어를 입력하면, package.json 파일이 생성되는데,
파일에 들어가서 아래와 같이 type을 작성해줍니다.</p>
<pre><code>{
  &quot;type&quot;: &quot;module&quot;,
  &quot;dependencies&quot;: {
    &quot;axios&quot;: &quot;^1.7.9&quot;
}
</code></pre><p>이렇게 하면 내가 설치한 모듈을 원활하게 돌릴 수 있는 초기 작업이 완료됩니다.</p>
<h2 id="사용법">사용법</h2>
<p>일반적으로 모든 모듈은 비공개 상태입니다. 다시 말해, 모듈은 캡슐화가 되어 다른 모듈에서 접근할 수 없고, 개별적 존재로서 애플리케이션과 분리되어 존재합니다.</p>
<p>비공개 상태이기에 이 비공개를 가져오려면 특별한 명령어가 필요합니다. 
그 명령에 대해서 알아보도록 하겠습니다.</p>
<h4 id="export">export</h4>
<p>: 공개가 필요한 부분에 한정하여 명시적으로 선택적 공개하는 것(지정된 모듈 내보내기)</p>
<h4 id="import">import</h4>
<p>: 지정된 모듈을 가져오기</p>
<p>위의 명령어를 통해서 내가 원하는 파일의 모듈을 가져오고, 내보낼 수 있습니다.</p>
<pre><code>// 내가 만든 모듈
export function add(a, b) {
  return a + b;
}

export function subtract(a, b) {
  return a - b;
}

export function multiply(a, b) {
  return a * b;
}

export function divide(a, b) {
  return a / b;
}</code></pre><p>위에 작성된 코드는 사칙연산 함수를 만들어서 해당 파일 외 다른 파일에서도 사용이 가능할 수 있도록 내보내도록(export) 작성해두었습니다.</p>
<pre><code>import { add, subtract, multiply, divide } from &quot;./export.mjs&quot;;

console.log(add(3, 5));
console.log(subtract(3, 6));
console.log(multiply(3, 5));
console.log(divide(6, 2));</code></pre><p>그러면 위와 같이 다른 파일에서 가져오고자 하는 모듈을 간단한 명령어를 통해서 경로를 입력하고 가져올 수 있습니다. </p>
<blockquote>
<p>** 명령어 작성법 **</p>
<ul>
<li>export + 모듈 <ul>
<li>const, function, class 다 가능하지만, 최상위 항목에서만 사용</li>
</ul>
</li>
<li>import {가져오려는 모듈 이름} from &quot;파일 경로&quot;</li>
</ul>
</blockquote>
<h2 id="추가-문법">추가 문법</h2>
<h3 id="1-named">1. named</h3>
<h4 id="1-as-import">1) as import</h4>
<p>import 할 때, as 키워드를 붙이면 내가 원하는 이름으로 호출을 할 수 있습니다. </p>
<pre><code>export const PI = 3.14;

export function add(a, b) {
  return a + b;
}
</code></pre><pre><code>import { PI, add as addNumbers } from &#39;./calculator.mjs&#39;;

console.log(addNumbers(1, 2));
</code></pre><p>export 된 이름 뒤에 as를 붙이고, 내가 부르고 싶은 이름을 적어서 명령어를 입력하면 이름을 바꿔서 import 할 수 있습니다.</p>
<h4 id="2-as-export">2) as export</h4>
<p>export 할 때부터 바꾸고 싶다면, export 할 때 동일하게 적어주면 됩니다. </p>
<pre><code>export add as addNumbers</code></pre><h3 id="2-한-번에-보내기">2. 한 번에 보내기</h3>
<h4 id="1-export-default">1) export default</h4>
<pre><code>const PI = 3.14;

function add(a, b) { 
  return a + b;
}

function subtract(a, b) { 
  return a - b;
}

function multiply(a, b) { 
  return a * b;
}

function divide(a, b) { 
  return a / b;
}

export { PI, add, subtract, multiply, divide };
</code></pre><p>위와 같이 내보내는 모듈이 많을 때는 위와 같이 중괄호{}로 묶는 방법도 있지만, 하나로 묶어서 보내는 방법도 있습니다.</p>
<pre><code>const calculator = { PI, add, subtract, multiply, divide }; // 객체로 만들기
export default calculator; // 객체 내보내기</code></pre><h4 id="2--import-namespace-import">2) &quot;*&quot; import (namespace import)</h4>
<p>&quot;*&quot; 문자를 사용하면, 지정 파일 내에서 export된 모든 모듈을 가져올 수 있습니다. </p>
<pre><code>const PI = 3.14;

function add(a, b) { 
  return a + b;
}

function subtract(a, b) { 
  return a - b;
}

function multiply(a, b) { 
  return a * b;
}

function divide(a, b) { 
  return a / b;
}

export { PI, add, subtract, multiply, divide };
</code></pre><pre><code>import * as calculator from &#39;./calculator.mjs&#39;;

console.log(calculator.PI);
console.log(calculator.add(1, 2));
console.log(calculator.subtract(1, 2));
console.log(calculator.multiply(1, 2));
console.log(calculator.divide(1, 2));
</code></pre><blockquote>
<p><em>* 사용법 **
import</em> as (통칭하여 부를 모듈명) from &#39;경로&#39;
-&gt; (통칭하여 부를 모듈명).(실제 모듈명)
** <em>해당 방법은 정말 필요할 때만 사용</em></p>
</blockquote>
<p>출처
⌜모던 자바스크립트 deep dive⌟ 저자 이웅모 p891
<a href="https://html-jc.tistory.com/503">https://html-jc.tistory.com/503</a>
<a href="https://medium.com/@su_bak/node-js-module-%EC%9D%B4%EB%9E%80-b1dd9224687f">https://medium.com/@su_bak/node-js-module-%EC%9D%B4%EB%9E%80-b1dd9224687f</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로미스(Promise)]]></title>
            <link>https://velog.io/@nancy_yeonjeong/%ED%94%84%EB%A1%9C%EB%AF%B8%EC%8A%A4Promise</link>
            <guid>https://velog.io/@nancy_yeonjeong/%ED%94%84%EB%A1%9C%EB%AF%B8%EC%8A%A4Promise</guid>
            <pubDate>Mon, 03 Feb 2025 00:12:38 GMT</pubDate>
            <description><![CDATA[<h2 id="프로미스promise">프로미스(Promise)</h2>
<p>: 자바스크립트에서 비동기 함수는 Promise 객체를 리턴</p>
<h2 id="promise의-3가지-상태">Promise의 3가지 상태</h2>
<p>1) Pending(대기) : 비동기 작업을 진행중
2) Fulfilled(이행) : 비동기 작업이 성공적으로 끝남
3) Rejected(거부) : 비동기 작업이 실패함</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[절차지향 vs 객체지향]]></title>
            <link>https://velog.io/@nancy_yeonjeong/%EC%A0%88%EC%B0%A8%EC%A7%80%ED%96%A5-vs-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5</link>
            <guid>https://velog.io/@nancy_yeonjeong/%EC%A0%88%EC%B0%A8%EC%A7%80%ED%96%A5-vs-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5</guid>
            <pubDate>Sun, 02 Feb 2025 23:58:02 GMT</pubDate>
            <description><![CDATA[<p>오늘은 절차지향 프로그래밍과 객체지향 프로그래밍에 대해서 알아보는 시간을 갖도록 하겠습니다. </p>
<h2 id="1-절차지향-프로그래밍pop이란">1. 절차지향 프로그래밍(POP)이란?</h2>
<p>: 기능을 작은 함수로 나누고, 각가의 함수가 데이터를 매개변수로 전달받아 작업을 수행. 코드의 재사용성과 모듈화에 유리하지만, 프로그램이 커지면 복잡해질 위험성 존재</p>
<h3 id="1-장점">1) 장점</h3>
<ul>
<li>컴퓨터의 처리구조와 유사해 실행속도가 빠름</li>
</ul>
<h3 id="2-단점">2) 단점</h3>
<ul>
<li>유지 보수가 어려움</li>
<li>실행 순서가 정해져있어서 코드의 순서가 바뀌면 동일한 결과를 보장하기 어려움</li>
<li>디버깅이 어려움</li>
</ul>
<h2 id="2-객체지향-프로그래밍이란oop">2. 객체지향 프로그래밍이란(OOP)?</h2>
<p>: 데이터를 속성과 메서드로 묶어 객체 단위로 프로그램을 구성하고, 객체 간의 메시지를 통해 작업을 수행하며 추상화 캡슐화 상속 다형성 등의 특징을 갖게 됨</p>
<h4 id="1-장점-1">1) 장점</h4>
<ul>
<li>코드의 재활용성이 높음</li>
<li>코딩이 절차지향보다 간편</li>
<li>디버깅이 쉬움</li>
</ul>
<h4 id="2-단점-1">2) 단점</h4>
<ul>
<li>처리 속도가 절차지향보다 느림 </li>
<li>설계에 많은 시간 소요가 필요</li>
</ul>
<h4 id="3-특성">3) 특성</h4>
<p>** (1) 캡슐화**
 : 객체를 캡슐로 싸서 그 내부를 보호하고 볼 수 없게 하는 것
** (2) 상속**
 : 상위 개체의 속성을 하위 개체에 물려줘 하위 개체가 상위 개체의 속성을 모두 가지는 관계</p>
<blockquote>
<p> ** 슈퍼클래스에 만들어진 필드와 메소드를 물려받음으로써 코드의 중복 작성을 방지하고, 코드를 재사용함으로써 코드 작성에 드는 시간과 비용을 줄여줌</p>
</blockquote>
<p>** (3) 다형성**
 : 같은 이름의 메소드가 클래스 혹은 객체 따라 다르게 구현되는 것</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[맥북(Mac) 터미널 Brew 설치]]></title>
            <link>https://velog.io/@nancy_yeonjeong/%EB%A7%A5%EB%B6%81Mac-%ED%84%B0%EB%AF%B8%EB%84%90-Brew-%EC%84%A4%EC%B9%98</link>
            <guid>https://velog.io/@nancy_yeonjeong/%EB%A7%A5%EB%B6%81Mac-%ED%84%B0%EB%AF%B8%EB%84%90-Brew-%EC%84%A4%EC%B9%98</guid>
            <pubDate>Fri, 31 Jan 2025 08:40:21 GMT</pubDate>
            <description><![CDATA[<p>Window에 Apt,
Mac에서는 Brew를 사용합니다.</p>
<p>이 프로그램은 소프트웨어를 쉽게 설치하고 관리할 수 있는 패키지 관리자이고, Brew를 이용하면 터미널에서 간단한 명령어로 다양한 개발 도구와 프로그램이 설치 가능합니다.</p>
<h2 id="1-brew-설치-여부-확인">1. brew 설치 여부 확인</h2>
<h3 id="1-mac---터미널-접속---brew-검색">1) Mac -&gt; 터미널 접속 -&gt; brew 검색</h3>
<pre><code>MacBookAir ~ % brew    
zsh: command not found: brew</code></pre><h3 id="2-위와-같이-뜨면-설치-진행">2) 위와 같이 뜨면 설치 진행</h3>
<h2 id="2-home-brew-접속">2. Home Brew 접속</h2>
<p>URL: <a href="https://brew.sh/">https://brew.sh/</a>
<img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/7655eacb-f971-4b54-8d59-9b23cdb23f9b/image.png" alt=""></p>
<h2 id="3-install-homebrew-복사">3. Install Homebrew 복사</h2>
<pre><code>/bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&quot;</code></pre><h2 id="4-터미널에-입력">4. 터미널에 입력</h2>
<h2 id="5-맥북-비밀번호-입력">5. 맥북 비밀번호 입력</h2>
<pre><code>MacBookAir ~ % /bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&quot;
==&gt; Checking for `sudo` access (which may request your password)...</code></pre><h2 id="6-enter-키-입력">6. Enter 키 입력</h2>
<pre><code>==&gt; This script will install:
/opt/homebrew/bin/brew
/opt/homebrew/share/doc/homebrew
/opt/homebrew/share/man/man1/brew.1
/opt/homebrew/share/zsh/site-functions/_brew
/opt/homebrew/etc/bash_completion.d/brew
/opt/homebrew
==&gt; The following new directories will be created:
/opt/homebrew/bin
/opt/homebrew/etc
/opt/homebrew/include
/opt/homebrew/lib
/opt/homebrew/sbin
/opt/homebrew/share
/opt/homebrew/var
/opt/homebrew/opt
/opt/homebrew/share/zsh
/opt/homebrew/share/zsh/site-functions
/opt/homebrew/var/homebrew
/opt/homebrew/var/homebrew/linked
/opt/homebrew/Cellar
/opt/homebrew/Caskroom
/opt/homebrew/Frameworks
==&gt; The Xcode Command Line Tools will be installed.

Press RETURN/ENTER to continue or any other key to abort:</code></pre><h2 id="7-에러메시지">7. 에러메시지</h2>
<p>: 아래와 같이 문구 속에 적혀있을 때 하단의 명령어 1,2를 순서대로 입력하시면 됩니다.</p>
<pre><code>Warning: /opt/homebrew/bin is not in your PATH.</code></pre><blockquote>
</blockquote>
<ul>
<li>명령어 1 : echo &#39;export PATH=/opt/homebrew/bin:$PATH&#39; &gt;&gt; ~/.zshrc</li>
<li>명령어 2 : source ~/.zshrc</li>
</ul>
<h2 id="8-설치-완료">8. 설치 완료</h2>
<p>: &quot;brew&quot; 검색 시 아래와 같은 문구가 나오면 나오면 완료 !</p>
<pre><code>  brew search TEXT|/REGEX/
  brew info [FORMULA|CASK...]
  brew install FORMULA|CASK...
  brew update
  brew upgrade [FORMULA|CASK...]
  brew uninstall FORMULA|CASK...
  brew list [FORMULA|CASK...]

Troubleshooting:
  brew config
  brew doctor
  brew install --verbose --debug FORMULA|CASK

Contributing:
  brew create URL [--no-fetch]
  brew edit [FORMULA|CASK...]

Further help:
  brew commands
  brew help [COMMAND]
  man brew
  https://docs.brew.sh
</code></pre><ol start="9">
<li>내가 설치한 brew 버전 조회 명령어<blockquote>
<p>brew --version</p>
</blockquote>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTTP란?]]></title>
            <link>https://velog.io/@nancy_yeonjeong/HTTP%EB%9E%80</link>
            <guid>https://velog.io/@nancy_yeonjeong/HTTP%EB%9E%80</guid>
            <pubDate>Thu, 30 Jan 2025 10:31:54 GMT</pubDate>
            <description><![CDATA[<p>이전 글에서 HTTP는 클라이언트와 서버 간의 데이터 통신을 정의하는 프로토콜로, 주로 http,https를 사용한다고 말씀드렸습니다. </p>
<p>웹에서 클라이언트와 서버 간의 요청 및 응답을 주고받는 프로토콜이라고 말씀드렸는데, 이번 글에서는 이 http가 어떤 것인지 좀 더 알아보는 글을 작성하려고 합니다.</p>
<p>HTTP는 클라이언트와 서버 간에 요청과 응답을 주고받는 방식으로 동작하는 애플리케이션 계층 프로토콜입니다.</p>
<h1 id="http-메시지">HTTP 메시지</h1>
<p>클라이언트와 서버들은 개별적인 메시지 교환에 의해 통신합니다.
보통 브라우저인 <strong>클라이언트에 의해 전송되는 메시지를 &quot;요청(requests)&quot;</strong>이라고 부르며, 그에 대해 <strong>서버에서 응답으로 전송되는 메시지 &quot;응답(responses)&quot;</strong>이라고 부릅니다.</p>
<h2 id="요청requests">요청(Requests)</h2>
<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/77020259-c684-49b4-99f3-edbc44f117ce/image.png" alt=""></p>
<h3 id="시작-줄">시작 줄</h3>
<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/09dc0051-daa2-49be-a6aa-d9563def29f2/image.png" alt=""></p>
<h4 id="1-http-method">(1) HTTP Method</h4>
<p>: 서버가 수행해야 할 동작을 나타냄</p>
<ul>
<li><p>GET: 리소스를 클라이언트로 가져다달라는 것을 의미</p>
</li>
<li><p>POST: 데이터가 서버로 들어가야 하는 것을 의미</p>
</li>
<li><p>PUT: 리소스를 대체(전체), 해당 리소스가 없으면 생성</p>
</li>
<li><p>PATCH: 리소스 부분 변경</p>
</li>
<li><p>DELETE: 리소스 삭제</p>
</li>
<li><p>PUT은 리소스를 완전히 교체하는 반면, PATCH는 리소스의 일부만 수정</p>
</li>
</ul>
<blockquote>
<p>GET /index.html HTTP/1.1
POST /submit-form HTTP/1.1
PUT /update-item/123 HTTP/1.1
PATCH /edit-profile HTTP/1.1
DELETE /delete-item/123 HTTP/1.1</p>
</blockquote>
<h4 id="2-요청-타겟">(2) 요청 타겟</h4>
<p>: 요청 타켓은 URL, 프로토콜, 포트, 도메인, 쿼리문자열 등을 포함 할 수 있다.</p>
<ul>
<li>가장 일반적인 형식이자, &quot;origin 형식&quot;으로 알려진 절대 경로입니다. 이 형식은 끝에 &quot;?&quot;와 쿼리 문자열이 따라옵니다.</li>
</ul>
<p><strong>GET / POST / HEAD / OPTIONS</strong> 메서드와 같이 사용됩니다. </p>
<blockquote>
<p>POST / HTTP/1.1
GET /background.png HTTP/1.0
HEAD /test.html?query=alibaba HTTP/1.1
OPTIONS /anypage.html HTTP/1.0</p>
</blockquote>
<h4 id="3-상태코드">(3) 상태코드</h4>
<p>: 요청에 대한 성공여부를 나타내는 코드</p>
<ul>
<li>1XX(조건부 응답): 요청을 받았으며 작업을 계속 진행</li>
<li>2XX(성공): 클라이언트가 요청한 동작을 수신하여 이해했고 승낙했으며 성공적으로 처리했음을 의미</li>
<li>3XX(리다이렉션 완료): 클라이언트는 요청을 마치기 위해 추가 동작을 취해야함을 의미</li>
<li>4XX(요청 오류): 클라이언트에 오류가 있음을 의미</li>
<li>5XX(서버 오류): 서버가 유효한 요청을 명백하게 수행하지 못함을 의미</li>
</ul>
<blockquote>
<p>2XX: 200OK
4XX: 404 Not Found
5XX: 500 Internal Server Error</p>
</blockquote>
<h3 id="headers">Headers</h3>
<p>: 대소문자 구분하지 않으며,&quot;Key:value&quot;형식으로 전송
<img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/6decc53d-5e3d-49dc-866d-2096ac246050/image.png" alt=""></p>
<ul>
<li>User-Agent(브라우저 정보), Accept(서버에서 원하는 형식 응답) 와 같은 request 헤더는 요청의 내용을 좀 더 구체화 시키고, 컨텍트를 제공하기도 하며, 조건에 따른 제약 사항을 주기도 하면서 요청 내용을 수정</li>
<li>메시지 데이터의 원래 형식과 적용된 인코딩을 설명하는 Content-Type 있음</li>
</ul>
<pre><code>&gt; Content-Type: application/json // 클라이언트나 서버가 보내는 데이터 형식</code></pre><h3 id="body본문">Body(본문)</h3>
<p>: 모든 요청에 본문이 들어가지는 않음(GET, HEAD, DELETE, OPTIONS 처럼 리소스를 가져오는 요청은 보통 본문이 필요 없음)</p>
<p> 일부 요청은 업데이트를 하기 위해 서버에 데이터를 전송하고, 보통(HTML 폼 데이터를 포함하는) POST 요청일 경우.</p>
<p> PUT 요청은 리소스를 교체하기 위해 본문을 포함</p>
<h2 id="응답response">응답(response)</h2>
<p><img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/2af069d3-76b2-4e0e-a3c0-32634ff4d052/image.png" alt=""></p>
<ul>
<li>서버의 메타 정보로, 요청을 처리한 서버가 어떻게 응답할지에 대한 내용을 담고 있음</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[About URL]]></title>
            <link>https://velog.io/@nancy_yeonjeong/About-URL</link>
            <guid>https://velog.io/@nancy_yeonjeong/About-URL</guid>
            <pubDate>Sat, 25 Jan 2025 09:08:15 GMT</pubDate>
            <description><![CDATA[<p>인터넷에서 재밌는 글을 보고 친구들에게 공유해주는 의미를 알 수 없는 긴 영어 링크가 무엇을 나타내는 것인지 궁금하신 적 없으신가요? </p>
<p>첫 게시글로 URL은 어떤 것인지, 
저 긴 영어 블라블라에 어떤 정보들이 포함되어있는지 오늘 한 번 알아보겠습니다.</p>
<h2 id="uniform-resource-locator">Uniform Resource Locator</h2>
<p>흔히 우리가 물건을 온라인으로 물건을 주문하면, 
이 물건을 어디에 가져다둬야하는지 &quot;주소&quot;를 입력해야 합니다. </p>
<p>물건의 위치를 정확하게 표기하기 위해서는 
&#39;서울시 종로구 사직로161 경복궁&#39; 와 같이 시/구/도로명/건물명 이 들어가고, 아파트나 빌라의 경우 동/호수와 또 물건을 어디에 위치시킬지(문 앞/ 소화전 안) 지정까지 하겠죠.</p>
<p>URL도 웹페이지의 주소의 역할을 합니다.
어떤 URL을 입력하느냐에 따라서 메인 페이지로 들어갈지, 가입하는 페이지로 들어갈지, 로그인 페이지로 들어갈지 달라지게 됩니다. </p>
<p>그래서 우리는 URL을 <strong>&quot;웹 페이지를 찾기 위한 주소&quot;</strong>라고 부릅니다. </p>
<blockquote>
<p>Ex. <a href="https://www.naver.com">https://www.naver.com</a> </p>
</blockquote>
<h2 id="url-구성요소">URL 구성요소</h2>
<p>URL에서 위치별로 어떤 의미를 가지고 있는지 알아보도록 하겠습니다.
<img src="https://velog.velcdn.com/images/nancy_yeonjeong/post/ebf073cf-5f3f-40b7-bd05-2c56470336ff/image.png" alt=""></p>
<h3 id="1-프로토콜protocol">1. 프로토콜(Protocol)</h3>
<p>리소스에 접근하는 방법을 정의하는 부분으로 주로 http, https 등을 사용합니다. 웹에서 데이터를 주고 받는 프로토콜이고, https는 http에서 보안이 강화된 형태입니다.
이 외에도 smtp/pop3,dns, tcp/ip와 같은 형태도 있습니다.</p>
<h3 id="2-도메인ip-주소">2. 도메인(IP 주소)</h3>
<p>IP주소는 169.143.5.432와 같이 표현되는데, 가시성이 떨어져서 이를 <a href="http://www.naver.com%EA%B3%BC">www.naver.com과</a> 같은 문자로 표기합니다. 이 문자로 표기되는 것을 도메인이라고 합니다.
서버에서는 도메인(en.dict.naver.com)이 검색되면 이에 해당하는 IP(210.89.168.68)로 DNS 서버가 변환하여 주소를 전달합니다.</p>
<h3 id="3-경로path">3. 경로(Path)</h3>
<p>서버 내에서의 자원의 위치를 지정하는 역할을 하고 잇습니다. 위와 같이 도메인의 바로 다음에 위치하고 있습니다. 여기서는 #/search 가 이에 해당된다.</p>
<h3 id="4-프래그먼트fragment">4. 프래그먼트(Fragment)</h3>
<p>URL 안에서 특정 위치를 지정하는 용도로 사용합니다. 
&quot;#&quot;으로 시작하며 특정 이름을 참조합니다.</p>
<h3 id="5-퀴리-문자열query-string">5. 퀴리 문자열(Query String)</h3>
<p>URL에서 추가 정보를 전달하기 위해 사용되는 부분입니다. &quot;?&quot; 뒤에 있는 값을 의미하고 여기서는 &quot;query=apple&quot;은 검색 쿼리를 의미합니다. 여기서 사용자가 검색한 값이 &quot;apple&quot;이라는 값을 가진다는 의미입니다.</p>
<p>여러개의 파라미터는 &amp; 기호로 구분이 됩니다. <strong>key=value 형태를 띄는 특징</strong>이 있습니다. </p>
<blockquote>
<p>Ex. ?q=hello&amp;hi=ko 검색어와 언어설정
    ?page=2&amp;sort=asc 페이지 번호와 정렬 방식 설정</p>
</blockquote>
<h2 id="웹-브라우저가-작동하는-방식">웹 브라우저가 작동하는 방식</h2>
<h3 id="1-dns-조회">1. DNS 조회</h3>
<p>웹 브라우저가 DNS 서버를 통해 도메인(호스트명)을 IP 주소로 변환
<a href="http://www.naver.com">www.naver.com</a> -&gt; 210.89.168.68</p>
<h3 id="2-http-요청-메시지-생성">2. HTTP 요청 메시지 생성</h3>
<p>변환된 IP 주소를 바탕으로 요청 메시지를 생성하는데, 이때 요청 헤더와 메소드(GET, POST등)를 포함</p>
<blockquote>
<ul>
<li>메소드 : GET, POST, PUT 등 어떤 작업을 요청할지 명시</li>
</ul>
</blockquote>
<ul>
<li>헤더 : 요청에 대한 추가적인 정보
   Ex. User-Agent(브라우저 정보), Accept-Language(언어 정보)</li>
<li>URL 경로 : 요청할 리소스</li>
</ul>
<h3 id="3-소켓을-통한-연결">3. 소켓을 통한 연결</h3>
<p>웹 브라우저는 소켓 라이브러리를 이용해 TCP/IP 연결을 요청
이 과정에서 3-Way Handshake(3단계 핸드쉐이크)를 통해 서버와 연결</p>
<blockquote>
<ul>
<li><strong>TCP(Teansmission Control Protocol)</strong>: 전송 제어 프로토콜, 데이터를 전송하는 방식에 대한 규칙을 정함</li>
</ul>
</blockquote>
<ul>
<li><strong>3-Way Handshake</strong>: TCP 연결을 할 때 필요한 과정, 두 컴퓨터가 소통할 준비가 되었는지 확인하는 과정</li>
</ul>
<blockquote>
<p>1) SYN(클라이언트 → 서버): 클라이언트는 연결을 시작하는 패킷 전송
2) SYN-ACK(서버 → 클라이언트): 서버는 연결 요청을 수락했다는 응답 전송
3) ACK(클라이언트 → 서버): 클라이언트가 연결 준비 완료를 서버에 알림</p>
</blockquote>
<h3 id="4-서버로-패킷-전송">4. 서버로 패킷 전송</h3>
<p>연결에 성공하면 http 메시지를 포함한 TCP/IP 패킷을 생성하여 전송
이때, HTTP 메시지(Ex. GET /index.html HTTP/1.1)가 포함되어 서버가 어떤 리소스를 요청하는지 알림</p>
<blockquote>
<ul>
<li>패킷: 데이터를 작은 조각으로 나눔. 네트워크에서 데이터를 전송할 때 효율적이고 안정적인 전송과 네트워크 속도 향상을 위해서 사용</li>
</ul>
</blockquote>
<h3 id="5-서버의-응답-처리">5. 서버의 응답 처리</h3>
<p>서버는 패킷을 받고 나서 http 메시지를 해석
이 후 HTML 데이터를 포함한 응답 메시지를 만들어 클라이언트 반환 </p>
<blockquote>
<ul>
<li>상태코드: 200 Ok 는 성공적으로 요청을 처리했음을 의미하고, 400 Not Found는 요청한 리소스를 찾을 수 없다는 뜻</li>
</ul>
</blockquote>
<ul>
<li>헤더: 응답에 대한 추가적인 정보(Content-Type, Date 등)</li>
<li>본문(Body): 실제 요청한 콘텐츠(HTML 파일, 이미지 등)</li>
</ul>
<h3 id="6-응답-메시지-렌더링">6. 응답 메시지 렌더링</h3>
<p>클라이언트는 응답 메시지를 받아 화면에 콘텐츠를 렌더링해서 사용자가 볼 수 있도록 표시</p>
]]></description>
        </item>
    </channel>
</rss>