<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>하영차의 공부기록장</title>
        <link>https://velog.io/</link>
        <description>Data Scientist, interested in CV, NLP</description>
        <lastBuildDate>Sun, 21 Sep 2025 08:18:42 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>하영차의 공부기록장</title>
            <url>https://velog.velcdn.com/images/emma_lee/profile/99cfba60-00e1-4773-99b7-c94fd0401b80/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. 하영차의 공부기록장. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/emma_lee" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[ML] 활성화 함수 (Activation Function)]]></title>
            <link>https://velog.io/@emma_lee/ML-%ED%99%9C%EC%84%B1%ED%99%94-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@emma_lee/ML-%ED%99%9C%EC%84%B1%ED%99%94-%ED%95%A8%EC%88%98</guid>
            <pubDate>Sun, 21 Sep 2025 08:18:42 GMT</pubDate>
            <description><![CDATA[<h1 id="딥러닝에서-자주-쓰이는-활성화-함수">딥러닝에서 자주 쓰이는 활성화 함수</h1>
<p>신경망에서 <strong>활성화 함수(activation function)</strong>는 매우 중요한 역할을 한다.<br>신경망은 기본적으로 입력 $$x$$ 에 가중치 $$W$$ 와 편향 $$b$$ 를 곱해 선형 변환을 수행한다.  </p>
<p>$$
z = W x + b
$$</p>
<p>만약 이 값 그대로를 다음 층으로 넘긴다면, 아무리 층을 쌓아도 결국 <strong>하나의 선형 함수</strong>와 다르지 않다.<br>선형 함수는 직선(또는 초평면)으로만 데이터를 나눌 수 있기 때문에 XOR 같은 비선형 패턴을 표현할 수 없다.  </p>
<p>따라서 <strong>비선형성을 도입하는 장치</strong>, 즉 활성화 함수가 반드시 필요하다.  </p>
<hr>
<h2 id="1-시그모이드sigmoid">1. 시그모이드(Sigmoid)</h2>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/bb436215-5cd7-4e06-bb56-9d170b567c95/image.png" alt=""></p>
<p>시그모이드는 어떤 입력 값이 들어와도 출력을 0과 1 사이로 눌러주는 S자 곡선 함수다.<br>$$
\sigma(x) = \frac{1}{1+e^{-x}}
$$<br>출력이 확률처럼 해석될 수 있기 때문에 이진 분류 문제의 출력층에서 직관적으로 사용된다. 하지만 입력 값이 너무 크거나 작을 때는 기울기가 거의 0에 가까워져 역전파가 제대로 전달되지 않는다. 이를 기울기 소실(Vanishing Gradient)이라고 부른다. 또한 출력이 0을 중심으로 대칭적이지 않아서 학습이 더딜 수 있다는 한계가 있다.  </p>
<hr>
<h2 id="2-하이퍼볼릭-탄젠트tanh">2. 하이퍼볼릭 탄젠트(Tanh)</h2>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/05b0958e-1528-4596-bb59-c53325bfafe3/image.png" alt=""></p>
<p>Tanh 함수는 시그모이드와 형태가 비슷하지만 출력 범위가 -1에서 1 사이로 확장된다.<br>$$
\tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}}
$$<br>출력이 0을 중심으로 대칭이기 때문에 시그모이드보다 학습이 좀 더 안정적이다. 그러나 값이 커지거나 작아질수록 기울기가 0으로 수렴하는 문제는 여전히 남아 있다. 따라서 기울기 소실 문제 때문에 심층 신경망에서는 잘 쓰이지 않는다.</p>
<hr>
<h2 id="3-렐루relu-rectified-linear-unit">3. 렐루(ReLU, Rectified Linear Unit)</h2>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/ce76955f-0acb-432b-a5d9-c5c8088195e3/image.png" alt="">
ReLU는 지금 가장 널리 사용되는 활성화 함수다.<br>$$
f(x) = \max(0, x)
$$<br>0보다 크면 입력을 그대로 통과시키고, 0 이하에서는 0을 출력한다. 계산이 단순하고 양수 구간에서 기울기가 항상 1이라 기울기 소실 문제를 크게 완화한다. 하지만 입력이 0 이하인 경우에는 기울기가 아예 0이 되어 뉴런이 학습에서 배제될 수 있다. 이 현상을 dying ReLU 문제라고 부르며, 이 문제는 뒤에 나오는 Leaky ReLU 등으로 완화할 수 있다.    </p>
<hr>
<h2 id="4-리키-렐루leaky-relu">4. 리키 렐루(Leaky ReLU)</h2>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/8393b487-3a77-4374-9f25-86f59d558b85/image.png" alt="">
Leaky ReLU는 ReLU의 변형으로, 음수 구간에서도 아주 작은 기울기를 남겨둔다.<br>$$
f(x) =
\begin{cases}
x &amp; x &gt; 0 \
\alpha x &amp; x \leq 0
\end{cases}
$$<br>이 방식은 dying ReLU 문제를 완화한다. 음수 입력에서도 조금씩 가중치가 업데이트되기 때문에 뉴런이 죽어버리는 상황을 줄여준다. 다만 이때 사용하는 (\alpha) 값은 임의적으로 정해야 하고, 최적의 값을 찾기 위해 실험이 필요하다.  </p>
<hr>
<h2 id="5-소프트맥스softmax">5. 소프트맥스(Softmax)</h2>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/9c1c0a68-ff2d-4e53-b542-4610d2f55659/image.png" alt="">
Softmax는 주로 다중 분류 문제에서 출력층에 사용된다.<br>$$
\sigma(z_i) = \frac{e^{z_i}}{\sum_j e^{z_j}}
$$<br>여러 개의 입력을 받아 각 클래스에 대해 0과 1 사이의 확률을 출력하며, 전체 합이 1이 된다. 그래서 각 출력 노드는 해당 클래스일 확률을 의미한다. 다만 값이 큰 쪽에 확률이 몰리는 경향이 있어서, log-sum-exp trick 같은 수치적 안정화 기법을 적용하는 경우가 많다.    </p>
<hr>
<h1 id="활성화-함수는-언제-쓸까">활성화 함수는 언제 쓸까?</h1>
<h2 id="은닉층-hidden-layer">은닉층 (Hidden Layer)</h2>
<p>선형 변환만 있으면 아무리 층을 쌓아도 전체는 하나의 선형 함수와 같다.<br>따라서 은닉층에는 반드시 활성화 함수를 넣어 <strong>비선형성</strong>을 주어야 한다.<br>여기서 선택한 함수가 학습 효율, 속도, 성능에 큰 영향을 준다.  </p>
<h2 id="출력층-output-layer">출력층 (Output Layer)</h2>
<p>출력층에서는 문제의 성격에 맞는 활성화 함수를 선택한다.<br>모든 문제에서 쓰이는 건 아니고, <strong>목표 값의 의미</strong>에 따라 달라진다.  </p>
<ul>
<li>확률이 필요하다면 <strong>Sigmoid</strong>나 <strong>Softmax</strong>  </li>
<li>연속적인 수치가 필요하다면 별도 활성화 없이 <strong>선형 출력</strong>  </li>
</ul>
<hr>
<h1 id="어떤-활성화-함수를-써야-할까">어떤 활성화 함수를 써야 할까?</h1>
<h2 id="1-은닉층">1. 은닉층</h2>
<ul>
<li><strong>ReLU</strong>: 가장 기본이자 표준. 단순하고 빠르며 깊은 네트워크 학습에 강하다.  </li>
<li><strong>Leaky ReLU / PReLU</strong>: ReLU가 죽는 문제(dying ReLU)를 완화해야 할 때 고려.  </li>
<li><strong>ELU / SELU</strong>: 평균을 0 근처로 유지하고 싶을 때 사용.  </li>
<li><strong>GELU / Swish</strong>: 최근 트랜스포머 등에서 자주 쓰이는 부드러운 ReLU 대체제.  </li>
</ul>
<p>기본적으로는 <strong>ReLU부터 시작</strong>하고, 문제가 생기면 변형 함수들을 고려한다.  </p>
<h2 id="2-출력층">2. 출력층</h2>
<ul>
<li><p><strong>이진 분류 → Sigmoid</strong><br>출력이 0~1로 제한되어 “양성 클래스일 확률”처럼 해석할 수 있다.<br>손실 함수로 <strong>Binary Cross-Entropy</strong>를 함께 사용한다.  </p>
</li>
<li><p><strong>다중 분류 → Softmax</strong><br>각 클래스에 대해 확률 분포를 만들어준다.<br>손실 함수는 <strong>Cross-Entropy</strong>를 사용한다.  </p>
</li>
<li><p><strong>회귀 문제 → 없음 (Linear)</strong><br>예측해야 할 값이 확률이 아니라 실제 수치이기 때문이다.<br>출력층은 그대로 실수 값을 출력하며, 보통 $$f(x) = x$$ 형태로 표현된다.  </p>
</li>
</ul>
<hr>
<h1 id="즉">즉</h1>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/1aa94013-4324-4e71-9098-230b19973f95/image.png" alt=""></p>
<ul>
<li>은닉층에는 <strong>비선형성 확보</strong>를 위해 반드시 활성화 함수를 넣어야 한다.  </li>
<li>은닉층 기본값은 <strong>ReLU</strong>, 필요시 변형(ReLU 계열, ELU, GELU 등)을 쓴다.  </li>
<li>출력층은 <strong>문제의 성격</strong>에 따라 다르다.  <ul>
<li>이진 분류 → Sigmoid  </li>
<li>다중 분류 → Softmax  </li>
<li>회귀 → 없음 </li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ML] 역전파 (Backpropagation)]]></title>
            <link>https://velog.io/@emma_lee/ML-%EC%97%AD%EC%A0%84%ED%8C%8C-Backpropagation</link>
            <guid>https://velog.io/@emma_lee/ML-%EC%97%AD%EC%A0%84%ED%8C%8C-Backpropagation</guid>
            <pubDate>Fri, 19 Sep 2025 07:21:54 GMT</pubDate>
            <description><![CDATA[<p>딥러닝이나 인공신경망을 공부하다 보면 반드시 만나게 되는 개념이 <strong>역전파(Backpropagation)</strong> 이다.<br>이 알고리즘은 신경망이 스스로 학습할 수 있게 해주는 핵심 원리다.  </p>
<hr>
<h2 id="1-신경망의-학습">1. 신경망의 학습</h2>
<p>신경망은 기본적으로 <strong>입력 → 여러 개의 은닉층 → 출력</strong> 구조를 가지고 있다.<br>여기서 중요한 건 신경망이 스스로 정답을 맞히기 위해 <strong>가중치(W)와 편향(b)</strong> 을 조금씩 조정한다는 점이다.</p>
<p>즉, 학습이란 결국</p>
<ul>
<li>현재 예측이 정답과 얼마나 다른지 계산하고  </li>
<li>그 차이를 줄이는 방향으로 W, b를 수정하는 과정  </li>
</ul>
<p>이라고 할 수 있다.</p>
<hr>
<h2 id="2-순전파-forward-propagation">2. 순전파 (Forward Propagation)</h2>
<p>먼저 데이터를 넣어 결과(예측값)를 계산한다. 이를 <strong>순전파</strong>라고 한다.  </p>
<p>예를 들어, 입력 데이터 <code>x</code>가 신경망을 통과하면서 다음과 같은 계산이 일어난다.</p>
<ul>
<li><code>z1 = W1*x + b1</code>  </li>
<li><code>h1 = f(z1)</code>  </li>
<li><code>z2 = W2*h1 + b2</code>  </li>
<li><code>h2 = f(z2)</code>  </li>
<li>…  </li>
<li><code>y_hat = f(WL*h(L-1) + bL)</code></li>
</ul>
<p>여기서  </p>
<ul>
<li><code>W, b</code>: 우리가 학습시켜야 할 파라미터  </li>
<li><code>f()</code>: 활성화 함수 (예: ReLU, Sigmoid 등)  </li>
<li><code>y_hat</code>: 신경망이 예측한 값  </li>
</ul>
<p>즉, <strong>순전파는 입력을 넣었을 때 신경망이 출력값을 계산하는 과정</strong>이다.</p>
<hr>
<h2 id="3-손실-함수-loss-function">3. 손실 함수 (Loss Function)</h2>
<p>신경망이 출력한 예측값 <code>y_hat</code>이 실제 정답 <code>y</code>와 얼마나 다른지 계산하는 함수를 <strong>손실 함수(loss function)</strong> 라고 한다.  </p>
<p>예를 들어, <strong>평균제곱오차(MSE)</strong> 는 다음과 같다.</p>
<ul>
<li><code>L = (1/2) * (y - y_hat)^2</code></li>
</ul>
<p>여기서 L은 오차(loss)를 의미한다.<br>L이 클수록 예측이 많이 틀린 것이고, L이 작을수록 정답에 가깝다는 뜻이다.</p>
<hr>
<h2 id="4-역전파-backpropagation">4. 역전파 (Backpropagation)</h2>
<p>손실 L을 줄이려면 가중치 W와 편향 b를 어떻게 바꿔야 할까?</p>
<p>이를 위해 우리는 L을 W와 b에 대해 <strong>미분(gradient)</strong> 한다.<br>즉, <code>∂L/∂W</code>, <code>∂L/∂b</code>를 구해야 한다.  </p>
<p>하지만 신경망은 여러 층으로 쌓여 있기 때문에 직접 미분하기가 복잡하다.<br>여기서 등장하는 것이 <strong>연쇄 법칙(Chain Rule)</strong> 이다.  </p>
<p>예를 들어, 출력층의 가중치 <code>W2</code>에 대한 기울기는 다음과 같이 계산할 수 있다.</p>
<ul>
<li><code>∂L/∂W2 = ∂L/∂y_hat * ∂y_hat/∂z2 * ∂z2/∂W2</code></li>
</ul>
<p>즉, 오차가 출력에서부터 역으로 전파되면서 각 층의 W, b에 대해 얼마나 손실에 기여했는지를 알려준다.  </p>
<p>이 과정을 거치면 <strong>각 층별로 &quot;얼마나 잘못했는지&quot; 알 수 있게 된다.</strong><br>그리고 그 정보를 바탕으로 파라미터를 수정한다.<br>이 전체 과정이 바로 <strong>역전파(Backpropagation)</strong> 이다.</p>
<hr>
<h2 id="5-파라미터-업데이트">5. 파라미터 업데이트</h2>
<p>기울기를 구했다면 이제 파라미터를 업데이트한다.<br>가장 기본적인 방법은 <strong>경사 하강법(Gradient Descent)</strong> 이다.</p>
<ul>
<li><code>W := W - α * ∂L/∂W</code>  </li>
<li><code>b := b - α * ∂L/∂b</code></li>
</ul>
<p>여기서 <code>α</code> 는 학습률(learning rate)이라고 하며, 한 번에 얼마나 크게 이동할지를 정한다.<br>학습률이 너무 크면 발산할 수 있고, 너무 작으면 학습이 느려진다.</p>
<hr>
<h2 id="6-전체-학습-과정-요약">6. 전체 학습 과정 요약</h2>
<ol>
<li>입력을 받아 <strong>순전파</strong> → 예측값 계산  </li>
<li>예측값과 실제 정답을 비교 → <strong>손실 계산</strong>  </li>
<li>손실을 바탕으로 <strong>역전파</strong> → 각 파라미터의 기울기 계산  </li>
<li>기울기를 이용해 <strong>경사 하강법으로 W, b 업데이트</strong>  </li>
<li>이 과정을 여러 번(epoch) 반복  </li>
</ol>
<p>결국 신경망은 점점 더 정답에 가까운 출력을 내도록 학습된다.<br>즉, <strong>역전파는 신경망 학습을 가능하게 해주는 핵심 알고리즘</strong>이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ML] 퍼셉트론의 개념(단층 퍼셉트론 / 다층 퍼셉트론)]]></title>
            <link>https://velog.io/@emma_lee/ML-%ED%8D%BC%EC%85%89%ED%8A%B8%EB%A1%A0%EC%9D%98-%EA%B0%9C%EB%85%90%EB%8B%A8%EC%B8%B5-%ED%8D%BC%EC%85%89%ED%8A%B8%EB%A1%A0-%EB%8B%A4%EC%B8%B5-%ED%8D%BC%EC%85%89%ED%8A%B8%EB%A1%A0</link>
            <guid>https://velog.io/@emma_lee/ML-%ED%8D%BC%EC%85%89%ED%8A%B8%EB%A1%A0%EC%9D%98-%EA%B0%9C%EB%85%90%EB%8B%A8%EC%B8%B5-%ED%8D%BC%EC%85%89%ED%8A%B8%EB%A1%A0-%EB%8B%A4%EC%B8%B5-%ED%8D%BC%EC%85%89%ED%8A%B8%EB%A1%A0</guid>
            <pubDate>Fri, 19 Sep 2025 07:14:40 GMT</pubDate>
            <description><![CDATA[<h2 id="퍼셉트론perceptron">퍼셉트론(Perceptron)</h2>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/9a0d96f0-f656-4dbe-8735-7e3ae86ae6bd/image.png" alt=""></p>
<p>퍼셉트론은 다수의 입력 신호를 받아 하나의 출력 신호를 내는 구조다.<br>즉, <strong>입력 → 연산(가중치, 편향, 활성화 함수) → 출력</strong> 시스템이라고 할 수 있다.
신호가 흐를 때는 1, 신호가 흐르지 않을 때는 0으로 간주한다.</p>
<h3 id="가중치와-편향">가중치와 편향</h3>
<p>퍼셉트론의 수식은 다음과 같다.</p>
<p>$$
y = f\left(\sum_{i=1}^n w_i x_i + b \right)
$$</p>
<ul>
<li>$x_i$: 입력 값  </li>
<li>$w_i$: 가중치 (weight)  </li>
<li>$b$: 편향 (bias)  </li>
<li>$f(\cdot)$: 활성화 함수 (activation function)  </li>
</ul>
<p>즉, 입력과 가중치의 <strong>가중합(weighted sum)</strong> 에 편향을 더하고,<br>그 결과를 <strong>활성화 함수</strong>에 통과시켜 출력 $y$를 얻는다.  </p>
<hr>
<h3 id="퍼셉트론의-한계">퍼셉트론의 한계</h3>
<p>퍼셉트론이 <strong>Unit Step Function</strong>을 활성화 함수로 사용할 경우,<br>선형적으로 구분 가능한 문제만 풀 수 있다.  </p>
<p>예: AND, OR 게이트는 가능하지만 XOR 문제는 풀 수 없다.  </p>
<hr>
<h2 id="다층-퍼셉트론-multi-layer-perceptron-mlp">다층 퍼셉트론 (Multi-Layer Perceptron, MLP)</h2>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/c78f84a0-0480-4475-92c1-0379e8ea80e9/image.png" alt=""></p>
<p>퍼셉트론을 여러 층으로 쌓으면 <strong>다층 퍼셉트론(MLP)</strong> 이 된다.<br>MLP는 <strong>행렬 곱 → 편향 더하기 → 활성화 함수 적용</strong>의 반복이다.  </p>
<p>수식으로 표현하면,  </p>
<p>$$
h^{(1)} = f(W^{(1)} x + b^{(1)})
$$</p>
<p>$$
h^{(2)} = f(W^{(2)} h^{(1)} + b^{(2)})
$$</p>
<p>...</p>
<p>$$
\hat{y} = f(W^{(L)} h^{(L-1)} + b^{(L)})
$$</p>
<ul>
<li>$W^{(l)}$: $l$번째 층의 가중치 행렬  </li>
<li>$b^{(l)}$: $l$번째 층의 편향 벡터  </li>
<li>$f$: 활성화 함수 (ReLU, Sigmoid, Tanh 등)  </li>
<li>$h^{(l)}$: $l$번째 은닉층(hidden layer)의 출력  </li>
</ul>
<hr>
<h3 id="왜-비선형-활성화-함수가-필요한가">왜 비선형 활성화 함수가 필요한가?</h3>
<p>만약 모든 층에서 $f(x)$가 선형 함수라면?</p>
<p>$$
h^{(1)} = W^{(1)} x + b^{(1)}
$$</p>
<p>$$
h^{(2)} = W^{(2)} h^{(1)} + b^{(2)} = W^{(2)} (W^{(1)} x + b^{(1)}) + b^{(2)}
$$</p>
<p>이를 정리하면 결국 하나의 선형 변환이 된다.</p>
<p>$$
h^{(2)} = (W^{(2)} W^{(1)}) x + (W^{(2)} b^{(1)} + b^{(2)})
$$</p>
<p>즉, 선형 활성화 함수만 쓰면 <strong>아무리 층을 깊게 쌓아도 결국은 FC Layer 한 층과 동일한 표현력</strong>밖에 얻지 못한다.  </p>
<p>따라서 <strong>비선형 활성화 함수(non-linear activation)</strong> 가 꼭 필요하다.  </p>
<ul>
<li>Sigmoid, Tanh, ReLU 같은 함수들이 이를 가능하게 해준다.  </li>
<li>선형 → 비선형 → 선형 → 비선형 … 구조를 쌓으면<br>훨씬 복잡하고 다양한 함수를 근사할 수 있다.  </li>
</ul>
<hr>
<h2 id="즉">즉</h2>
<ul>
<li>퍼셉트론: $y = f(\sum w_i x_i + b)$  </li>
<li>퍼셉트론을 여러 층으로 쌓으면 MLP  </li>
<li>비선형 활성화 함수를 넣어야만 깊은 신경망의 표현력이 살아난다</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ML] Training, Validation, Test data]]></title>
            <link>https://velog.io/@emma_lee/ML-Training-Validation-Test-data</link>
            <guid>https://velog.io/@emma_lee/ML-Training-Validation-Test-data</guid>
            <pubDate>Wed, 17 Sep 2025 06:47:11 GMT</pubDate>
            <description><![CDATA[<h2 id="데이터셋-분리-dataset-split">데이터셋 분리 (Dataset Split)</h2>
<p>딥러닝 모델을 학습시킬 때는 <strong>데이터를 어떻게 나눠 쓰느냐</strong>가 성능에 큰 영향을 준다.<br>처음부터 끝까지 똑같은 데이터로만 학습과 평가를 하면 모델이 “암기”만 하게 되고, 실제 새로운 데이터를 만나면 제대로 동작하지 않을 수 있다.  </p>
<p>그래서 데이터셋은 보통 <strong>Training / Validation / Test</strong> 세 가지로 나눈다.  </p>
<hr>
<h3 id="training-vs-validation-vs-test">Training vs. Validation vs. Test</h3>
<ul>
<li><p><strong>Training data (훈련 데이터)</strong><br>모델의 파라미터(가중치, 편향 등)를 학습하는 데 사용된다.<br>쉽게 말해 “연습 문제”다.  </p>
</li>
<li><p><strong>Validation data (검증 데이터)</strong><br>학습 중간중간 모델의 성능을 확인하고, 하이퍼파라미터를 조정하는 데 사용된다. 시험에 대비한 “모의고사 문제” 역할이다.
→ Gradient 계산과 파라미터 업데이트에는 참여하지 않는다.  </p>
</li>
<li><p><strong>Test data (테스트 데이터)</strong><br>학습이 끝난 최종 모델이 새로운 데이터에 대해 얼마나 잘 작동하는지 평가하는 데 사용된다. 즉, 진짜 “수능 문제” 같은 역할이다. 
→ Training에 포함되면 안 된다! (실전 적합성을 확인해야 하기 때문)  </p>
</li>
</ul>
<hr>
<h3 id="왜-validation이-필요한가">왜 Validation이 필요한가?</h3>
<p>Training 데이터만 사용하면 <strong>언제 학습을 멈춰야 하는지</strong> 판단하기 어렵다.<br>너무 오래 학습하면 Training 성능은 좋아지지만, 새로운 데이터에서는 오히려 성능이 떨어지는 <strong>오버피팅(overfitting)</strong> 문제가 발생한다.  </p>
<p>Validation 데이터는 이럴 때 학습이 과한지(early stopping 필요 여부)를 알려주는 지표가 된다.  </p>
<hr>
<h3 id="k-fold-cross-validation">K-Fold Cross Validation</h3>
<p>데이터가 많다면 Training과 Validation을 넉넉하게 나눌 수 있다.<br>하지만 데이터가 적다면 Validation에 쓰는 데이터가 아까울 수 있다.  </p>
<p>이럴 때 사용하는 방법이 <strong>K-Fold 교차 검증(Cross Validation)</strong> 이다.  </p>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/809bdf0e-96ba-4e11-a307-5390f3ba30b5/image.png" alt=""></p>
<p>위 그림에서 K = 5.</p>
<ol>
<li>Training 데이터를 K등분으로 나눈다.  </li>
<li>그중 1개는 Validation으로, 나머지 K-1개는 Training으로 사용한다.  </li>
<li>이 과정을 K번 반복하면서 매번 다른 조합으로 Validation을 만든다.  </li>
<li>최종적으로 K개의 Validation 성능을 평균 내어 모델의 일반화 성능을 평가한다.  </li>
</ol>
<p>→ 이렇게 하면 “편향된 Validation” 문제를 줄일 수 있다.<br>→ 하이퍼파라미터 튜닝에도 활용 가능하다.<br>→ 경우에 따라 학습된 K개의 모델을 앙상블(majority vote 등)로 합치기도 한다.  </p>
<hr>
<h2 id="즉">즉</h2>
<ul>
<li><strong>Training / Validation / Test</strong> 데이터는 각각 연습, 모의고사, 수능 같은 역할을 한다.  </li>
<li>Validation 데이터는 오버피팅을 방지하고 학습 중 모델 성능을 조율하는 데 필요하다.  </li>
<li>데이터가 적을 때는 <strong>K-Fold Cross Validation</strong>으로 검증 안정성을 높일 수 있다.  </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ML] 최적화 알고리즘]]></title>
            <link>https://velog.io/@emma_lee/ML-%EC%B5%9C%EC%A0%81%ED%99%94-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@emma_lee/ML-%EC%B5%9C%EC%A0%81%ED%99%94-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Wed, 17 Sep 2025 05:58:51 GMT</pubDate>
            <description><![CDATA[<h2 id="최적화-알고리즘-optimization-algorithm">최적화 알고리즘 (Optimization Algorithm)</h2>
<p>딥러닝 모델을 학습시킬 때 가장 중요한 과정 중 하나는 <strong>손실 함수(Loss Function)를 최소화하는 것</strong>이다.<br>모델이 예측한 값과 실제 정답이 다르면 손실이 발생하는데, 이 손실을 줄이려면 모델 파라미터(가중치, 편향 등)를 잘 조정해야 한다.  </p>
<p>그럼 어떻게 하면 파라미터를 조금씩 조정해 최적의 값을 찾을 수 있을까?<br>바로 <strong>최적화 알고리즘(Optimization Algorithm)</strong> 이 그 역할을 한다.  </p>
<hr>
<h2 id="gradient-descent">Gradient Descent</h2>
<h3 id="gradient-descent-원리">Gradient Descent 원리</h3>
<p>최적화 알고리즘의 출발점은 <strong>경사 하강법(Gradient Descent)</strong> 이다.<br>아이디어는 아주 단순하다.  </p>
<ul>
<li>일단 가중치와 편향을 아무렇게나 초기화한다.  </li>
<li>현재 위치에서 손실이 얼마나 되는지 확인한다.  </li>
<li>손실을 줄이려면 어디로 가야 할까?  </li>
</ul>
<p>여기서 <strong>그라디언트(Gradient)</strong> 가 등장하는데,
그라디언트는 손실 함수가 가장 빠르게 증가하는 방향을 알려준다.<br>그렇다면 손실을 줄이려면? 반대 방향으로 가면 된다.  </p>
<p>이때 이동하는 보폭을 <strong>learning rate(학습률, α)</strong> 라고 부른다.<br>너무 크게 가면 발산할 수 있고, 너무 작으면 학습이 너무 느려진다.  </p>
<h3 id="gradient-descent-기본-수식">Gradient Descent 기본 수식</h3>
<p>$$
\theta := \theta - \alpha \nabla_\theta L(\theta)
$$</p>
<ul>
<li>$\theta$: 모델의 파라미터(가중치, 편향 등)  </li>
<li>$L(\theta)$: 손실 함수 (loss function)  </li>
<li>$\nabla_\theta L(\theta)$: 파라미터에 대한 손실 함수의 기울기(gradient)  </li>
<li>$\alpha$: 학습률(learning rate)  </li>
</ul>
<h3 id="gradient-descent-종류">Gradient Descent 종류</h3>
<ol>
<li><p><strong>Gradient Descent (경사 하강법, GD)</strong><br>모든 데이터를 사용해 기울기를 계산하고, 그 방향으로 파라미터를 한 번씩 업데이트하는 방식이다.
안정적이지만 데이터가 많을수록 계산이 느리고, 지역 최적해(local minimum)에 갇히기 쉽다.  </p>
</li>
<li><p><strong>Stochastic Gradient Descent (확률적 경사 하강법, SGD)</strong><br>매번 데이터를 하나만 뽑아서 그라디언트를 계산하고 파라미터를 업데이트한다.
속도는 빠르지만, 매번 방향이 불안정해서 진동이 크다.<br>대신 local minimum을 탈출할 기회가 있다는 장점도 있다. (늘 global minimum을 찾는다는 것은 아님!</p>
</li>
<li><p><strong>Mini-batch SGD (미니배치 경사 하강법)</strong><br>SGD는 데이터를 하나씩만 보니까 너무 성급하게 방향을 결정한다는 단점을 보완하기 위한 방법이다. 이는 전체 데이터 중 일부(배치)를 뽑아 기울기를 계산한다.<br>GPU 병렬 연산 덕분에 빠르고, 안정성도 적당히 유지된다.<br>그래서 딥러닝에서는 사실상 <strong>표준</strong>처럼 사용된다.  </p>
</li>
</ol>
<hr>
<h2 id="발전된-최적화-알고리즘들">발전된 최적화 알고리즘들</h2>
<p>연구가 발전하면서 경사 하강법을 더 효율적으로 만들려는 시도가 이어졌다.<br>대표적으로 다음과 같은 알고리즘들이 있다.  </p>
<ul>
<li><p><strong>Momentum</strong><br>매번 기울기를 그대로 따르지 않고, 이전 업데이트 방향을 조금 더 반영한다.<br>관성을 가진 것처럼 움직여서 진동을 줄이고 빠르게 수렴한다.  </p>
</li>
<li><p><strong>RMSProp (Root Mean Square Propagation)</strong><br>파라미터마다 다른 학습률을 적용한다.<br>가파른 방향은 조심스럽게, 완만한 방향은 과감하게 이동한다.  </p>
</li>
<li><p><strong>Adam (Adaptive Moment Estimation)</strong><br>Momentum(1차 모멘트)과 RMSProp(2차 모멘트, 기울기 제곱 평균)을 합친 알고리즘이다.<br>파라미터마다 학습률을 다르게 적용하면서도 진동을 줄여 안정적으로 학습된다.<br>현재 가장 널리 쓰이는 최적화 알고리즘이다.  </p>
</li>
<li><p><strong>AdamW</strong><br>Adam에 <strong>Weight Decay(가중치 감소)</strong> 를 명시적으로 적용한 버전이다.<br>정규화 효과가 커져서 과적합을 방지하는 데 도움이 된다.<br>최신 딥러닝 모델에서는 Adam보다 AdamW를 더 많이 쓴다.  </p>
</li>
</ul>
<hr>
<h2 id="하이퍼파라미터-vs-파라미터">하이퍼파라미터 vs. 파라미터</h2>
<p>최적화 알고리즘에는 사람이 직접 정해줘야 하는 값들이 있다.<br>이를 <strong>하이퍼파라미터(hyperparameter)</strong> 라고 부른다.  </p>
<p>대표적인 예시:  </p>
<ul>
<li><strong>Epoch</strong>: 전체 데이터를 몇 번 반복할지  </li>
<li><strong>Batch size</strong>: 한 번에 몇 개 데이터를 볼지  </li>
<li><strong>Learning rate</strong>: 한 번 이동할 때 보폭 크기  </li>
</ul>
<p>반면, 모델이 스스로 학습하는 값들은 <strong>파라미터(parameter)</strong> 라고 부른다.<br>예를 들어 가중치(weight)와 편향(bias)는 파라미터이고, epoch나 learning rate는 하이퍼파라미터다.  </p>
<blockquote>
<p>하이퍼파라미터 예시:  </p>
</blockquote>
<ul>
<li>학습 관련: epoch, batch size, learning rate, initial weight  </li>
<li>모델 구조: layer 수, node 수, activation function  </li>
<li>학습 목표: loss function 선택, optimization algorithm 선택</li>
</ul>
<hr>
<h2 id="즉">즉</h2>
<ul>
<li>최적화 알고리즘은 손실을 줄이기 위해 파라미터를 조정하는 방법이다.  </li>
<li>Gradient Descent는 그 기본 아이디어이고, 배치/확률적/미니배치 방식으로 나뉜다.  </li>
<li>Momentum, RMSProp, Adam, AdamW 같은 발전된 알고리즘은 더 빠르고 안정적으로 학습을 돕는다.  </li>
<li>학습 과정에서는 epoch, batch size, learning rate 같은 하이퍼파라미터를 잘 설정하는 것이 중요하다.  </li>
</ul>
<p>정리하자면, 딥러닝 모델의 성능은 단순히 모델 구조만으로 결정되지 않는다.<br>어떤 <strong>최적화 알고리즘</strong>을 쓰느냐, 그리고 <strong>하이퍼파라미터를 어떻게 조율하느냐</strong>에 따라 같은 모델도 전혀 다른 결과를 낼 수 있다.  </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ML] 선형 회귀와 로지스틱 회귀]]></title>
            <link>https://velog.io/@emma_lee/ML-%EC%84%A0%ED%98%95-%ED%9A%8C%EA%B7%80Linear-Regression%EC%99%80-%EB%A1%9C%EC%A7%80%EC%8A%A4%ED%8B%B1-%ED%9A%8C%EA%B7%80Logistic-Regression</link>
            <guid>https://velog.io/@emma_lee/ML-%EC%84%A0%ED%98%95-%ED%9A%8C%EA%B7%80Linear-Regression%EC%99%80-%EB%A1%9C%EC%A7%80%EC%8A%A4%ED%8B%B1-%ED%9A%8C%EA%B7%80Logistic-Regression</guid>
            <pubDate>Mon, 15 Sep 2025 11:21:22 GMT</pubDate>
            <description><![CDATA[<h2 id="선형-회귀linear-regression">선형 회귀(Linear Regression)</h2>
<p>우리가 어떤 현상에서 입력과 출력이 어떻게 연결되는지 알고 싶을 때가 많다.<br>예를 들어 유튜브 영상의 <strong>조회수</strong>가 늘면 <strong>수익</strong>이 얼마나 늘어나는지 궁금하다.<br>선형 회귀는 이 관계를 하나의 <strong>직선</strong>으로 설명하려는 방법이다. 식으로 쓰면 <code>y = ax + b</code>다.  </p>
<ul>
<li><code>a</code>: 기울기(가중치, weight) → 조회수가 늘어날 때 수익이 얼마나 변하는지  </li>
<li><code>b</code>: 절편(바이어스, bias) → 조회수가 0일 때 발생하는 기본 수익  </li>
</ul>
<p>즉, 선형 회귀는 <strong>데이터를 가장 잘 설명하는 직선</strong>을 찾는 방법이다.<br>이때 “가장 잘”의 기준은 <strong>손실 함수(loss function)</strong>다. 예측값 <code>ŷ</code>와 실제값 <code>y</code>의 차이를 계산한다.  </p>
<h3 id="손실-함수">손실 함수</h3>
<ul>
<li><strong>MAE (Mean Absolute Error)</strong>: 오차의 절댓값 평균 → 이상치에 덜 민감하다.  </li>
<li><strong>MSE (Mean Squared Error)</strong>: 오차의 제곱 평균 → 큰 오차에 더 큰 벌점을 준다.  </li>
</ul>
<p>손실을 최소화하는 <code>a</code>, <code>b</code>가 우리가 찾는 최적의 파라미터다.  </p>
<h3 id="왜-경사-하강법인가">왜 경사 하강법인가</h3>
<p>파라미터가 두 개일 때는 눈으로 직선을 그려볼 수도 있다.<br>하지만 실제 문제는 파라미터가 수백만, 수십억 개다.<br>모두 바꿔보며 비교하는 것은 불가능하다.  </p>
<p>그래서 <strong>경사 하강법(Gradient Descent)</strong>을 쓴다.<br>아이디어는 간단하다. 현재 위치에서 손실이 가장 빨리 줄어드는 방향(그라디언트의 반대 방향)으로 조금씩 이동하는 것인데, 이 과정을 반복하면 손실이 점점 줄어든다.  </p>
<hr>
<h2 id="로지스틱-회귀logistic-regression">로지스틱 회귀(Logistic Regression)</h2>
<p>로지스틱 회귀는 <strong>분류 문제</strong>에 사용하는 모델이다.<br>출력이 “예/아니오”, “스팸/정상”처럼 0과 1로 갈리는 문제에서 주로 쓴다.  </p>
<p>선형 결합 <code>z = w·x + b</code>를 만든 뒤, 이를 <strong>시그모이드(sigmoid)</strong> 함수에 통과시켜 <strong>확률</strong>을 얻는다.<br>시그모이드 함수는 입력이 아무리 커도 0과 1 사이로 눌러준다.<br>그래서 “양성일 확률이 0.87이다”처럼 해석이 가능하다.  </p>
<ul>
<li>확률 &gt; 0.5 → 1(긍정 클래스)  </li>
<li>확률 ≤ 0.5 → 0(부정 클래스)  </li>
</ul>
<p>여기서 시그모이드 입력값 <code>z</code>를 <strong>로짓(logit)</strong>이라고 부른다.  </p>
<h3 id="손실과-학습">손실과 학습</h3>
<p>로지스틱 회귀는 <strong>이진 교차 엔트로피(Binary Cross Entropy)</strong>를 손실 함수로 쓴다.<br>예측이 정답과 다를수록, 특히 확신을 가지고 틀릴수록 손실이 크게 증가한다.  </p>
<p>파라미터 학습 과정은 선형 회귀와 같다.<br>손실을 파라미터에 대해 편미분해 <strong>그라디언트</strong>를 구하고, 그 반대 방향으로 이동한다.<br>최적화 알고리즘으로는 Gradient Descent, SGD, Adam 등을 많이 쓴다.  </p>
<hr>
<h2 id="두-모델의-차이-요약">두 모델의 차이 요약</h2>
<ul>
<li><p><strong>문제 성격</strong>  </p>
<ul>
<li>선형 회귀: 연속값 예측 (매출, 온도, 수익 등)  </li>
<li>로지스틱 회귀: 이진 분류 (스팸 여부, 질병 유무 등)  </li>
</ul>
</li>
<li><p><strong>출력 해석</strong>  </p>
<ul>
<li>선형 회귀: 실수값을 그대로 출력한다.  </li>
<li>로지스틱 회귀: 0~1 사이의 확률을 출력하고, 기준값으로 0/1을 결정한다.  </li>
</ul>
</li>
<li><p><strong>손실 함수</strong>  </p>
<ul>
<li>선형 회귀: MSE(주로 사용), MAE(이상치 대응)  </li>
<li>로지스틱 회귀: Binary Cross Entropy  </li>
</ul>
</li>
<li><p><strong>학습 방식</strong>  </p>
<ul>
<li>둘 다 손실을 줄이는 방향으로 파라미터를 업데이트한다.  </li>
<li>핵심은 <strong>그라디언트와 경사 하강법</strong>이다.  </li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ML] 인공 신경망]]></title>
            <link>https://velog.io/@emma_lee/ML-%EC%9D%B8%EA%B3%B5-%EC%8B%A0%EA%B2%BD%EB%A7%9D</link>
            <guid>https://velog.io/@emma_lee/ML-%EC%9D%B8%EA%B3%B5-%EC%8B%A0%EA%B2%BD%EB%A7%9D</guid>
            <pubDate>Mon, 15 Sep 2025 10:54:44 GMT</pubDate>
            <description><![CDATA[<h2 id="인공-신경-artificial-neuron">인공 신경 (Artificial Neuron)</h2>
<p>딥러닝에서 우리가 흔히 부르는 <strong>인공 신경망(ANN, Artificial Neural Network)</strong>은 가장 작은 단위부터 출발한다.<br>그 단위가 바로 <strong>인공 신경(Artificial Neuron)</strong>이다.  </p>
<p>인공 신경은 사람 뇌 속의 뉴런(Neuron)을 모방한 구조이며, <strong>노드(Node)</strong>와 이를 잇는 <strong>엣지(Edge, connection)</strong>로 이루어진다.<br>흐름은 다음과 같다.  </p>
<ol>
<li>입력값이 들어온다.  </li>
<li>입력값은 웨이트(가중치, weight)와 곱해진다.  </li>
<li>바이어스(편향, bias)를 더해준다.  </li>
<li>활성화 함수(Activation function)를 통과한다.  </li>
<li>최종 출력값이 나온다.  </li>
</ol>
<p>즉, 인공 신경은 <strong>곱하기 → 더하기 → 비선형 변환</strong>을 거쳐 출력을 내는 단순한 함수다.  </p>
<blockquote>
<p>활성화 함수에는 여러 종류가 있지만, 가장 단순한 형태는 <strong>계단 함수(Unit Step Function)</strong>다.<br>입력이 어떤 기준을 넘으면 1, 아니면 0을 내는 방식이다.  </p>
</blockquote>
<hr>
<h2 id="인공-신경망-artificial-neural-network-ann">인공 신경망 (Artificial Neural Network, ANN)</h2>
<p>인공 신경 하나만으로는 복잡한 문제를 풀 수 없다.<br>그래서 여러 개의 인공 신경을 층층이 쌓아 올려 만든 구조가 바로 <strong>인공 신경망</strong>이다.  </p>
<ul>
<li>각 층(layer)에서는 <strong>가중치 곱하기 → 바이어스 더하기 → 활성화 함수 적용</strong>이 반복된다.  </li>
<li>모든 노드가 서로 연결된 층은 <strong>완전 연결 층(Fully Connected Layer, FC Layer)</strong>이라고 부른다.  </li>
</ul>
<p>우리가 흔히 딥러닝에서 말하는 &quot;네트워크&quot;는 바로 이 인공 신경망의 구조를 뜻한다.  </p>
<hr>
<h2 id="인공-신경망은-결국-함수다">인공 신경망은 결국 &#39;함수&#39;다</h2>
<p>그렇다면 이렇게 여러 층을 쌓은 인공 신경망은 어떤 역할을 할까?<br>바로 <strong>입력을 받아 출력을 내는 하나의 거대한 함수</strong>라고 볼 수 있다.  </p>
<p>학습 과정은 이 함수가 올바른 출력을 내도록 <strong>웨이트와 바이어스를 조정하는 과정</strong>이다.<br>즉, 많은 데이터를 넣어주고  </p>
<ul>
<li>“이 입력에는 이런 출력이 나와야 해”라는 예시를 알려주면서  </li>
<li>그 차이를 줄이는 방향으로 파라미터를 업데이트한다.  </li>
</ul>
<p>그 결과, 새로운 데이터가 들어와도 적절한 출력을 낼 수 있게 된다.<br>결국 AI는 <strong>입력과 출력을 매핑(mapping)하는 함수를 학습한다</strong>고 말할 수 있다.  </p>
<hr>
<h2 id="간단한-예시">간단한 예시</h2>
<p>가장 단순한 1차 함수 <code>y = ax + b</code>도 인공 신경망으로 표현할 수 있다.  </p>
<ul>
<li>입력: <code>x</code>  </li>
<li>가중치(weight): <code>a</code>  </li>
<li>바이어스(bias): <code>b</code>  </li>
<li>출력: <code>y</code>  </li>
</ul>
<p>즉, 우리가 수학 시간에 배운 1차 함수조차도 인공 신경의 구조로 해석할 수 있다.<br>이런 단순한 블록을 쌓고 확장해 나간 것이 오늘날의 인공 신경망이다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ML] 지도・비지도・자기지도・강화 학습]]></title>
            <link>https://velog.io/@emma_lee/ML-%EC%A7%80%EB%8F%84%ED%95%99%EC%8A%B5%EB%B9%84%EC%A7%80%EB%8F%84%ED%95%99%EC%8A%B5%EC%9E%90%EA%B8%B0%EC%A7%80%EB%8F%84%ED%95%99%EC%8A%B5%EA%B0%95%ED%99%94%ED%95%99%EC%8A%B5</link>
            <guid>https://velog.io/@emma_lee/ML-%EC%A7%80%EB%8F%84%ED%95%99%EC%8A%B5%EB%B9%84%EC%A7%80%EB%8F%84%ED%95%99%EC%8A%B5%EC%9E%90%EA%B8%B0%EC%A7%80%EB%8F%84%ED%95%99%EC%8A%B5%EA%B0%95%ED%99%94%ED%95%99%EC%8A%B5</guid>
            <pubDate>Thu, 04 Sep 2025 06:51:13 GMT</pubDate>
            <description><![CDATA[<h1 id="1-지도-학습-supervised-learning">1. 지도 학습 (Supervised Learning)</h1>
<p>지도학습은 <strong>정답(label)이 있는 데이터</strong>를 기반으로 입력-출력 간의 관계를 학습한다. 미리 사람이 입력에 대한 정답을 미리 만들어놓은 것이다. 이를 통해 데이터를 보고 ‘정답’을 맞히는 방식으로 학습한다. </p>
<table>
<thead>
<tr>
<th>유형</th>
<th>설명</th>
<th>예시</th>
</tr>
</thead>
<tbody><tr>
<td>분류</td>
<td>데이터를 클래스 또는 범주로 나눔</td>
<td>이메일 스팸 필터링, 질병 진단, 고객 이탈 여부</td>
</tr>
<tr>
<td>회귀</td>
<td>수치 값을 예측</td>
<td>부동산 가격 예측, 주가 예측, 날씨 예측</td>
</tr>
</tbody></table>
<blockquote>
<p>주요 알고리즘: 의사결정나무, 랜덤포레스트, SVM, 로지스틱 회귀, 선형 회귀 등</p>
</blockquote>
<hr>
<h1 id="2-비지도-학습-unsupervised-learning">2. 비지도 학습 (Unsupervised Learning)</h1>
<p>비지도 학습은 <strong>정답(label)이 없는 데이터</strong>에서 유의미한 패턴, 구조, 그룹을 발견하는 것이다. 데이터 간의 유사성을 기반으로 자동으로 분류하거나 압축하는 데 사용된다.</p>
<table>
<thead>
<tr>
<th>대표 기법</th>
<th>설명</th>
<th>예시</th>
</tr>
</thead>
<tbody><tr>
<td>군집화 (Clustering)</td>
<td>유사한 특성을 가진 데이터끼리 그룹화</td>
<td>고객 세분화, 상품 추천</td>
</tr>
<tr>
<td>차원 축소 (PCA, t-SNE 등)</td>
<td>고차원 데이터를 시각화 가능한 형태로 축소</td>
<td>데이터 시각화, 노이즈 제거</td>
</tr>
<tr>
<td>연관 규칙 학습</td>
<td>항목 간의 관계 탐색</td>
<td>장바구니 분석, 추천 시스템</td>
</tr>
</tbody></table>
<hr>
<h1 id="3-자기지도-학습-self-supervised-learning">3. 자기지도 학습 (Self-Supervised Learning)</h1>
<p>자기지도 학습은 <strong>지도학습과 비지도학습의 중간 형태</strong>이다. 비지도처럼 정답(label)이 없는 원천 데이터에서 학습하지만, 지도처럼 가짜 라벨을 스스로 생성하여 학습한다. 즉, 사람이 직접 라벨링하지 않아도, 데이터의 일부를 숨기고 나머지 데이터를 활용하여 &#39;스스로 문제를 내고 맞히는 방식&#39;으로 학습하는 것이 핵심이다. GPT, BERT와 같은 모델 역시 자기지도학습을 통해 만들어진 것이다!</p>
<hr>
<h1 id="4-강화-학습-reinforcement-learning">4. 강화 학습 (Reinforcement Learning)</h1>
<p>강화학습은 <strong>보상을 최대화하며 정책을 학습</strong>하는 것이다. 이는 꼭 사람이 학습하는 것과 비슷한 방식인데, 어떤 행동을 했을 때 상대방이 웃고 있으면 계속 그 행동을 이어가고, 찡그리는 표정을 지으면 싫은 행동임을 인식하고 그 행동을 하지 않는 방식으로 학습해왔다. </p>
<p>바둑을 예시로 들어서 강화학습의 주요 용어들에 대해 살펴보면 다음과 같다.</p>
<ul>
<li>Agent: 게임 속에서 직접 행동하는 주체. ex) 흑돌</li>
<li>Action:  에이전트가 할 수 있는 선택. ex) 수</li>
<li>Reward: 행동의 결과로 받는 점수. ex) 승점</li>
<li>Environment: 에이전트와 상호작용하는 세상 전체. ex) 바둑판+상대방+규칙+심판</li>
<li>State: 현재 상황. ex) 돌이 어떻게 놓여  있는가.</li>
<li>Q-function: 이 상태에서 이 행동을 하면 얼마나 좋은가? ex) 지금 이 수를 두면 이길 확률</li>
<li>Episode: 여러 번의 에피소드를 겪으면서 점점 강화됨. ex) 게임 한 판</li>
<li>Q-learning: 이 상황에선 이 수가 이득이구나. 하며 점차 업데이트 하는 방식. ex) Q-function을 배우는 방법</li>
<li>Exploration: 이미 아는 수만 두면 발전이 없으므로, 새로운 수를 시도해보는 것. ex) 새로운 길을 찾게 해줌.</li>
<li>Discount factor: 좋고 나쁨을 얘기해 줌.</li>
</ul>
<blockquote>
<p>주요 예시:  </p>
<ul>
<li>알파고(바둑 AI)  </li>
<li>로봇 제어  </li>
<li>게임 플레이 에이전트</li>
</ul>
</blockquote>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Git] Git 설치 & 기본 명령어]]></title>
            <link>https://velog.io/@emma_lee/Git-Git-%EC%84%A4%EC%B9%98-%EA%B8%B0%EB%B3%B8-%EB%AA%85%EB%A0%B9%EC%96%B4</link>
            <guid>https://velog.io/@emma_lee/Git-Git-%EC%84%A4%EC%B9%98-%EA%B8%B0%EB%B3%B8-%EB%AA%85%EB%A0%B9%EC%96%B4</guid>
            <pubDate>Wed, 16 Jul 2025 08:01:53 GMT</pubDate>
            <description><![CDATA[<h2 id="1-git-설치">1. Git 설치</h2>
<h3 id="다운로드-및-설치">다운로드 및 설치</h3>
<ul>
<li>공식 웹사이트 접속: <a href="https://git-scm.com/">https://git-scm.com/</a></li>
<li>운영체제에 맞는 버전 선택 후 설치</li>
<li>설치 중 특별한 설정 없이 기본 옵션으로 진행해도 무방</li>
</ul>
<h3 id="설치-확인">설치 확인</h3>
<p>설치 후 터미널(Git Bash 등)에서 아래 명령어 입력:</p>
<pre><code>git --version</code></pre><p>정상적으로 설치되었다면 버전 정보 출력</p>
<hr>
<h2 id="2-git-명령어-사용-환경">2. Git 명령어 사용 환경</h2>
<p>Git 명령어는 다양한 환경에서 사용 가능 
운영체제나 개발 환경에 따라 적합한 방법을 선택하면 됨</p>
<table>
<thead>
<tr>
<th>환경</th>
<th>특징</th>
<th>권장 대상</th>
</tr>
</thead>
<tbody><tr>
<td>Git Bash</td>
<td>리눅스 명령어 지원, 설치 후 바로 사용 가능</td>
<td>Windows 사용자, 학습 목적</td>
</tr>
<tr>
<td>macOS 터미널</td>
<td>기본 제공, 빠른 실행 가능</td>
<td>Mac 사용자</td>
</tr>
<tr>
<td>VS Code 터미널</td>
<td>Git UI와 통합, 다양한 셸 선택 가능</td>
<td>모든 사용자</td>
</tr>
<tr>
<td>CMD / PowerShell</td>
<td>가볍게 실행 가능, Bash 명령어 미지원</td>
<td>간단한 Git 작업</td>
</tr>
</tbody></table>
<blockquote>
<p>Git을 처음 사용하는 경우, <strong>Git Bash 또는 VS Code 터미널</strong> 사용을 추천!</p>
</blockquote>
<hr>
<h2 id="3-기본-리눅스-명령어-git-bash-기준">3. 기본 리눅스 명령어 (Git Bash 기준)</h2>
<p>Git은 CLI 기반 도구이므로 기본적인 경로 명령어를 알아야 한다.</p>
<ul>
<li><code>cd</code>: 디렉토리 이동  </li>
<li><code>ls</code>: 현재 폴더 내 파일/디렉토리 목록 출력  </li>
<li><code>shift + insert</code>: 붙여넣기  </li>
<li><code>tab</code>: 자동완성  </li>
</ul>
<hr>
<h2 id="4-git-기본-명령어-실습-흐름">4. Git 기본 명령어 실습 흐름</h2>
<p>Git은 일반적으로 다음 순서로 사용된다:</p>
<ol>
<li>작업 디렉토리 설정</li>
<li>저장소 초기화</li>
<li>사용자 정보 등록</li>
<li>원격 저장소 연결</li>
<li>변경 사항 추가 → 커밋 → 푸시</li>
</ol>
<hr>
<h3 id="1-작업-디렉토리-이동">1) 작업 디렉토리 이동</h3>
<pre><code>cd Desktop
cd 폴더명</code></pre><hr>
<h3 id="2-git-저장소-초기화">2) Git 저장소 초기화</h3>
<pre><code>git init</code></pre><p>현재 디렉토리를 Git 저장소로 초기화함. 이후 Git 명령어 사용 가능.</p>
<hr>
<h3 id="3-사용자-정보-등록">3) 사용자 정보 등록</h3>
<pre><code>git config --global user.name &quot;사용자 이름&quot;
git config --global user.email &quot;사용자 이메일&quot;</code></pre><p><code>--global</code> 옵션은 최초 1회만 설정하면 모든 프로젝트에 적용됨.</p>
<hr>
<h3 id="4-원격-저장소-연결-github-등">4) 원격 저장소 연결 (GitHub 등)</h3>
<ol>
<li><p>GitHub에서 새 레포지토리 생성  </p>
</li>
<li><p>주소 복사:<br>예시<br><code>https://github.com/사용자명/레포지토리명.git</code></p>
</li>
<li><p>연결 명령어:</p>
<p> git remote add origin 복사한_주소</p>
</li>
</ol>
<hr>
<h3 id="5-파일-추가-및-커밋">5) 파일 추가 및 커밋</h3>
<h4 id="변경-파일-스테이지에-추가">변경 파일 스테이지에 추가</h4>
<pre><code>git add .</code></pre><p>또는 특정 파일만:</p>
<pre><code>git add 파일명</code></pre><h4 id="커밋">커밋</h4>
<pre><code>git commit -m &quot;커밋 메시지&quot;</code></pre><hr>
<h3 id="6-github에-푸시">6) GitHub에 푸시</h3>
<pre><code>git push origin master</code></pre><p>※ 브랜치 이름이 <code>main</code>인 경우:</p>
<pre><code>git push origin main</code></pre><hr>
<h3 id="7-github에서-변경사항-받아오기">7) GitHub에서 변경사항 받아오기</h3>
<pre><code>git pull origin master</code></pre><hr>
<h2 id="5-추가-명령어">5. 추가 명령어</h2>
<h3 id="사용자-정보-확인">사용자 정보 확인</h3>
<pre><code>git config --global --list</code></pre><h3 id="원격-저장소-확인">원격 저장소 확인</h3>
<pre><code>git remote -v</code></pre><h3 id="원격-저장소-삭제">원격 저장소 삭제</h3>
<pre><code>git remote rm origin</code></pre><h3 id="로컬-git-저장소-삭제-주의">로컬 Git 저장소 삭제 (주의!)</h3>
<pre><code>rm -rf .git</code></pre><p>해당 폴더 내 Git 기록 완전 삭제. 이후 <code>git init</code>부터 다시 진행 필요.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Git] Git & GitHub]]></title>
            <link>https://velog.io/@emma_lee/Git-Git-GitHub</link>
            <guid>https://velog.io/@emma_lee/Git-Git-GitHub</guid>
            <pubDate>Fri, 16 May 2025 03:46:08 GMT</pubDate>
            <description><![CDATA[<h1 id="git-vs-github">Git vs GitHub</h1>
<p>개발을 시작하면 가장 먼저 접하게 되는 개념 중 하나가 Git과 GitHub이다.<br>이름은 비슷하지만 두 도구는 역할이 명확히 다르다.</p>
<hr>
<h2 id="git">Git</h2>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/427c79d5-4066-419c-bd13-5573c98ec774/image.png" alt="Git"></p>
<p>Git은 <strong>로컬에서 사용하는 분산 버전 관리 도구</strong>이다.<br>코드 변경 이력을 기록하고, 이전 상태로 되돌리거나 브랜치를 만들어 실험할 수 있도록 도와준다.<br>개인 개발은 물론 협업에서도 필수적인 도구이다.</p>
<h3 id="주요-기능">주요 기능</h3>
<ul>
<li>코드 변경 사항 추적 및 복원</li>
<li>브랜치를 활용한 실험 및 개발</li>
<li>병합(Merge)과 충돌 해결을 통한 협업</li>
</ul>
<p>모든 Git 정보는 로컬 저장소에 <code>.git</code> 폴더로 저장된다.</p>
<hr>
<h2 id="github">GitHub</h2>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/d4bc3603-bf7e-4ae1-b6d1-fdad76764168/image.png" alt="GitHub"></p>
<p>GitHub는 Git 저장소를 <strong>온라인에 저장하고 공유할 수 있게 해주는 플랫폼</strong>이다.<br>Git으로 관리된 프로젝트를 업로드하여 백업하고, 다른 사람과 협업할 수 있는 환경을 제공한다.</p>
<h3 id="주요-기능-1">주요 기능</h3>
<ul>
<li>원격 저장소 관리 및 백업</li>
<li>Pull Request를 통한 코드 리뷰</li>
<li>이슈 트래킹, 협업, 오픈소스 기여 등 지원</li>
</ul>
<p>GitHub는 Git을 기반으로 하며, 명령어는 Git과 동일하게 사용된다.</p>
<hr>
<h2 id="local-repository-vs-remote-repository">local repository vs remote repository</h2>
<p>Git은 로컬 저장소와 원격 저장소를 함께 사용한다.</p>
<ul>
<li><strong>로컬 저장소(local)</strong>: 개발자가 직접 작업하는 컴퓨터 내 Git 저장소</li>
<li><strong>원격 저장소(remote)</strong>: GitHub와 같은 온라인 플랫폼에 위치한 저장소</li>
</ul>
<h3 id="동기화-명령어">동기화 명령어</h3>
<ul>
<li><code>git push</code> : 로컬 → 원격 저장소로 변경 사항 업로드  </li>
<li><code>git pull</code> : 원격 → 로컬 저장소로 변경 사항 다운로드</li>
</ul>
<p>GitHub는 이러한 <code>push</code>와 <code>pull</code>을 통해 로컬 저장소와 원격 저장소를 연결해주는 역할을 한다.</p>
<hr>
<h2 id="git과-github-비교">Git과 GitHub 비교</h2>
<table>
<thead>
<tr>
<th>구분</th>
<th>Git</th>
<th>GitHub</th>
</tr>
</thead>
<tbody><tr>
<td>역할</td>
<td>버전 관리 도구</td>
<td>원격 저장소 서비스</td>
</tr>
<tr>
<td>사용 위치</td>
<td>로컬 (내 컴퓨터)</td>
<td>클라우드 (웹 기반)</td>
</tr>
<tr>
<td>기능</td>
<td>커밋, 브랜치, 병합 등 로컬 작업 중심</td>
<td>저장소 공유, 협업, Pull Request, 이슈 관리 등</td>
</tr>
<tr>
<td>필요 조건</td>
<td>Git 설치 필요</td>
<td>회원가입 후 웹 사용 가능</td>
</tr>
</tbody></table>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Flutter] 안드로이드 & iOS 앱 개발 환경 정리]]></title>
            <link>https://velog.io/@emma_lee/Flutter-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-iOS-%EC%95%B1-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@emma_lee/Flutter-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-iOS-%EC%95%B1-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 24 Apr 2025 03:37:59 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Flutter를 공부하다가 iOS에서 돌아가는 어플을 만들기 위해서는 맥북이 필수적으로 필요하다는 이야기를 들어서 궁금했던 내용들을 정리해보려고 한다!  
결론부터 말하자면, <strong>iOS는 Mac에서만 개발 가능하다.</strong></p>
</blockquote>
<hr>
<h2 id="🎯-목표">🎯 목표</h2>
<p><strong>&quot;안드로이드 + iOS 둘 다 돌아가는 어플 만들고 싶다!&quot;</strong></p>
<p>요즘은 크로스 플랫폼 프레임워크인 Flutter 덕분에,<br>한 번의 코드 작성으로 <strong>Android와 iOS 앱을 동시에</strong> 개발할 수 있는 시대다.<br>하지만 개발 환경에 따라 몇 가지 제약이 생긴다.</p>
<hr>
<h3 id="windows-vs-mac-노트북-비교">Windows vs Mac 노트북 비교</h3>
<table>
<thead>
<tr>
<th>운영체제</th>
<th>안드로이드 앱 개발</th>
<th>iOS 앱 개발</th>
<th>비고</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Windows</strong></td>
<td>⭕ 가능</td>
<td>❌ 불가능</td>
<td>iOS 앱은 Mac 전용 툴(Xcode)이 필요함</td>
</tr>
<tr>
<td><strong>Mac</strong></td>
<td>⭕ 가능</td>
<td>⭕ 가능</td>
<td>Android &amp; iOS 둘 다 개발 가능</td>
</tr>
</tbody></table>
<hr>
<h3 id="mac에서만-ios-개발할-수-있는-이유">Mac에서만 iOS 개발할 수 있는 이유</h3>
<ul>
<li>iOS 앱을 빌드하고 실행하기 위해서는 애플의 공식 개발 도구인 <code>Xcode</code>가 필요하다.  </li>
<li>하지만 이 <code>Xcode</code>는 오직 <strong>macOS에서만 설치 및 실행 가능</strong>하다.  </li>
<li>Windows에서 Flutter로 iOS 코드를 <strong>작성</strong>하는 건 가능하지만, <strong>빌드(실행)하거나 App Store에 배포하는 건 불가능</strong>하다.</li>
</ul>
<hr>
<h3 id="요약표">요약표</h3>
<blockquote>
<p>Flutter로 iOS 앱까지 만들고 싶다면<br><strong>iOS 빌드용 Mac 환경은 반드시 필요하다.</strong></p>
</blockquote>
<table>
<thead>
<tr>
<th>작업 항목</th>
<th>Windows 노트북</th>
<th>Mac 노트북</th>
</tr>
</thead>
<tbody><tr>
<td>Flutter 앱 개발</td>
<td>⭕ 가능</td>
<td>⭕ 가능</td>
</tr>
<tr>
<td>Android 앱 테스트</td>
<td>⭕ 가능</td>
<td>⭕ 가능</td>
</tr>
<tr>
<td>iOS 앱 테스트</td>
<td>❌ 불가능</td>
<td>⭕ 가능</td>
</tr>
<tr>
<td>iOS 앱 App Store 배포</td>
<td>❌ 불가능</td>
<td>⭕ 가능</td>
</tr>
</tbody></table>
<hr>
<h3 id="추가-팁">추가 팁</h3>
<ul>
<li>Flutter Web이나 Desktop 앱은 Windows에서도 문제 없이 가능하다.</li>
<li>iOS 개발만 목표라면 <strong>Swift + Xcode + Mac 조합</strong>이 더 효율적이다.</li>
<li>Flutter는 <strong>Firebase, Supabase</strong> 등과 잘 어울린다. → 백엔드 걱정도 줄여준다!</li>
</ul>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 선언 방식, 제이쿼리(jQuery), 비동기 개념]]></title>
            <link>https://velog.io/@emma_lee/JavaScript-8.-%EC%84%A0%EC%96%B8-%EB%B0%A9%EC%8B%9D-%EC%A0%9C%EC%9D%B4%EC%BF%BC%EB%A6%ACjQuery-%EB%B9%84%EB%8F%99%EA%B8%B0-%EA%B0%9C%EB%85%90</link>
            <guid>https://velog.io/@emma_lee/JavaScript-8.-%EC%84%A0%EC%96%B8-%EB%B0%A9%EC%8B%9D-%EC%A0%9C%EC%9D%B4%EC%BF%BC%EB%A6%ACjQuery-%EB%B9%84%EB%8F%99%EA%B8%B0-%EA%B0%9C%EB%85%90</guid>
            <pubDate>Wed, 23 Apr 2025 12:13:32 GMT</pubDate>
            <description><![CDATA[<h2 id="17-선언-방식">17. 선언 방식</h2>
<p>JavaScript는 HTML에서 다음 세 가지 방식으로 선언할 수 있다.</p>
<hr>
<h3 id="17-1-내부-방식-internal-javascript">17-1. 내부 방식 (Internal JavaScript)</h3>
<pre><code class="language-html">&lt;script&gt;
  alert(&quot;내부 방식으로 작성된 JavaScript입니다.&quot;);
&lt;/script&gt;</code></pre>
<ul>
<li><code>&lt;script&gt;</code> 태그 내부에 코드를 작성</li>
<li>보통 <code>&lt;body&gt;</code> 하단에 위치해 HTML 로딩 이후 실행되도록 함</li>
</ul>
<hr>
<h3 id="17-2-인라인-방식-inline-javascript">17-2. 인라인 방식 (Inline JavaScript)</h3>
<pre><code class="language-html">&lt;button onclick=&quot;alert(&#39;인라인 방식&#39;)&quot;&gt;클릭&lt;/button&gt;</code></pre>
<ul>
<li>HTML 태그의 속성으로 JS 코드 직접 삽입</li>
<li>유지보수가 어렵고 추천되지 않음</li>
</ul>
<hr>
<h3 id="17-3-외부-방식-external-javascript">17-3. 외부 방식 (External JavaScript)</h3>
<pre><code class="language-html">&lt;script src=&quot;main.js&quot;&gt;&lt;/script&gt;</code></pre>
<ul>
<li>JS 코드를 별도 <code>.js</code> 파일에 작성하고 링크함</li>
<li>가장 실무적인 방식 (HTML, CSS, JS 분리)</li>
</ul>
<hr>
<h3 id="주의사항">주의사항</h3>
<ul>
<li><code>&lt;script&gt;</code>는 HTML 요소보다 <strong>뒤쪽</strong>에 위치해야 DOM 요소를 정상 인식함</li>
<li><code>&lt;head&gt;</code>에 넣을 경우 <code>DOMContentLoaded</code> 이벤트나 <code>$(document).ready()</code> 필요</li>
</ul>
<hr>
<h2 id="18-제이쿼리jquery">18. 제이쿼리(jQuery)</h2>
<h3 id="개요">개요</h3>
<ul>
<li>JS의 문법을 <strong>간결하고</strong> <strong>브라우저 호환성</strong> 있게 사용할 수 있도록 설계</li>
<li>DOM 조작, 이벤트 처리, Ajax 등 간편하게 처리 가능</li>
</ul>
<hr>
<h3 id="기본-문법">기본 문법</h3>
<pre><code class="language-javascript">$(선택자).동작함수(매개변수);</code></pre>
<ul>
<li>접근: <code>$(&quot;#id&quot;)</code>, <code>$(&quot;.class&quot;)</code></li>
<li>동작: <code>.html()</code>, <code>.text()</code>, <code>.css()</code></li>
<li>이벤트: <code>.on(&quot;click&quot;, function() {...})</code></li>
</ul>
<hr>
<h3 id="예제">예제</h3>
<pre><code class="language-html">&lt;script src=&quot;https://code.jquery.com/jquery-3.7.1.min.js&quot;&gt;&lt;/script&gt;

&lt;script&gt;
  $(document).ready(function() {
    $(&quot;#btn&quot;).on(&quot;click&quot;, function() {
      $(&quot;#text&quot;).text(&quot;버튼 클릭됨!&quot;);
    });
  });
&lt;/script&gt;

&lt;button id=&quot;btn&quot;&gt;클릭&lt;/button&gt;
&lt;p id=&quot;text&quot;&gt;기본 텍스트&lt;/p&gt;</code></pre>
<hr>
<h2 id="19-동기-vs-비동기-통신">19. 동기 vs 비동기 통신</h2>
<hr>
<h3 id="19-1-동기synchronous">19-1. 동기(Synchronous)</h3>
<ul>
<li>요청 → 응답을 받을 때까지 <strong>대기</strong></li>
<li>흐름이 차단됨</li>
</ul>
<pre><code class="language-javascript">alert(&quot;닫기 전까지 다음 코드 실행 안 됨&quot;);
console.log(&quot;이건 나중에 출력됨&quot;);</code></pre>
<hr>
<h3 id="19-2-비동기asynchronous">19-2. 비동기(Asynchronous)</h3>
<ul>
<li>요청 → 기다리지 않고 다음 코드 <strong>즉시 실행</strong></li>
<li>흐름을 <strong>멈추지 않음</strong></li>
</ul>
<pre><code class="language-javascript">setTimeout(() =&gt; {
  console.log(&quot;3초 후 출력&quot;);
}, 3000);
console.log(&quot;이건 먼저 실행됨&quot;);</code></pre>
<hr>
<h3 id="동기-vs-비동기-비교">동기 vs 비동기 비교</h3>
<table>
<thead>
<tr>
<th>항목</th>
<th>동기 (Synchronous)</th>
<th>비동기 (Asynchronous)</th>
</tr>
</thead>
<tbody><tr>
<td>실행 순서</td>
<td>순차 처리</td>
<td>병렬 처리 가능</td>
</tr>
<tr>
<td>흐름 차단</td>
<td>O</td>
<td>X</td>
</tr>
<tr>
<td>사용자 경험</td>
<td>멈춤 발생 가능</td>
<td>자연스러운 UX</td>
</tr>
<tr>
<td>예시</td>
<td><code>alert()</code>, <code>form submit</code></td>
<td><code>setTimeout()</code>, <code>fetch()</code></td>
</tr>
</tbody></table>
<hr>
<h3 id="json-예시">JSON 예시</h3>
<pre><code class="language-json">{
  &quot;name&quot;: &quot;Emma&quot;,
  &quot;age&quot;: 25,
  &quot;skills&quot;: [&quot;JavaScript&quot;, &quot;Python&quot;]
}</code></pre>
<pre><code class="language-javascript">let data = {
  name: &quot;Emma&quot;,
  age: 25,
  skills: [&quot;JavaScript&quot;, &quot;Python&quot;]
};

console.log(data.skills[1]); // &quot;Python&quot;</code></pre>
<hr>
<h3 id="fetch-예제-비동기-통신">fetch 예제 (비동기 통신)</h3>
<pre><code class="language-javascript">fetch(&quot;https://api.example.com/data&quot;)
  .then(res =&gt; res.json())
  .then(data =&gt; console.log(data))
  .catch(err =&gt; console.error(&quot;에러 발생:&quot;, err));</code></pre>
<hr>
<h2 id="20-동적-요소-생성">20. 동적 요소 생성</h2>
<p>HTML 요소를 JS로 동적으로 생성하는 방법 정리</p>
<hr>
<h3 id="핵심-메서드">핵심 메서드</h3>
<table>
<thead>
<tr>
<th>동작</th>
<th>메서드</th>
</tr>
</thead>
<tbody><tr>
<td>태그 생성</td>
<td><code>document.createElement()</code></td>
</tr>
<tr>
<td>텍스트 생성</td>
<td><code>document.createTextNode()</code></td>
</tr>
<tr>
<td>속성 생성</td>
<td><code>document.createAttribute()</code></td>
</tr>
<tr>
<td>속성 추가</td>
<td><code>setAttributeNode()</code></td>
</tr>
<tr>
<td>요소 추가</td>
<td><code>appendChild()</code></td>
</tr>
</tbody></table>
<hr>
<h3 id="텍스트-포함-요소-생성">텍스트 포함 요소 생성</h3>
<pre><code class="language-javascript">let span = document.createElement(&quot;span&quot;);
let text = document.createTextNode(&quot;생성된 텍스트입니다.&quot;);
span.appendChild(text);
document.getElementById(&quot;container&quot;).appendChild(span);</code></pre>
<hr>
<h3 id="이미지-생성-예시">이미지 생성 예시</h3>
<pre><code class="language-javascript">let img = document.createElement(&quot;img&quot;);
let src = document.createAttribute(&quot;src&quot;);
src.value = &quot;https://image-url.com/example.png&quot;;
img.setAttributeNode(src);
document.getElementById(&quot;container&quot;).appendChild(img);</code></pre>
<hr>
<h3 id="댓글-동적-생성-실습-예시">댓글 동적 생성 실습 예시</h3>
<ul>
<li>input에 댓글 입력</li>
<li>등록 버튼 클릭 or Enter 시 li 생성</li>
<li>삭제 버튼도 함께 생성</li>
</ul>
<p>→ 실습 전체 HTML은 마크다운 상단 참고</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 실습 프로젝트 모음(2): 스타일 제어 및 이미지 다루기]]></title>
            <link>https://velog.io/@emma_lee/JavaScript-7.-%EC%8B%A4%EC%8A%B5-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%AA%A8%EC%9D%8C2-%EC%8A%A4%ED%83%80%EC%9D%BC-%EC%A0%9C%EC%96%B4-%EB%B0%8F-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EB%8B%A4%EB%A3%A8%EA%B8%B0</link>
            <guid>https://velog.io/@emma_lee/JavaScript-7.-%EC%8B%A4%EC%8A%B5-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%AA%A8%EC%9D%8C2-%EC%8A%A4%ED%83%80%EC%9D%BC-%EC%A0%9C%EC%96%B4-%EB%B0%8F-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EB%8B%A4%EB%A3%A8%EA%B8%B0</guid>
            <pubDate>Wed, 23 Apr 2025 12:09:26 GMT</pubDate>
            <description><![CDATA[<h2 id="15-스타일-제어">15. 스타일 제어</h2>
<ul>
<li>JavaScript를 통해 HTML 요소의 스타일을 동적으로 변경할 수 있다.  </li>
<li>이는 <strong>프론트엔드 인터랙션의 핵심 요소</strong>로, 사용자 경험을 향상시키는 데 중요한 역할을 한다.</li>
</ul>
<hr>
<h3 id="스타일-제어-방법">스타일 제어 방법</h3>
<ul>
<li>CSS 스타일을 JavaScript로 수정할 수 있다.</li>
<li>방식: <code>요소.style.속성명 = &quot;값&quot;</code> 또는 <code>요소.style.cssText = &quot;속성: 값; ...&quot;</code>.</li>
<li><strong>인라인 방식</strong>으로 적용되며 유지보수는 어렵지만 빠르게 적용 가능하다.</li>
</ul>
<hr>
<h3 id="예제-버튼-클릭-시-텍스트-색상과-크기-변경">예제: 버튼 클릭 시 텍스트 색상과 크기 변경</h3>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;title&gt;스타일 제어&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;span id=&quot;text&quot;&gt;나의 스타일을 변경해줘!!&lt;/span&gt;
  &lt;button id=&quot;btn&quot;&gt;스타일 변경하기!&lt;/button&gt;

  &lt;script&gt;
    const change = () =&gt; {
      document.getElementById(&quot;text&quot;).style.cssText = &quot;color: pink; font-size: 50px&quot;;
    };

    document.getElementById(&quot;btn&quot;).addEventListener(&quot;click&quot;, change);
  &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<hr>
<h3 id="실습-포인트">실습 포인트</h3>
<ul>
<li>속성 접근은 <code>.style.속성명</code> 또는 <code>.style.cssText</code></li>
<li>단순 스타일 제어 시는 인라인 방식도 유효</li>
<li>유지보수 관점에서는 클래스 제어를 추천 (<code>classList.add/remove</code>)</li>
</ul>
<hr>
<h2 id="16-이미지-다루기-image">16. 이미지 다루기 (Image)</h2>
<p>HTML에서 이미지를 삽입하거나 JavaScript로 동적으로 제어할 수 있다.</p>
<hr>
<h3 id="기본-이미지-삽입-html-태그">기본 이미지 삽입 (HTML 태그)</h3>
<pre><code class="language-html">&lt;img src=&quot;이미지경로.jpg&quot; alt=&quot;대체텍스트&quot; width=&quot;300&quot;&gt;</code></pre>
<table>
<thead>
<tr>
<th>속성</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>src</code></td>
<td>이미지 경로</td>
</tr>
<tr>
<td><code>alt</code></td>
<td>대체 텍스트 (이미지 실패 시)</td>
</tr>
<tr>
<td><code>width</code></td>
<td>너비 지정</td>
</tr>
</tbody></table>
<p>예시:</p>
<pre><code class="language-html">&lt;img src=&quot;https://via.placeholder.com/300x200&quot; alt=&quot;예시 이미지&quot; width=&quot;300&quot;&gt;</code></pre>
<hr>
<h3 id="js로-이미지-속성-변경">JS로 이미지 속성 변경</h3>
<pre><code class="language-html">&lt;img id=&quot;myImg&quot; src=&quot;cat.jpg&quot; alt=&quot;고양이&quot; width=&quot;200&quot;&gt;
&lt;button onclick=&quot;changeImage()&quot;&gt;이미지 변경&lt;/button&gt;

&lt;script&gt;
  function changeImage() {
    document.getElementById(&quot;myImg&quot;).src = &quot;dog.jpg&quot;;
  }
&lt;/script&gt;</code></pre>
<blockquote>
<p>버튼 클릭 시 이미지가 변경된다 (<code>src</code> 속성 수정).</p>
</blockquote>
<hr>
<h3 id="js로-이미지-생성-및-삽입">JS로 이미지 생성 및 삽입</h3>
<pre><code class="language-html">&lt;button onclick=&quot;addImage()&quot;&gt;이미지 추가&lt;/button&gt;
&lt;div id=&quot;container&quot;&gt;&lt;/div&gt;

&lt;script&gt;
  function addImage() {
    const img = document.createElement(&quot;img&quot;);
    img.src = &quot;https://via.placeholder.com/150&quot;;
    img.alt = &quot;동적으로 생성된 이미지&quot;;
    img.width = 150;

    document.getElementById(&quot;container&quot;).appendChild(img);
  }
&lt;/script&gt;</code></pre>
<blockquote>
<p>버튼을 누르면 이미지가 동적으로 생성되어 화면에 추가된다.</p>
</blockquote>
<hr>
<h3 id="이미지-경로-정리">이미지 경로 정리</h3>
<table>
<thead>
<tr>
<th>경로 유형</th>
<th>예시</th>
</tr>
</thead>
<tbody><tr>
<td>같은 폴더</td>
<td><code>src=&quot;image.jpg&quot;</code></td>
</tr>
<tr>
<td>상위 폴더</td>
<td><code>src=&quot;../image.jpg&quot;</code></td>
</tr>
<tr>
<td>하위 폴더</td>
<td><code>src=&quot;images/image.jpg&quot;</code></td>
</tr>
<tr>
<td>외부 링크</td>
<td><code>src=&quot;https://.../image.jpg&quot;</code></td>
</tr>
</tbody></table>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 실습 프로젝트 모음(1): 기초 DOM 실습]]></title>
            <link>https://velog.io/@emma_lee/JavaScript-6.-%EC%8B%A4%EC%8A%B5-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%AA%A8%EC%9D%8C1-%EA%B8%B0%EC%B4%88-DOM-%EC%8B%A4%EC%8A%B5</link>
            <guid>https://velog.io/@emma_lee/JavaScript-6.-%EC%8B%A4%EC%8A%B5-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%AA%A8%EC%9D%8C1-%EA%B8%B0%EC%B4%88-DOM-%EC%8B%A4%EC%8A%B5</guid>
            <pubDate>Wed, 23 Apr 2025 12:06:23 GMT</pubDate>
            <description><![CDATA[<h2 id="11-태그-생성-실습">11. 태그 생성 실습</h2>
<ul>
<li>버튼 클릭 시 <code>div</code> 영역에 <code>h1</code>, <code>a</code>, <code>ul</code> 태그를 누적 생성한다.</li>
<li>각 버튼은 각기 다른 태그를 생성한다.</li>
<li>코드 구조를 다음 3영역으로 정리한다.</li>
</ul>
<p>1) 요소를 변수에 저장하는 영역<br>2) 함수를 제작하는 영역<br>3) 함수와 태그를 연결하는 영역</p>
<blockquote>
<p>React, Vue, Angular 등 프레임워크는 값이 바뀌면 자동 렌더링되지만,<br>순수 JavaScript에서는 <code>innerHTML</code>, <code>innerText</code> 등을 직접 수정해 반영해야 한다.</p>
</blockquote>
<hr>
<h3 id="코드-예시">코드 예시</h3>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;title&gt;태그 생성 실습&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;h1 id=&quot;text&quot;&gt;클릭해서 태그를 누적 생성&lt;/h1&gt;
  &lt;button id=&quot;btn_h1&quot;&gt;h1태그 생성&lt;/button&gt;
  &lt;button id=&quot;btn_a&quot;&gt;a태그 생성&lt;/button&gt;
  &lt;button id=&quot;btn_ul&quot;&gt;ul태그 생성&lt;/button&gt;
  &lt;div id=&quot;content&quot;&gt;&lt;/div&gt;

  &lt;script&gt;
    let div = document.getElementById(&quot;content&quot;);
    let btn_h1 = document.getElementById(&quot;btn_h1&quot;);
    let btn_a = document.getElementById(&quot;btn_a&quot;);
    let btn_ul = document.getElementById(&quot;btn_ul&quot;);

    const h1 = () =&gt; {
      div.innerHTML += &quot;&lt;h1&gt;h1태그 생성&lt;/h1&gt;&quot;;
    }

    const a = () =&gt; {
      div.innerHTML += &quot;&lt;a href=&#39;#&#39;&gt;a태그 생성&lt;/a&gt;&quot;;
    }

    const ul = () =&gt; {
      div.innerHTML += `
        &lt;ul&gt;
          &lt;li&gt;HTML&lt;/li&gt;
          &lt;li&gt;CSS&lt;/li&gt;
        &lt;/ul&gt;`;
    }

    btn_h1.addEventListener(&quot;click&quot;, h1);
    btn_a.addEventListener(&quot;click&quot;, a);
    btn_ul.addEventListener(&quot;click&quot;, ul);
  &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<hr>
<h3 id="tip">Tip!</h3>
<ul>
<li><code>innerHTML +=</code>로 기존 내용 유지한 채 누적 가능</li>
<li>백틱(``)을 사용하면 가독성 좋은 HTML 작성 가능</li>
<li>요소 생성 후 바로 삽입하지 않으면 렌더링되지 않는다</li>
</ul>
<hr>
<h2 id="12-업다운-실습">12. 업다운 실습</h2>
<ul>
<li><code>+</code> 버튼 클릭 시 숫자가 1씩 증가</li>
<li><code>-</code> 버튼 클릭 시 숫자가 1씩 감소 (단, 0 미만 불가)</li>
</ul>
<h3 id="속성-접근-기본">속성 접근 기본</h3>
<ul>
<li><code>innerText</code>, <code>innerHTML</code> → 텍스트 변경</li>
<li><code>value</code> → 입력값 접근</li>
<li><code>type</code>, <code>src</code>, <code>className</code>, <code>style</code> 등 속성 직접 접근/수정 가능</li>
</ul>
<hr>
<h3 id="코드-예제">코드 예제</h3>
<pre><code class="language-html">&lt;p id=&quot;number&quot;&gt;0&lt;/p&gt;
&lt;button id=&quot;btn_plus&quot;&gt;+&lt;/button&gt;
&lt;button id=&quot;btn_minus&quot;&gt;-&lt;/button&gt;

&lt;script&gt;
  const plus = () =&gt; {
    document.getElementById(&quot;number&quot;).innerText =
      Number(document.getElementById(&quot;number&quot;).innerText) + 1;
  };

  const minus = () =&gt; {
    const current = Number(document.getElementById(&quot;number&quot;).innerText);
    if (current &gt; 0) {
      document.getElementById(&quot;number&quot;).innerText = current - 1;
    }
  };

  document.getElementById(&quot;btn_plus&quot;).addEventListener(&quot;click&quot;, plus);
  document.getElementById(&quot;btn_minus&quot;).addEventListener(&quot;click&quot;, minus);
&lt;/script&gt;</code></pre>
<hr>
<h2 id="13-속성-변경-실습-비밀번호-보이기">13. 속성 변경 실습: 비밀번호 보이기</h2>
<h3 id="목표">목표</h3>
<ul>
<li>버튼 클릭 시 비밀번호 input의 type 속성을 <code>text</code>로 전환 → 비밀번호 노출</li>
<li>한 번 더 클릭 시 다시 <code>password</code>로 변경</li>
</ul>
<pre><code class="language-html">비밀번호: &lt;input type=&quot;password&quot; id=&quot;input&quot;&gt;
&lt;button id=&quot;btn&quot;&gt;비밀번호 보이기&lt;/button&gt;

&lt;script&gt;
  const change_type = () =&gt; {
    const input = document.getElementById(&quot;input&quot;);
    input.type = input.type === &quot;password&quot; ? &quot;text&quot; : &quot;password&quot;;
  }

  document.getElementById(&quot;btn&quot;).addEventListener(&quot;click&quot;, change_type);
&lt;/script&gt;</code></pre>
<hr>
<h2 id="14-복수-요소-처리-실습">14. 복수 요소 처리 실습</h2>
<h3 id="개념">개념</h3>
<ul>
<li><code>getElementsByTagName</code>, <code>getElementsByClassName</code> 등으로 가져온 결과는 <strong>HTMLCollection</strong> (유사 배열)</li>
<li>반복문 가능하지만 <code>map</code>, <code>filter</code>, <code>push</code> 등은 사용 불가</li>
<li>→ <code>Array.from()</code>을 사용해 <strong>배열로 변환</strong> 필요</li>
</ul>
<hr>
<h3 id="코드-예제-1">코드 예제</h3>
<pre><code class="language-html">&lt;ul&gt;
  &lt;li&gt;HTML&lt;/li&gt;
  &lt;li&gt;CSS&lt;/li&gt;
  &lt;li&gt;JS&lt;/li&gt;
&lt;/ul&gt;
&lt;button id=&quot;btn&quot;&gt;li태그 출력&lt;/button&gt;

&lt;script&gt;
  const print = () =&gt; {
    const li = document.getElementsByTagName(&quot;li&quot;);
    for (let i = 0; i &lt; li.length; i++) {
      console.log(li[i].innerText);
    }

    const arr = Array.from(li);
    console.log(&quot;배열 변환:&quot;, arr);
  }

  document.getElementById(&quot;btn&quot;).addEventListener(&quot;click&quot;, print);
&lt;/script&gt;</code></pre>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] DOM & 이벤트: JS로 HTML 제어하기]]></title>
            <link>https://velog.io/@emma_lee/JavaScript-5.-DOM-%EC%9D%B4%EB%B2%A4%ED%8A%B8-JS%EB%A1%9C-HTML-%EC%A0%9C%EC%96%B4%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@emma_lee/JavaScript-5.-DOM-%EC%9D%B4%EB%B2%A4%ED%8A%B8-JS%EB%A1%9C-HTML-%EC%A0%9C%EC%96%B4%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 23 Apr 2025 11:54:03 GMT</pubDate>
            <description><![CDATA[<h2 id="9-dom-document-object-model">9. DOM (Document Object Model)</h2>
<ul>
<li>HTML 문서의 요소를 효과적으로 다루기 위해 모든 요소를 트리 구조로 표현한 모델을 <strong>DOM(Document Object Model)</strong> 이라고 한다.  </li>
<li>JavaScript는 이 DOM을 활용해 HTML 문서의 내용을 조작할 수 있다.</li>
</ul>
<hr>
<h3 id="dom의-개념">DOM의 개념</h3>
<ul>
<li>HTML 문서를 트리 형태로 구조화하여 <strong>태그, 속성, 텍스트</strong>를 객체처럼 다룰 수 있게 만든 구조이다.</li>
<li>최상위 노드는 <code>document</code> 객체이다.</li>
<li>DOM을 통해 HTML 요소에 접근, 수정, 삭제, 생성 가능하다.</li>
</ul>
<hr>
<h3 id="html-문서-읽는-순서">HTML 문서 읽는 순서</h3>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/d18b4495-46c6-45c5-b90e-f3438d51f9c6/image.png" alt="HTML문서 읽는 순서"></p>
<hr>
<h3 id="dom-요소-접근-방법">DOM 요소 접근 방법</h3>
<p>JavaScript에서 DOM 요소에 접근하는 방법은 여러 가지가 있다.</p>
<h4 id="1-요소-자체에-접근">1) 요소 자체에 접근</h4>
<pre><code class="language-javascript">let h1 = document.getElementById(&quot;text&quot;);
console.log(h1);</code></pre>
<h4 id="2-요소의-텍스트만-접근-innertext">2) 요소의 텍스트만 접근 (<code>innerText</code>)</h4>
<pre><code class="language-javascript">let span = document.getElementById(&quot;number&quot;).innerText;
console.log(&quot;innerText:&quot;, span);</code></pre>
<h4 id="3-html-구조-전체-접근-innerhtml">3) HTML 구조 전체 접근 (<code>innerHTML</code>)</h4>
<pre><code class="language-javascript">let spanHtml = document.getElementById(&quot;number&quot;).innerHTML;
console.log(&quot;innerHTML:&quot;, spanHtml);</code></pre>
<blockquote>
<p><code>innerText</code>는 태그를 무시하고 순수 텍스트만,<br><code>innerHTML</code>은 HTML 태그 구조까지 포함하여 인식한다.</p>
</blockquote>
<h4 id="4-요소의-텍스트-수정">4) 요소의 텍스트 수정</h4>
<pre><code class="language-javascript">document.getElementById(&quot;text&quot;).innerText = &quot;변경된 텍스트입니다.&quot;;</code></pre>
<hr>
<h3 id="주의사항">주의사항</h3>
<pre><code class="language-javascript">document.getElementById(&quot;text&quot;).innerText = &quot;&lt;a href=&#39;#&#39;&gt;JS로 변경한 텍스트입니다.&lt;/a&gt;&quot;;
// 출력: &lt;a href=&#39;#&#39;&gt;JS로 변경한 텍스트입니다.&lt;/a&gt;

document.getElementById(&quot;text&quot;).innerHTML = &quot;&lt;a href=&#39;#&#39;&gt;JS로 변경한 텍스트입니다.&lt;/a&gt;&quot;;
// 출력: JS로 변경한 텍스트입니다. (링크 포함)</code></pre>
<ul>
<li><code>innerText</code>: HTML 태그 인식 ❌ (문자 그대로 출력)</li>
<li><code>innerHTML</code>: HTML 구조로 렌더링됨 (태그까지 포함)</li>
</ul>
<hr>
<h3 id="dom-접근-요약">DOM 접근 요약</h3>
<table>
<thead>
<tr>
<th>접근 방식</th>
<th>설명</th>
<th>특징</th>
</tr>
</thead>
<tbody><tr>
<td><code>innerText</code></td>
<td>요소 안의 <strong>텍스트</strong>에 접근</td>
<td>태그 무시</td>
</tr>
<tr>
<td><code>innerHTML</code></td>
<td>요소 안의 <strong>HTML 전체</strong> 접근</td>
<td>태그 인식</td>
</tr>
<tr>
<td><code>getElementById</code></td>
<td>특정 id의 요소 객체에 접근</td>
<td>가장 많이 사용되는 접근 방식</td>
</tr>
</tbody></table>
<hr>
<h2 id="10-이벤트-연결">10. 이벤트 연결</h2>
<p>JavaScript에서 <strong>이벤트(event)</strong>란 사용자의 동작(클릭, 입력 등)에 반응하는 동작을 의미한다.<br>이벤트를 연결하는 방법에는 대표적으로 3가지가 있다.</p>
<hr>
<h3 id="10-1-인라인-방식">10-1. 인라인 방식</h3>
<ul>
<li>태그 안에 직접 <code>onclick</code> 등의 속성으로 함수를 연결</li>
<li>코드가 많아지면 유지보수가 어려워짐</li>
</ul>
<pre><code class="language-javascript">const print = () =&gt; {
  alert(&quot;함수가 실행되었습니다.&quot;);
}</code></pre>
<pre><code class="language-html">&lt;button onclick=&quot;print()&quot;&gt;알림창 출력&lt;/button&gt;</code></pre>
<hr>
<h3 id="10-2-addeventlistener-방식">10-2. addEventListener 방식</h3>
<ul>
<li>JS 코드로 HTML 요소에 이벤트를 연결</li>
<li>함수 호출 시 <code>()</code> 생략 → 즉시 실행 방지</li>
</ul>
<pre><code class="language-javascript">const print = () =&gt; {
  alert(&quot;함수가 실행되었습니다.&quot;);
}

document.getElementById(&quot;btn2&quot;).addEventListener(&quot;click&quot;, print);</code></pre>
<pre><code class="language-html">&lt;button id=&quot;btn2&quot;&gt;분리된 이벤트 실행&lt;/button&gt;</code></pre>
<hr>
<h3 id="10-3-익명-함수-방식">10-3. 익명 함수 방식</h3>
<ul>
<li>함수 선언 없이 이벤트와 동시에 정의</li>
<li>해당 태그에서만 사용하는 이벤트에 적합</li>
</ul>
<pre><code class="language-javascript">document.getElementById(&quot;btn3&quot;).addEventListener(&quot;click&quot;, () =&gt; {
  alert(&quot;나만 쓰는 함수입니다.&quot;);
});</code></pre>
<pre><code class="language-html">&lt;button id=&quot;btn3&quot;&gt;오직 나만 쓰는 함수&lt;/button&gt;</code></pre>
<hr>
<h3 id="전체-예시-코드">전체 예시 코드</h3>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ko&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;title&gt;이벤트 연결 예제&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;button id=&quot;btn1&quot; onclick=&quot;print()&quot;&gt;알림창 출력&lt;/button&gt;
  &lt;button id=&quot;btn2&quot;&gt;분리된 이벤트 실행&lt;/button&gt;
  &lt;button id=&quot;btn3&quot;&gt;오직 나만 쓰는 함수&lt;/button&gt;

  &lt;script&gt;
    // 1. 인라인 방식
    const print = () =&gt; {
      alert(&quot;함수가 실행되었습니다.&quot;);
    }

    // 2. addEventListener 방식
    document.getElementById(&quot;btn2&quot;).addEventListener(&quot;click&quot;, print);

    // 3. 익명 함수 방식
    document.getElementById(&quot;btn3&quot;).addEventListener(&quot;click&quot;, () =&gt; {
      alert(&quot;나만 쓰는 함수입니다.&quot;);
    });
  &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<hr>
<h3 id="tip">Tip!</h3>
<ul>
<li>이벤트 연결 시에는 반드시 <strong>함수가 먼저 선언</strong>된 후에 연결해야 한다.</li>
<li>이벤트명은 대소문자를 구분 (<code>click</code>, <code>keydown</code>, <code>mouseenter</code>, <code>submit</code> 등)한다.</li>
<li><code>onclick</code>, <code>onchange</code> 같은 속성은 HTML 태그에서 직접 사용할 수 있다.</li>
</ul>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 데이터 구조: 객체(Object)와 배열(Array)]]></title>
            <link>https://velog.io/@emma_lee/JavaScript-4.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B5%AC%EC%A1%B0-%EA%B0%9D%EC%B2%B4Object%EC%99%80-%EB%B0%B0%EC%97%B4Array</link>
            <guid>https://velog.io/@emma_lee/JavaScript-4.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B5%AC%EC%A1%B0-%EA%B0%9D%EC%B2%B4Object%EC%99%80-%EB%B0%B0%EC%97%B4Array</guid>
            <pubDate>Wed, 23 Apr 2025 11:50:20 GMT</pubDate>
            <description><![CDATA[<h2 id="8-객체와-배열">8. 객체와 배열</h2>
<p>JavaScript에서 <strong>객체(Object)</strong>와 <strong>배열(Array)</strong>은 데이터를 구조화하고 관리하는 기본 단위이다.<br>객체는 <strong>서로 다른 의미의 데이터</strong>, 배열은 <strong>동일한 성격의 데이터</strong>를 저장하는 데 적합하다.</p>
<hr>
<h3 id="8-1-객체-object">8-1. 객체 (Object)</h3>
<p>Python의 <strong>딕셔너리(dict)</strong>와 유사하며,<br><strong>key-value</strong> 쌍으로 데이터를 저장하는 자료형이다.</p>
<pre><code class="language-javascript">let person = {
  name: &quot;하영&quot;,
  hobby: &quot;발레&quot;,
  gender: &quot;여자&quot;,
  school: [&quot;한국초&quot;, &quot;한국중&quot;, { 전공: &quot;이과&quot;, 구분: &quot;인문계&quot; }]
};</code></pre>
<ul>
<li>키(key)를 통해 값을 조회한다.</li>
<li>중첩된 데이터도 자유롭게 표현할 수 있다.</li>
</ul>
<h4 id="객체의-특징">객체의 특징</h4>
<ul>
<li>의미가 서로 다른 데이터를 저장할 때 적합하다.</li>
<li>객체의 속성은 <code>객체명.키</code> 또는 <code>객체명[&quot;키&quot;]</code> 형태로 접근한다.</li>
<li>데이터 송수신(JSON) 시 주로 사용된다.</li>
</ul>
<pre><code class="language-javascript">console.log(person.name);           // &quot;하영&quot;
console.log(person.school[1]);      // &quot;한국중&quot;
console.log(person.school[2].전공); // &quot;이과&quot;</code></pre>
<hr>
<h3 id="8-2-배열-array">8-2. 배열 (Array)</h3>
<p>JS에서의 배열은 <strong>Python의 리스트(list)</strong>와 유사하며,<br>동일한 성격의 데이터를 순차적으로 나열하는 자료형이다.</p>
<pre><code class="language-javascript">let name = [&quot;정형&quot;, &quot;서보경&quot;, &quot;이도연&quot;, &quot;손지영&quot;];</code></pre>
<h4 id="배열의-특징">배열의 특징</h4>
<ul>
<li>배열의 크기는 <strong>동적</strong>이다.</li>
<li>배열의 크기가 지정되어 있어도 <strong>데이터를 추가하면 저장공간이 자동으로 할당</strong>된다.</li>
<li>배열의 크기는 배열의 length라는 프로퍼티(property)에 저장된다.</li>
<li>모든 타입을 저장할 수 있는 구조이다.</li>
<li>순서가 있는 데이터 집합이다.</li>
<li><code>index</code>로 조회하며, index는 0부터 시작한다.</li>
<li>반복문과 함께 매우 자주 사용된다.</li>
</ul>
<pre><code class="language-javascript">console.log(name[0]);        // &quot;정형&quot;
console.log(name.length);    // 4</code></pre>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/93fadbf9-0285-4f39-b299-fc9d94a78b7e/image.png" alt="array2"></p>
<hr>
<h3 id="배열-메서드-정리">배열 메서드 정리</h3>
<table>
<thead>
<tr>
<th>메서드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>push()</code></td>
<td>배열 끝에 요소 추가</td>
</tr>
<tr>
<td><code>pop()</code></td>
<td>배열 끝 요소 제거</td>
</tr>
<tr>
<td><code>includes()</code></td>
<td>특정 값 포함 여부 확인</td>
</tr>
<tr>
<td><code>indexOf()</code></td>
<td>특정 값의 인덱스 반환</td>
</tr>
<tr>
<td><code>splice()</code></td>
<td>요소 추가 또는 제거</td>
</tr>
<tr>
<td><code>join()</code></td>
<td>배열을 문자열로 결합</td>
</tr>
<tr>
<td><code>slice()</code></td>
<td>배열의 일부분을 잘라서 반환</td>
</tr>
</tbody></table>
<pre><code class="language-javascript">name.push(&quot;Emma&quot;);
console.log(name.includes(&quot;Emma&quot;));  // true</code></pre>
<hr>
<h3 id="객체-vs-배열-비교-요약">객체 vs 배열 비교 요약</h3>
<table>
<thead>
<tr>
<th>항목</th>
<th>객체(Object)</th>
<th>배열(Array)</th>
</tr>
</thead>
<tbody><tr>
<td>구조</td>
<td>키-값(key-value) 구조</td>
<td>순서 기반의 값 모음</td>
</tr>
<tr>
<td>접근 방식</td>
<td><code>obj.key</code> / <code>obj[&quot;key&quot;]</code></td>
<td><code>arr[index]</code></td>
</tr>
<tr>
<td>사용 목적</td>
<td>다양한 속성 데이터 저장</td>
<td>동일한 항목 리스트 저장</td>
</tr>
</tbody></table>
<hr>
<h3 id="예시-복습">예시 복습</h3>
<pre><code class="language-javascript">// 객체 접근 예시
console.log(person.name);            // &quot;하영&quot;
console.log(person.school[2].구분);  // &quot;인문계&quot;

// 배열 접근 예시
console.log(name[0]);                // &quot;정형&quot;</code></pre>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 제어문의 세계: 조건과 반복, 함수]]></title>
            <link>https://velog.io/@emma_lee/JavaScript-3.-%EC%A0%9C%EC%96%B4%EB%AC%B8%EC%9D%98-%EC%84%B8%EA%B3%84-%EC%A1%B0%EA%B1%B4%EA%B3%BC-%EB%B0%98%EB%B3%B5-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@emma_lee/JavaScript-3.-%EC%A0%9C%EC%96%B4%EB%AC%B8%EC%9D%98-%EC%84%B8%EA%B3%84-%EC%A1%B0%EA%B1%B4%EA%B3%BC-%EB%B0%98%EB%B3%B5-%ED%95%A8%EC%88%98</guid>
            <pubDate>Wed, 23 Apr 2025 11:42:08 GMT</pubDate>
            <description><![CDATA[<h2 id="6-조건문과-반복문">6. 조건문과 반복문</h2>
<p>JavaScript에서 프로그램의 흐름을 제어할 때 사용하는 대표적인 문법은 <strong>조건문</strong>과 <strong>반복문</strong>이다.<br>사용자의 입력, 조건에 따라 실행 분기나 반복을 구성할 수 있으며, 동적 로직 구현에 필수적이다.</p>
<hr>
<h3 id="6-1-조건문">6-1. 조건문</h3>
<p>조건에 따라 코드 실행 흐름을 달리하고 싶을 때 사용한다.</p>
<h4 id="if--else-if--else">if / else if / else</h4>
<pre><code class="language-javascript">let score = 85;

if (score &gt;= 90) {
  console.log(&quot;A&quot;);
} else if (score &gt;= 80) {
  console.log(&quot;B&quot;);
} else {
  console.log(&quot;C&quot;);
}</code></pre>
<h4 id="switch-문">switch 문</h4>
<pre><code class="language-javascript">let fruit = &quot;apple&quot;;

switch (fruit) {
  case &quot;apple&quot;:
    console.log(&quot;사과입니다&quot;);
    break;
  case &quot;banana&quot;:
    console.log(&quot;바나나입니다&quot;);
    break;
  default:
    console.log(&quot;알 수 없는 과일입니다&quot;);
}</code></pre>
<blockquote>
<p><code>break</code>를 쓰지 않으면 다음 case까지 실행됨에 주의!</p>
</blockquote>
<hr>
<h3 id="6-2-반복문">6-2. 반복문</h3>
<p>같은 작업을 여러 번 반복하고 싶을 때 사용한다.</p>
<h4 id="for문">for문</h4>
<pre><code class="language-javascript">for (let i = 0; i &lt; 5; i++) {
  console.log(i);
}</code></pre>
<h4 id="forof-배열-전용">for...of (배열 전용)</h4>
<pre><code class="language-javascript">let arr = [1, 2, 3];

for (let num of arr) {
  console.log(num);
}</code></pre>
<h4 id="forin-객체-전용">for...in (객체 전용)</h4>
<pre><code class="language-javascript">let person = { name: &quot;Emma&quot;, age: 25 };

for (let key in person) {
  console.log(`${key}: ${person[key]}`);
}</code></pre>
<hr>
<h4 id="while문">while문</h4>
<pre><code class="language-javascript">let i = 0;
while (i &lt; 3) {
  console.log(i);
  i++;
}</code></pre>
<h4 id="do-while문">do-while문</h4>
<pre><code class="language-javascript">let i = 0;
do {
  console.log(i);
  i++;
} while (i &lt; 3);</code></pre>
<hr>
<h3 id="break--continue">break / continue</h3>
<ul>
<li><code>break</code> : 반복문을 <strong>즉시 종료</strong></li>
<li><code>continue</code> : 다음 반복으로 <strong>건너뛰기</strong></li>
</ul>
<pre><code class="language-javascript">for (let i = 1; i &lt;= 5; i++) {
  if (i === 3) continue;
  if (i === 5) break;
  console.log(i);  // 1, 2, 4
}</code></pre>
<hr>
<h2 id="7-함수-function">7. 함수 (Function)</h2>
<p>함수는 <strong>특정 작업을 수행하는 코드 블록</strong>으로, <strong>재사용성</strong>, <strong>유지보수성</strong>, <strong>가독성</strong>을 높이기 위해 사용된다.</p>
<hr>
<h3 id="7-1-함수란">7-1. 함수란?</h3>
<ul>
<li>특정 기능을 하나로 묶은 코드 단위</li>
<li>JS 함수는 매개변수 타입이나 개수에 제약이 없음</li>
<li>인자의 개수가 부족하면 <code>undefined</code>, 초과 인자는 무시됨</li>
</ul>
<pre><code class="language-javascript">let data;           // undefined
let data2 = null;   // null</code></pre>
<h4 id="예시">예시</h4>
<pre><code class="language-javascript">function add(num1, num2) {
  console.log(num1, num2);
}

add(1);          // 1 undefined
add(1, null);    // 1 null
add(1, 2, 4);    // 1 2 (초과 인자 무시)</code></pre>
<hr>
<h3 id="7-2-함수-정의-방법">7-2. 함수 정의 방법</h3>
<p>JavaScript에서 함수를 정의하는 방법은 대표적으로 2가지가 있다.</p>
<h4 id="기본-함수-선언-방식">기본 함수 선언 방식</h4>
<pre><code class="language-javascript">function add(num1, num2) {
  return num1 + num2;
}

console.log(add(3, 5));  // 8</code></pre>
<ul>
<li><code>function 함수명(매개변수) { ... }</code></li>
<li>가장 전통적인 함수 선언 방식</li>
<li><strong>호이스팅</strong>(코드 선언보다 위에서 호출 가능) 지원</li>
</ul>
<h4 id="화살표-함수-arrow-function">화살표 함수 (Arrow Function)</h4>
<pre><code class="language-javascript">const minus = (a, b) =&gt; {
  return a - b;
};

console.log(minus(7, 2)); // 5</code></pre>
<ul>
<li><code>const 함수명 = (매개변수) =&gt; { 실행 코드 }</code></li>
<li>한 줄인 경우 중괄호와 return 생략 가능</li>
</ul>
<pre><code class="language-javascript">const square = x =&gt; x * x;
console.log(square(4));  // 16</code></pre>
<ul>
<li><strong>익명 함수</strong>로 정의되며 변수에 할당</li>
<li><strong>this 바인딩 없음</strong>, 객체 내부 메서드로 사용 시 주의</li>
</ul>
<hr>
<h3 id="함수-정의-비교-요약표">함수 정의 비교 요약표</h3>
<table>
<thead>
<tr>
<th>구분</th>
<th>선언 방식</th>
<th>호출 방식</th>
<th>특징</th>
</tr>
</thead>
<tbody><tr>
<td>기본 함수</td>
<td><code>function fn()</code></td>
<td><code>fn()</code></td>
<td>호이스팅됨, 일반 함수</td>
</tr>
<tr>
<td>화살표 함수</td>
<td><code>const fn = () =&gt; {}</code></td>
<td><code>fn()</code></td>
<td>호이스팅 안 됨, this 바인딩 없음</td>
</tr>
</tbody></table>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 자료형부터 연산까지]]></title>
            <link>https://velog.io/@emma_lee/JavaScript-2.-%EC%9E%90%EB%A3%8C%ED%98%95%EB%B6%80%ED%84%B0-%EC%97%B0%EC%82%B0%EA%B9%8C%EC%A7%80-ptdcpejg</link>
            <guid>https://velog.io/@emma_lee/JavaScript-2.-%EC%9E%90%EB%A3%8C%ED%98%95%EB%B6%80%ED%84%B0-%EC%97%B0%EC%82%B0%EA%B9%8C%EC%A7%80-ptdcpejg</guid>
            <pubDate>Wed, 23 Apr 2025 11:36:55 GMT</pubDate>
            <description><![CDATA[<h2 id="4-자료형-data-types">4. 자료형 (Data Types)</h2>
<p>JavaScript는 다양한 데이터 타입을 제공하며, <strong>동적 타이핑(dynamic typing)</strong> 언어로, 변수에 저장되는 값의 타입이 <strong>실행 중(runtime)에 자동으로 결정</strong>된다.</p>
<hr>
<h3 id="기본-데이터-타입">기본 데이터 타입</h3>
<table>
<thead>
<tr>
<th>타입명</th>
<th>설명</th>
<th>예시</th>
</tr>
</thead>
<tbody><tr>
<td><code>Number</code></td>
<td>정수와 실수를 포함한 숫자형</td>
<td><code>1</code>, <code>3.14</code>, <code>-10</code></td>
</tr>
<tr>
<td><code>String</code></td>
<td>문자열</td>
<td><code>&quot;Hello&quot;</code>, <code>&#39;123&#39;</code></td>
</tr>
<tr>
<td><code>Boolean</code></td>
<td>참 또는 거짓</td>
<td><code>true</code>, <code>false</code></td>
</tr>
<tr>
<td><code>Array</code></td>
<td>순서가 있는 값들의 리스트</td>
<td><code>[1, 2, 3]</code></td>
</tr>
<tr>
<td><code>Object</code></td>
<td>키-값 쌍으로 구성된 구조체</td>
<td><code>{ name: &quot;Emma&quot; }</code></td>
</tr>
<tr>
<td><code>Null</code></td>
<td>의도적으로 비워진 값</td>
<td><code>null</code></td>
</tr>
<tr>
<td><code>Undefined</code></td>
<td>값이 할당되지 않은 상태</td>
<td><code>undefined</code></td>
</tr>
</tbody></table>
<blockquote>
<p>✅ JavaScript에서는 정수와 실수를 <strong>모두 <code>Number</code> 타입</strong>으로 처리한다.</p>
</blockquote>
<hr>
<h3 id="자동-형변환-type-coercion">자동 형변환 (Type Coercion)</h3>
<p>JavaScript는 연산자에 따라 값의 타입을 자동으로 변환하기도 한다.</p>
<table>
<thead>
<tr>
<th>연산자</th>
<th>동작 방식</th>
<th>예시</th>
</tr>
</thead>
<tbody><tr>
<td><code>+</code></td>
<td>문자열이 포함되면 문자열로 변환</td>
<td><code>&quot;3&quot; + 2 → &quot;32&quot;</code></td>
</tr>
<tr>
<td><code>-</code>, <code>*</code>, <code>/</code>, <code>&lt;</code>, <code>&gt;</code></td>
<td>숫자형으로 변환하여 계산</td>
<td><code>&quot;5&quot; - 1 → 4</code></td>
</tr>
</tbody></table>
<blockquote>
<p><code>+</code>는 문자열 우선, 나머지 연산자는 숫자 우선!</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/b7f1b008-3a7c-40cb-a093-f49757dd5690/image.png" alt="자동형변환"></p>
<blockquote>
<p>⚠️ <code>==</code>과 <code>!=</code>은 형변환이 일어나므로 <strong>예상치 못한 결과</strong>가 나올 수 있다.<br>→ <strong>항상 <code>===</code>, <code>!==</code>를 사용하는 것이 안전한 Best Practice</strong>이다.</p>
</blockquote>
<hr>
<h3 id="명시적-형변환-type-casting">명시적 형변환 (Type Casting)</h3>
<h4 id="문자열-→-숫자">문자열 → 숫자</h4>
<pre><code class="language-javascript">Number(&quot;123&quot;);     // 123
parseInt(&quot;3.14&quot;);  // 3
parseFloat(&quot;3.14&quot;);// 3.14</code></pre>
<h4 id="숫자-→-문자열">숫자 → 문자열</h4>
<pre><code class="language-javascript">String(123);       // &quot;123&quot;
(123).toString();  // &quot;123&quot;</code></pre>
<hr>
<h2 id="5-연산자와-표현식">5. 연산자와 표현식</h2>
<ul>
<li>JavaScript의 연산자는 값을 계산하거나 조건을 비교할 때 사용된다.  </li>
<li>대표적으로 <strong>산술 연산자, 대입 연산자, 비교 연산자, 논리 연산자, 삼항 연산자</strong>가 있다.</li>
</ul>
<hr>
<h3 id="산술-연산자-arithmetic-operators">산술 연산자 (Arithmetic Operators)</h3>
<table>
<thead>
<tr>
<th>연산자</th>
<th>설명</th>
<th>예시</th>
<th>결과</th>
</tr>
</thead>
<tbody><tr>
<td><code>+</code></td>
<td>더하기</td>
<td>5 + 2</td>
<td>7</td>
</tr>
<tr>
<td><code>-</code></td>
<td>빼기</td>
<td>5 - 2</td>
<td>3</td>
</tr>
<tr>
<td><code>*</code></td>
<td>곱하기</td>
<td>5 * 2</td>
<td>10</td>
</tr>
<tr>
<td><code>/</code></td>
<td>나누기</td>
<td>10 / 2</td>
<td>5</td>
</tr>
<tr>
<td><code>%</code></td>
<td>나머지</td>
<td>10 % 3</td>
<td>1</td>
</tr>
<tr>
<td><code>**</code></td>
<td>거듭제곱</td>
<td>2 ** 3</td>
<td>8</td>
</tr>
</tbody></table>
<pre><code class="language-javascript">console.log(5 + 2);    // 7
console.log(10 % 3);   // 1
console.log(2 ** 4);   // 16</code></pre>
<hr>
<h3 id="대입-연산자-assignment-operators">대입 연산자 (Assignment Operators)</h3>
<table>
<thead>
<tr>
<th>연산자</th>
<th>설명</th>
<th>예시</th>
<th>결과</th>
</tr>
</thead>
<tbody><tr>
<td><code>=</code></td>
<td>값 할당</td>
<td>a = 10</td>
<td>10</td>
</tr>
<tr>
<td><code>+=</code></td>
<td>더한 후 할당</td>
<td>a += 5</td>
<td>a = a + 5</td>
</tr>
<tr>
<td><code>-=</code></td>
<td>뺀 후 할당</td>
<td>a -= 3</td>
<td>a = a - 3</td>
</tr>
<tr>
<td><code>*=</code></td>
<td>곱한 후 할당</td>
<td>a *= 2</td>
<td>a = a * 2</td>
</tr>
<tr>
<td><code>/=</code></td>
<td>나눈 후 할당</td>
<td>a /= 2</td>
<td>a = a / 2</td>
</tr>
<tr>
<td><code>%=</code></td>
<td>나머지 후 할당</td>
<td>a %= 3</td>
<td>a = a % 3</td>
</tr>
</tbody></table>
<pre><code class="language-javascript">let a = 10;
a += 5;  // 15
a *= 2;  // 30</code></pre>
<hr>
<h3 id="비교-연산자-comparison-operators">비교 연산자 (Comparison Operators)</h3>
<table>
<thead>
<tr>
<th>연산자</th>
<th>설명</th>
<th>예시</th>
<th>결과</th>
</tr>
</thead>
<tbody><tr>
<td><code>==</code></td>
<td>값이 같음 (느슨한 비교)</td>
<td>5 == &quot;5&quot;</td>
<td>true</td>
</tr>
<tr>
<td><code>===</code></td>
<td>값과 타입 모두 같음</td>
<td>5 === &quot;5&quot;</td>
<td>false</td>
</tr>
<tr>
<td><code>!=</code></td>
<td>값이 다름 (느슨한 비교)</td>
<td>5 != &quot;5&quot;</td>
<td>false</td>
</tr>
<tr>
<td><code>!==</code></td>
<td>값 또는 타입이 다름</td>
<td>5 !== &quot;5&quot;</td>
<td>true</td>
</tr>
<tr>
<td><code>&gt;</code></td>
<td>크다</td>
<td>7 &gt; 5</td>
<td>true</td>
</tr>
<tr>
<td><code>&lt;</code></td>
<td>작다</td>
<td>3 &lt; 5</td>
<td>true</td>
</tr>
<tr>
<td><code>&gt;=</code></td>
<td>크거나 같다</td>
<td>5 &gt;= 5</td>
<td>true</td>
</tr>
<tr>
<td><code>&lt;=</code></td>
<td>작거나 같다</td>
<td>4 &lt;= 2</td>
<td>false</td>
</tr>
</tbody></table>
<pre><code class="language-javascript">console.log(5 == &quot;5&quot;);    // true
console.log(5 === &quot;5&quot;);   // false</code></pre>
<hr>
<h3 id="논리-연산자-logical-operators">논리 연산자 (Logical Operators)</h3>
<table>
<thead>
<tr>
<th>연산자</th>
<th>설명</th>
<th>예시</th>
<th>결과</th>
</tr>
</thead>
<tbody><tr>
<td>AND</td>
<td>양쪽 모두 true면 true</td>
<td>true &amp;&amp; false</td>
<td>false</td>
</tr>
<tr>
<td>OR</td>
<td>하나라도 true면 true</td>
<td>false or true</td>
<td>true</td>
</tr>
<tr>
<td>NOT</td>
<td>논리값 반전</td>
<td>!true</td>
<td>false</td>
</tr>
</tbody></table>
<blockquote>
<p>AND == <code>&amp;&amp;</code>
OR == <code>||</code>
NOR == <code>!</code>
사실 이 내용을 표 안에 넣고 싶었는데, 표 마크다운 할 때 <code>|</code> 이 기호가 자꾸 표로 인식돼서 넣기 실패했다 ㅠ.. 이스케이프 코드도 안먹는데 방법 아시는 분?</p>
</blockquote>
<pre><code class="language-javascript">let a = true;
let b = false;
console.log(a &amp;&amp; b);   // false
console.log(a || b);   // true
console.log(!a);       // false</code></pre>
<hr>
<h3 id="삼항-연산자-ternary-operator">삼항 연산자 (Ternary Operator)</h3>
<p>조건에 따라 값을 구분할 수 있는 간단한 연산자이다.<br>형식: <code>조건 ? 참일 때 값 : 거짓일 때 값</code></p>
<pre><code class="language-javascript">let score = 85;
let result = score &gt;= 60 ? &quot;합격&quot; : &quot;불합격&quot;;
console.log(result);  // &quot;합격&quot;</code></pre>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] JS 기초: 개념·입출력·변수]]></title>
            <link>https://velog.io/@emma_lee/JavaScript-1.-JS-%EA%B8%B0%EC%B4%88-%EA%B0%9C%EB%85%90%EC%9E%85%EC%B6%9C%EB%A0%A5%EB%B3%80%EC%88%98</link>
            <guid>https://velog.io/@emma_lee/JavaScript-1.-JS-%EA%B8%B0%EC%B4%88-%EA%B0%9C%EB%85%90%EC%9E%85%EC%B6%9C%EB%A0%A5%EB%B3%80%EC%88%98</guid>
            <pubDate>Wed, 23 Apr 2025 08:47:40 GMT</pubDate>
            <description><![CDATA[<h2 id="1-javascript란">1. JavaScript란?</h2>
<ul>
<li><p>JavaScript는 웹 브라우저에서 동작하는 <strong>프로그래밍 언어</strong>로,<br>웹 페이지를 <strong>동적으로 제어</strong>하기 위해 만들어졌다.</p>
</li>
<li><p>HTML과 CSS로 구성된 <strong>정적인 웹페이지</strong>에  
→ <strong>인터랙티브한 기능</strong>을 추가할 수 있다.</p>
</li>
<li><p>예를 들어:</p>
<ul>
<li>알림창 띄우기  </li>
<li>이미지 슬라이드  </li>
<li>버튼 클릭 시 이벤트 처리  </li>
<li>사용자 입력값에 따라 화면 변화 등</li>
</ul>
</li>
</ul>
<blockquote>
<p>✅ JavaScript는 웹사이트에 생명력을 불어넣는 역할을 한다.</p>
</blockquote>
<hr>
<h3 id="javascript의-역사">JavaScript의 역사</h3>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/3c24f45a-bb24-448e-a140-236130184436/image.png" alt="history"></p>
<ul>
<li>1995년, 넷스케이프(Netscape)에서 <strong>Brendan Eich</strong>가 처음 개발했다.</li>
<li>초기에는 <strong>LiveScript</strong>라는 이름이었으나, Java의 인기에 편승해 <strong>JavaScript</strong>로 개명되었다.</li>
<li>본래 브라우저 내에서만 작동했지만, <strong>Node.js</strong>가 등장하면서 서버 개발 영역까지 확장되었다.</li>
</ul>
<blockquote>
<p>💡 JavaScript는 Java와 이름만 비슷할 뿐, 완전히 다른 언어이다.</p>
</blockquote>
<hr>
<h3 id="javascript의-활용-분야">JavaScript의 활용 분야</h3>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/6a6e370a-c806-4f93-a439-340450af0103/image.png" alt="use"></p>
<p>JavaScript는 이제 <strong>웹 프론트엔드</strong>를 넘어  <strong>앱 개발, 서버, 데이터 시각화, IoT</strong> 등 다양한 분야에서 활용된다.</p>
<ul>
<li><strong>웹 프론트엔드</strong> : React, Vue, Angular</li>
<li><strong>모바일 앱</strong> : React Native, Ionic</li>
<li><strong>서버 개발</strong> : Node.js, Express</li>
<li><strong>데스크탑 앱</strong> : Electron</li>
<li><strong>데이터 시각화</strong> : D3.js, Chart.js</li>
<li><strong>게임 / IoT 개발</strong> : Phaser, Johnny-Five 등</li>
</ul>
<blockquote>
<p>🎯 과거엔 브라우저 전용이었지만, 지금은 전방위 개발에 활용되는 범용 언어다.</p>
</blockquote>
<hr>
<h3 id="javascript의-주요-특징">JavaScript의 주요 특징</h3>
<ol>
<li><strong>브라우저에서 실행 가능한 유일한 언어</strong></li>
<li><strong>Node.js</strong>를 통해 서버 개발까지 가능</li>
<li><strong>다양한 프레임워크 및 생태계</strong>와 호환</li>
<li><strong>빠르고 유연한 개발 환경</strong></li>
<li><strong>동적 타이핑 언어</strong>로 프로토타입 개발에 유리</li>
<li><strong>호이스팅, 클로저, 이벤트 루프</strong> 등 고유한 특징 보유</li>
</ol>
<blockquote>
<p>JavaScript는 웹을 넘어 모든 플랫폼을 아우르는 <strong>다재다능한 언어</strong>다.</p>
</blockquote>
<hr>
<h2 id="2-입력과-출력-in-javascript">2. 입력과 출력 in JavaScript</h2>
<h3 id="입력-input">입력 (Input)</h3>
<h4 id="prompttext-입력-예시"><code>prompt(&quot;text&quot;, &quot;입력 예시&quot;)</code></h4>
<ul>
<li>사용자의 <strong>텍스트 입력</strong>을 받아오는 창을 띄운다.</li>
<li>반환값은 <strong>항상 문자열(String)</strong>이다.</li>
</ul>
<pre><code class="language-javascript">let birth = prompt(&quot;생년월일을 입력하세요&quot;, &quot;Ex)YYMMDD&quot;);</code></pre>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/60d9839b-6725-4e2b-b877-38cb40ed4308/image.png" alt="prompt"></p>
<h4 id="confirmtext"><code>confirm(&quot;text&quot;)</code></h4>
<ul>
<li><strong>확인 / 취소 버튼</strong>이 있는 팝업창을 띄운다.</li>
<li>반환값은 <strong>Boolean(true / false)</strong>이다.</li>
</ul>
<pre><code class="language-javascript">let isDelete = confirm(&quot;정말 삭제하시겠습니까?&quot;);</code></pre>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/75379f03-4ba2-422e-9725-8d2350185846/image.png" alt="confirm"></p>
<hr>
<h3 id="출력-output">출력 (Output)</h3>
<h4 id="documentwritetext"><code>document.write(&quot;text&quot;)</code></h4>
<pre><code class="language-javascript">document.write(&quot;Hello JavaScript!&quot;);</code></pre>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/5cfbeb2a-c739-424b-98a9-c116e498ddf2/image.png" alt="document"></p>
<h4 id="consolelogtext"><code>console.log(&quot;text&quot;)</code></h4>
<pre><code class="language-javascript">console.log(&quot;로그 출력&quot;);</code></pre>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/819f64a0-0f02-4825-88de-08abf7442abc/image.png" alt="console"></p>
<h4 id="alerttext"><code>alert(&quot;text&quot;)</code></h4>
<pre><code class="language-javascript">alert(&quot;작업이 완료되었습니다!&quot;);</code></pre>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/194e4ce2-3204-4bc1-935f-4811899f2e80/image.png" alt="alert"></p>
<hr>
<h2 id="3-변수-선언-방식">3. 변수 선언 방식</h2>
<h3 id="var"><code>var</code></h3>
<pre><code class="language-javascript">var a = 10;
var a = 20;
console.log(a); // 20</code></pre>
<h3 id="let"><code>let</code></h3>
<pre><code class="language-javascript">let b = 30;
b = 40;
console.log(b); // 40</code></pre>
<h3 id="const"><code>const</code></h3>
<pre><code class="language-javascript">const c = 100;
const user = { name: &quot;Emma&quot; };
user.name = &quot;HY&quot;;
console.log(user);</code></pre>
<hr>
<h3 id="변수-선언-방식-요약">변수 선언 방식 요약</h3>
<table>
<thead>
<tr>
<th>구분</th>
<th>재선언</th>
<th>재할당</th>
<th>스코프</th>
<th>사용 권장</th>
</tr>
</thead>
<tbody><tr>
<td><code>var</code></td>
<td>가능</td>
<td>가능</td>
<td>함수 스코프</td>
<td>❌ 지양됨</td>
</tr>
<tr>
<td><code>let</code></td>
<td>불가</td>
<td>가능</td>
<td>블록 스코프</td>
<td>✅ 기본 변수</td>
</tr>
<tr>
<td><code>const</code></td>
<td>불가</td>
<td>불가</td>
<td>블록 스코프</td>
<td>✅ 불변값</td>
</tr>
</tbody></table>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Flutter] 위젯(Widget) 총정리]]></title>
            <link>https://velog.io/@emma_lee/Flutter-4.-%EC%9C%84%EC%A0%AF-Widget</link>
            <guid>https://velog.io/@emma_lee/Flutter-4.-%EC%9C%84%EC%A0%AF-Widget</guid>
            <pubDate>Wed, 23 Apr 2025 06:31:06 GMT</pubDate>
            <description><![CDATA[<h1 id="flutter-위젯">Flutter 위젯</h1>
<ul>
<li>Flutter 개발에서 가장 핵심이 되는 개념은 <strong>&quot;위젯(Widget)&quot;</strong>이다.  </li>
<li>이 글에서는 위젯의 정의부터 기본 UI 구성, 상태 관리, 레이아웃까지 <strong>실무에 필요한 위젯 개념 전체를 정리</strong>한다.</li>
</ul>
<hr>
<h2 id="1-위젯widget이란">1. 위젯(Widget)이란?</h2>
<ul>
<li>Flutter의 모든 요소는 위젯이다.  </li>
<li>버튼, 텍스트, 이미지, 입력창 등 UI를 구성하는 모든 구성 요소가 위젯이며, 개발자는 이 위젯들을 조합해 앱을 만든다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/fc860f45-ea4d-49ef-8d54-24183c9c7d8a/image.png" alt=""></p>
<hr>
<h2 id="2-stateless-vs-stateful">2. Stateless vs Stateful</h2>
<h3 id="stateless-widget-변하지-않는-ui">Stateless Widget (변하지 않는 UI)</h3>
<ul>
<li>상태가 없고, 화면이 <strong>한 번 렌더링되면 바뀌지 않는 UI</strong>이다.</li>
<li>예: 아이콘, 제목, 고정된 텍스트</li>
</ul>
<pre><code class="language-dart">class MyText extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text(&#39;나는 Stateless 위젯!&#39;);
  }
}</code></pre>
<hr>
<h3 id="stateful-widget-상태가-바뀌는-ui">Stateful Widget (상태가 바뀌는 UI)</h3>
<ul>
<li>사용자의 입력이나 앱 상태에 따라 <strong>화면이 다시 그려지는 위젯</strong>이다.</li>
<li><code>setState()</code>를 사용해 상태를 갱신해야 화면이 업데이트된다.</li>
</ul>
<pre><code class="language-dart">class CounterWidget extends StatefulWidget {
  @override
  _CounterWidgetState createState() =&gt; _CounterWidgetState();
}

class _CounterWidgetState extends State&lt;CounterWidget&gt; {
  int counter = 0;

  void _increment() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text(&#39;카운터: $counter&#39;),
        ElevatedButton(
          onPressed: _increment,
          child: Text(&#39;증가하기&#39;),
        ),
      ],
    );
  }
}</code></pre>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/f906fbdc-c42c-4643-8770-ff0408ad2643/image.png" alt=""></p>
<hr>
<h2 id="3-scaffold">3. Scaffold</h2>
<h3 id="scaffold란">Scaffold란?</h3>
<ul>
<li>Scaffold는 Flutter에서 Material Design 기반 앱의 기본 레이아웃 구조를 제공하는 위젯으로, 거의 모든 Flutter 앱에서 사용된다.</li>
<li>화면의 상단, 하단, 본문, 플로팅 버튼 등 <strong>UI의 기본 틀을 구성</strong>할 수 있도록 돕는다.</li>
</ul>
<pre><code class="language-dart">Scaffold(
  appBar: AppBar(title: Text(&#39;앱 타이틀&#39;)),
  body: Center(child: Text(&#39;여기는 본문 영역&#39;)),
  floatingActionButton: FloatingActionButton(
    onPressed: () {},
    child: Icon(Icons.add),
  ),
)</code></pre>
<blockquote>
<p><code>appBar</code>, <code>body</code>, <code>drawer</code>, <code>bottomNavigationBar</code> 등 다양한 영역을 정의할 수 있다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/emma_lee/post/6ea00398-6531-40e2-85a7-4582664c3d64/image.png" alt=""></p>
<hr>
<h3 id="scaffold-주요-속성-정리">Scaffold 주요 속성 정리</h3>
<table>
<thead>
<tr>
<th>속성</th>
<th>설명</th>
<th>예시 코드</th>
</tr>
</thead>
<tbody><tr>
<td><code>appBar</code></td>
<td>상단 앱 바 영역</td>
<td><code>AppBar(title: Text(&#39;제목&#39;))</code></td>
</tr>
<tr>
<td><code>body</code></td>
<td>메인 콘텐츠 영역</td>
<td><code>Center(child: Text(&#39;본문&#39;))</code></td>
</tr>
<tr>
<td><code>floatingActionButton</code></td>
<td>오른쪽 하단 플로팅 버튼</td>
<td><code>FloatingActionButton(...)</code></td>
</tr>
<tr>
<td><code>drawer</code></td>
<td>좌측 사이드 메뉴 (햄버거 메뉴)</td>
<td><code>Drawer(child: ListView(...))</code></td>
</tr>
<tr>
<td><code>endDrawer</code></td>
<td>우측 사이드 메뉴</td>
<td><code>Drawer(...)</code></td>
</tr>
<tr>
<td><code>bottomNavigationBar</code></td>
<td>하단 탭 메뉴</td>
<td><code>BottomNavigationBar(...)</code></td>
</tr>
<tr>
<td><code>bottomSheet</code></td>
<td>하단 고정 시트</td>
<td><code>Container(height: 60, child: Text(...))</code></td>
</tr>
<tr>
<td><code>backgroundColor</code></td>
<td>Scaffold 배경 색상</td>
<td><code>backgroundColor: Colors.grey[100]</code></td>
</tr>
<tr>
<td><code>persistentFooterButtons</code></td>
<td>하단 고정 버튼 리스트</td>
<td><code>persistentFooterButtons: [Button(...)]</code></td>
</tr>
</tbody></table>
<hr>
<h2 id="4-기본-ui-위젯-정리">4. 기본 UI 위젯 정리</h2>
<h3 id="text">Text</h3>
<pre><code class="language-dart">Text(&#39;안녕하세요!&#39;, style: TextStyle(fontSize: 20))</code></pre>
<h3 id="container">Container</h3>
<pre><code class="language-dart">Container(
  width: 100,
  height: 50,
  color: Colors.amber,
  child: Text(&#39;박스&#39;),
)</code></pre>
<h3 id="image">Image</h3>
<pre><code class="language-dart">Image.asset(&#39;assets/logo.png&#39;)
Image.network(&#39;https://flutter.dev/images/flutter-logo-sharing.png&#39;)</code></pre>
<h3 id="icon">Icon</h3>
<pre><code class="language-dart">Icon(Icons.favorite, color: Colors.red)</code></pre>
<h3 id="elevatedbutton">ElevatedButton</h3>
<pre><code class="language-dart">ElevatedButton(onPressed: () {}, child: Text(&#39;클릭&#39;))</code></pre>
<h3 id="textfield">TextField</h3>
<pre><code class="language-dart">TextField(decoration: InputDecoration(labelText: &#39;입력하세요&#39;))</code></pre>
<hr>
<h2 id="5-레이아웃-위젯">5. 레이아웃 위젯</h2>
<h3 id="↔️-row--↕️-column">↔️ Row / ↕️ Column</h3>
<pre><code class="language-dart">Row(
  mainAxisAlignment: MainAxisAlignment.spaceAround,
  children: [Text(&#39;A&#39;), Text(&#39;B&#39;), Text(&#39;C&#39;)],
)

Column(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [Text(&#39;첫 번째&#39;), Text(&#39;두 번째&#39;)],
)</code></pre>
<h3 id="padding">Padding</h3>
<pre><code class="language-dart">Padding(
  padding: EdgeInsets.all(16.0),
  child: Text(&#39;패딩이 들어간 텍스트&#39;),
)</code></pre>
<h3 id="sizedbox">SizedBox</h3>
<pre><code class="language-dart">SizedBox(width: 20, height: 50)</code></pre>
<blockquote>
<p>여백을 주거나 크기를 지정할 때 사용</p>
</blockquote>
<h3 id="expanded">Expanded</h3>
<pre><code class="language-dart">Row(
  children: [
    Expanded(child: Container(color: Colors.red)),
    Expanded(child: Container(color: Colors.blue)),
  ],
)</code></pre>
<blockquote>
<p>남은 공간을 위젯 간에 비율로 배분</p>
</blockquote>
<h3 id="align--center">Align / Center</h3>
<pre><code class="language-dart">Align(alignment: Alignment.bottomRight, child: Text(&#39;오른쪽 아래&#39;))
Center(child: Text(&#39;가운데&#39;))</code></pre>
<h3 id="stack">Stack</h3>
<pre><code class="language-dart">Stack(
  children: [
    Container(width: 200, height: 200, color: Colors.green),
    Positioned(top: 50, left: 50, child: Text(&#39;겹친 텍스트&#39;)),
  ],
)</code></pre>
<blockquote>
<p>위젯을 겹쳐서 배치할 수 있음</p>
</blockquote>
<hr>
<h2 id="6-기타-유용한-위젯들">6. 기타 유용한 위젯들</h2>
<h3 id="listview-스크롤-가능한-목록">ListView (스크롤 가능한 목록)</h3>
<pre><code class="language-dart">ListView(
  children: [
    ListTile(title: Text(&#39;항목 1&#39;)),
    ListTile(title: Text(&#39;항목 2&#39;)),
  ],
)</code></pre>
<h3 id="gridview-그리드-형태-목록">GridView (그리드 형태 목록)</h3>
<pre><code class="language-dart">GridView.count(
  crossAxisCount: 2,
  children: List.generate(4, (index) =&gt; Text(&#39;아이템 $index&#39;)),
)</code></pre>
<h3 id="gesturedetector-제스처-인식">GestureDetector (제스처 인식)</h3>
<pre><code class="language-dart">GestureDetector(
  onTap: () {
    print(&#39;탭됨!&#39;);
  },
  child: Container(color: Colors.blue, child: Text(&#39;탭해보세요&#39;)),
)</code></pre>
<hr>
<h2 id="요약표">요약표</h2>
<table>
<thead>
<tr>
<th>카테고리</th>
<th>대표 위젯</th>
</tr>
</thead>
<tbody><tr>
<td>텍스트</td>
<td><code>Text</code>, <code>TextField</code></td>
</tr>
<tr>
<td>이미지</td>
<td><code>Image.asset</code>, <code>Image.network</code></td>
</tr>
<tr>
<td>버튼</td>
<td><code>ElevatedButton</code>, <code>IconButton</code></td>
</tr>
<tr>
<td>입력폼</td>
<td><code>TextField</code>, <code>Form</code>, <code>Checkbox</code></td>
</tr>
<tr>
<td>레이아웃</td>
<td><code>Row</code>, <code>Column</code>, <code>Expanded</code>, <code>Stack</code>, <code>Padding</code>, <code>Align</code></td>
</tr>
<tr>
<td>기타</td>
<td><code>Scaffold</code>, <code>ListView</code>, <code>GridView</code>, <code>GestureDetector</code></td>
</tr>
</tbody></table>
<hr>
]]></description>
        </item>
    </channel>
</rss>