<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>sun-ah.log</title>
        <link>https://velog.io/</link>
        <description>HTML로 코딩합니다.</description>
        <lastBuildDate>Mon, 04 Nov 2024 00:18:38 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>sun-ah.log</title>
            <url>https://velog.velcdn.com/images/sun-ah/profile/b30ff4b3-bef5-4e72-8c25-a53fa31a0df1/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. sun-ah.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/sun-ah" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[useCallback]]></title>
            <link>https://velog.io/@sun-ah/useCallback</link>
            <guid>https://velog.io/@sun-ah/useCallback</guid>
            <pubDate>Mon, 04 Nov 2024 00:18:38 GMT</pubDate>
            <description><![CDATA[<p>useCallback은 리액트에서 제공하는 훅으로, 함수의 메모이제이션을 위해 사용된다. ⚡ 컴포넌트가 렌더링될 때마다 동일한 함수를 다시 생성하는 것을 방지하고, 불필요한 렌더링을 줄여 성능을 최적화하는 데 유용하다. 특히 하위 컴포넌트에 콜백 함수로 함수를 전달할 때 유용하다.</p>
<p>useCallback의 기본 사용법 🔧</p>
<p>useCallback은 다음과 같은 형태로 사용한다:</p>
<pre><code>const memoizedCallback = useCallback(() =&gt; {
  함수 내용
}, [의존성 배열]);</code></pre><p>첫 번째 인자로 메모이제이션할 함수를 받고, 두 번째 인자로 의존성 배열을 받는다. 의존성 배열의 값들이 변경될 때만 함수가 새롭게 생성되며, 그렇지 않으면 이전에 생성한 함수를 재사용한다. 🌀</p>
<p>언제 사용해야 할까? 🤔</p>
<p>useCallback은 다음과 같은 상황에서 사용하면 좋다:</p>
<p>콜백 함수가 하위 컴포넌트로 전달되는 경우: 하위 컴포넌트가 전달된 함수의 변경을 감지해 불필요하게 다시 렌더링되지 않도록 막을 수 있다.</p>
<p>함수가 종속된 값이 변경되지 않을 때: 동일한 함수를 반복해서 생성하는 것을 방지하고, 리렌더링 성능을 최적화할 수 있다.</p>
<p>하지만 모든 함수에 useCallback을 적용하는 것은 오히려 코드의 복잡성을 높이고 성능을 저하시킬 수 있다. 따라서 성능에 중요한 영향을 줄 수 있는 상황에만 사용하는 것이 좋다. 🚫</p>
<p>예시 코드 📄</p>
<p>아래는 useCallback을 사용해 버튼 클릭 시 호출되는 핸들러 함수를 메모이제이션하는 예시이다:</p>
<pre><code>import React, { useState, useCallback } from &#39;react&#39;;

const Counter = () =&gt; {
  const [count, setCount] = useState(0);

  // useCallback을 사용해 핸들러를 메모이제이션
  const handleClick = useCallback(() =&gt; {
    setCount((prevCount) =&gt; prevCount + 1);
  }, []);

  return (
    &lt;div&gt;
      &lt;p&gt;카운트: {count}&lt;/p&gt;
      &lt;button onClick={handleClick}&gt;증가&lt;/button&gt;
    &lt;/div&gt;
  );
};

export default Counter;</code></pre><p>위 코드에서는 handleClick 함수가 useCallback을 통해 메모이제이션되어, 컴포넌트가 다시 렌더링될 때도 동일한 함수를 재사용하게 된다. ⏳ 이렇게 함으로써 불필요한 함수 재생성을 방지하고 성능을 개선할 수 있다.</p>
<p>정리 📌</p>
<p>useCallback은 함수의 메모이제이션을 위해 사용된다.</p>
<p>하위 컴포넌트에 콜백 함수로 전달할 때 성능 최적화에 유용하다.</p>
<p>성능 최적화가 필요한 경우에만 사용하고, 너무 남용하지 않는 것이 좋다. 😊</p>
<p>useCallback을 적절히 사용하면 불필요한 함수 생성과 렌더링을 줄이고, 컴포넌트의 성능을 최적화할 수 있다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[useMemo]]></title>
            <link>https://velog.io/@sun-ah/useMemo</link>
            <guid>https://velog.io/@sun-ah/useMemo</guid>
            <pubDate>Mon, 04 Nov 2024 00:16:45 GMT</pubDate>
            <description><![CDATA[<p>useMemo는 리액트에서 제공하는 훅으로, 컴포넌트가 렌더링될 때 비용이 많이 드는 연산을 최적화하기 위해 사용된다. 🧠✨ 특정 값이 변경되었을 때만 계산을 재수행하게 해주므로, 불필요한 연산을 줄이고 성능을 높이는 데 유용하다.</p>
<p>useMemo의 기본 사용법 🔧</p>
<p>useMemo는 다음과 같은 형태로 사용한다:</p>
<pre><code>const memoizedValue = useMemo(() =&gt; {
  return 계산이 많이 필요한 값;
}, [의존성 배열]);</code></pre><p>여기서 useMemo는 첫 번째 인자로 비용이 많이 드는 함수를 받고, 두 번째 인자로 의존성 배열을 받는다. 의존성 배열의 값들이 변경될 때만 첫 번째 인자의 함수가 다시 실행되어 값을 계산한다. 의존성 배열의 값들이 변경되지 않으면, 이전에 계산한 값을 재사용한다. 🌀</p>
<p>언제 사용해야 할까? 🤔</p>
<p>useMemo는 다음과 같은 상황에서 사용하면 좋다:</p>
<p>비용이 많이 드는 계산을 수행하는 경우:
예를 들어, 큰 배열을 필터링하거나 복잡한 수학적 연산을 할 때 사용하면 유용하다.</p>
<p>컴포넌트가 자주 렌더링되면서 동일한 계산을 반복하는 경우: useMemo를 사용해 이전 계산 결과를 재사용함으로써 불필요한 계산을 방지할 수 있다.</p>
<p>하지만 모든 경우에 useMemo를 사용하는 것은 권장되지 않는다. 지나치게 남용하면 코드가 복잡해지고 관리하기 어려워질 수 있다. 따라서 성능 문제가 발생할 가능성이 있는 경우에만 사용하는 것이 좋다. 🚫</p>
<p>예시 코드 📄</p>
<p>아래는 useMemo를 사용해 큰 배열을 필터링하는 예시이다:</p>
<pre><code>import React, { useState, useMemo } from &#39;react&#39;;

const ExpensiveComponent = ({ items }) =&gt; {
  const [filter, setFilter] = useState(&#39;&#39;);

  // useMemo를 사용해 필터링 결과를 메모이제이션
  const filteredItems = useMemo(() =&gt; {
    console.log(&#39;필터링 중...&#39;);
    return items.filter(item =&gt; item.includes(filter));
  }, [items, filter]);

  return (
    &lt;div&gt;
      &lt;input
        type=&quot;text&quot;
        value={filter}
        onChange={(e) =&gt; setFilter(e.target.value)}
        placeholder=&quot;검색어를 입력하세요&quot;
      /&gt;
      &lt;ul&gt;
        {filteredItems.map((item, index) =&gt; (
          &lt;li key={index}&gt;{item}&lt;/li&gt;
        ))}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
};

export default ExpensiveComponent;</code></pre><p>위 코드에서는 items 배열을 필터링하는 작업이 useMemo를 통해 메모이제이션된다. 🔍 filter가 변경될 때만 필터링 작업이 다시 수행되며, 그렇지 않으면 이전 필터링 결과를 재사용한다. 이를 통해 성능을 개선할 수 있다.</p>
<p>정리 📌</p>
<p>useMemo는 비용이 많이 드는 연산의 최적화를 위해 사용한다.</p>
<p>의존성 배열의 값이 변경되지 않으면 이전 결과를 재사용하여 불필요한 연산을 방지한다.</p>
<p>성능 최적화가 필요한 경우에만 사용하고, 너무 남용하지 않는 것이 좋다. 😊</p>
<p>이렇게 useMemo를 적절히 사용하면 컴포넌트의 성능을 높이고, 불필요한 계산을 줄일 수 있다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[리액트 생명주기(Life Cycle)란?]]></title>
            <link>https://velog.io/@sun-ah/%EB%A6%AC%EC%95%A1%ED%8A%B8%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0</link>
            <guid>https://velog.io/@sun-ah/%EB%A6%AC%EC%95%A1%ED%8A%B8%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0</guid>
            <pubDate>Sun, 27 Oct 2024 12:13:33 GMT</pubDate>
            <description><![CDATA[<p>리액트 생명주기 (Life Cycle)란 컴포넌트가 생성되고 업데이트되고 소멸되는 과정을 말한다. ⚙️ 이 생명주기를 이해하면 컴포넌트가 특정 시점에서 어떤 상태인지, 그리고 그에 따라 어떤 작업을 수행할 수 있는지 알 수 있다. 리액트 생명주기는 크게 세 가지 단계로 나눌 수 있다: 마운팅(Mounting), 업데이트(Updating), 언마운팅(Unmounting). 🔄</p>
<h3 id="1-마운팅-mounting-🛠️">1. 마운팅 (Mounting) 🛠️</h3>
<p>마운팅은 컴포넌트가 처음으로 DOM에 삽입될 때의 과정이다. 컴포넌트가 화면에 나타날 때 여러 가지 작업을 할 수 있는데, 이 단계에는 주로 다음과 같은 메서드들이 있다:</p>
<p>constructor(): 컴포넌트가 생성될 때 호출되며 초기 상태를 설정할 때 사용된다.
render(): 컴포넌트의 UI를 정의하는 메서드로, JSX를 반환한다.
componentDidMount(): 컴포넌트가 화면에 완전히 나타난 후 호출된다. 여기서 API 호출이나 DOM과 관련된 작업을 수행할 수 있다.</p>
<pre><code>import React, { Component } from &#39;react&#39;;

class ExampleComponent extends Component {
  constructor(props) {
    super(props);
    this.state = { data: null };
    console.log(&#39;constructor 호출&#39;);
  }

  componentDidMount() {
    console.log(&#39;componentDidMount 호출&#39;);
    // API 호출 예시
    fetch(&#39;https://api.example.com/data&#39;)
      .then(response =&gt; response.json())
      .then(data =&gt; this.setState({ data }));
  }

  render() {
    console.log(&#39;render 호출&#39;);
    return &lt;div&gt;데이터: {this.state.data}&lt;/div&gt;;
  }
}

export default ExampleComponent;</code></pre><p>위 코드에서 컴포넌트가 마운트될 때 constructor -&gt; render -&gt; componentDidMount 순으로 호출된다. 🌀</p>
<h3 id="2-업데이트-updating-♻️">2. 업데이트 (Updating) ♻️</h3>
<p>업데이트는 컴포넌트가 상태(state)나 속성(props)의 변경으로 인해 다시 렌더링될 때의 과정이다. 이 단계에서는 다음과 같은 메서드들이 사용된다:</p>
<p>shouldComponentUpdate(): 컴포넌트가 다시 렌더링될 필요가 있는지 결정한다. 성능 최적화를 위해 사용할 수 있다.</p>
<p>render(): 상태나 속성이 변경되면 다시 호출되어 UI를 업데이트한다.</p>
<p>componentDidUpdate(): 업데이트가 완료된 후 호출된다. 이전 상태와 현재 상태를 비교하거나, 추가적인 작업을 수행할 때 유용하다.</p>
<pre><code>componentDidUpdate(prevProps, prevState) {
  if (prevState.data !== this.state.data) {
    console.log(&#39;업데이트 완료: 새로운 데이터가 설정되었습니다.&#39;);
  }
}</code></pre><p>위 예시에서 componentDidUpdate는 상태가 변경될 때마다 호출되어 업데이트 이후의 작업을 수행한다. 🚀</p>
<h3 id="3-언마운팅-unmounting-🚪">3. 언마운팅 (Unmounting) 🚪</h3>
<p>언마운팅은 컴포넌트가 DOM에서 제거될 때의 과정이다. 이 단계에서는 componentWillUnmount() 메서드가 호출되며, 이 메서드는 컴포넌트가 소멸되기 전에 필요한 정리 작업(예: 타이머 정리, 이벤트 리스너 제거 등)을 수행할 수 있다.</p>
<pre><code>componentWillUnmount() {
  console.log(&#39;componentWillUnmount 호출&#39;);
  // 타이머 정리 예시
  clearInterval(this.timer);
}</code></pre><p>이 메서드를 통해 컴포넌트가 사라지기 전에 리소스를 정리하여 메모리 누수를 방지할 수 있다. 💡</p>
<h3 id="정리-📚">정리 📚</h3>
<p>리액트 생명주기는 컴포넌트의 상태 변화를 이해하고 적절한 타이밍에 필요한 작업을 수행하는 데 중요한 역할을 한다. 이를 통해 코드의 유지보수성과 성능을 높일 수 있다. 각 단계마다 적절한 메서드를 사용해 컴포넌트의 동작을 제어하고, 예기치 못한 문제를 방지할 수 있다. 😊</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[react 배열 렌더링 시 key 설정 이유와 주의사항]]></title>
            <link>https://velog.io/@sun-ah/%EB%A6%AC%EC%95%A1%ED%8A%B8%EB%B0%B0%EC%97%B4%EB%A0%8C%EB%8D%94%EB%A7%81key</link>
            <guid>https://velog.io/@sun-ah/%EB%A6%AC%EC%95%A1%ED%8A%B8%EB%B0%B0%EC%97%B4%EB%A0%8C%EB%8D%94%EB%A7%81key</guid>
            <pubDate>Sun, 27 Oct 2024 12:05:49 GMT</pubDate>
            <description><![CDATA[<p>리액트에서 배열을 렌더링할 때 꼭 🔑 key라는 속성을 설정해야 한다. 🔑 key는 리액트가 각 요소를 구분할 수 있게 해주는 유일한 식별자 역할을 하기 때문이다. 🔑 key가 없으면 리액트는 어떤 요소가 변경되었는지 모르게 되고, 그 결과 불필요하게 많은 리렌더링이 발생할 수 있다. 이러면 성능이 떨어지고, 렌더링 결과도 의도치 않게 어긋날 수 있다. ❗</p>
<p> 🔑 key를 설정할 때 가장 중요한 점은, 배열 내에서 각 요소가 유일하게 구분될 수 있는 값을 사용해야 한다는 것이다.
 흔히 map 함수를 사용해서 배열을 렌더링할 때 🔑 key로 인덱스를 사용하는 경우가 있는데, 이는 좋은 방법이 아니다. 🚫 요소의 순서가 바뀌거나 새로운 요소가 중간에 추가되면 인덱스가 바뀌기 때문이다. 이렇게 되면 리액트가 해당 요소를 제대로 추적하지 못하고, 예상치 못한 버그가 생길 수 있다. 🐛</p>
<pre><code>// 좋지 않은 예시코드 ❌
import React from &#39;react&#39;;

const ItemList = ({ items }) =&gt; {
  return (
    &lt;ul&gt;
      {items.map((item, index) =&gt; (
        &lt;li key={index}&gt;{item.name}&lt;/li&gt;
      ))}
    &lt;/ul&gt;
  );
};

export default ItemList;</code></pre><p>그래서 🔑 key로는 가능하면 그 요소의 고유한 ID를 사용하는 것이 좋다. ✅ 예를 들어 데이터베이스에서 가져온 데이터라면 각 항목에 고유한 ID가 있을 테니까, 그 ID를 🔑 key로 사용하는 것이다. 이렇게 하면 리액트가 각 요소의 변화를 정확하게 감지하고, 필요한 부분만 효율적으로 업데이트할 수 있다.</p>
<pre><code>// 좋은 예시 코드 ✅
import React from &#39;react&#39;;

const ItemList = ({ items }) =&gt; {
  return (
    &lt;ul&gt;
      {items.map((item) =&gt; (
        &lt;li key={item.id}&gt;{item.name}&lt;/li&gt;
      ))}
    &lt;/ul&gt;
  );
};

export default ItemList;</code></pre><p>위 예시에서 items 배열의 각 항목은 고유한 id를 가지고 있다고 가정한다. 이 id를 🔑 key로 사용함으로써 리액트가 각 요소를 효율적으로 추적할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[this 키워드와 Lexical Scope 이해하기]]></title>
            <link>https://velog.io/@sun-ah/this-lexical-scope</link>
            <guid>https://velog.io/@sun-ah/this-lexical-scope</guid>
            <pubDate>Sun, 13 Oct 2024 03:35:04 GMT</pubDate>
            <description><![CDATA[<p>오늘은 this 키워드를 알아보려 한다. this를 사용해본적이 없어 이것을 도대체 어떻게 사용하는 건지 건지 알쏭달쏭했다. 오늘 그것을 깔끔하게 정리해 보려한다. 추가로 &quot;Lexical Scope&quot;까지 같이 알아보자.</p>
<h3 id="this-">this ?</h3>
<p>호출 하는 관점에서 간단하게 설명하자면, this는 누가 호출했는지에 따라 달라진다. 예를 들어, 객체 안에서 함수를 호출하면 그 객체를 가리키고, 전역에서 호출하면 전역 객체(window나 global)를 가리킨다.</p>
<p>하지만 여기서 주의할 점이 있는데, 화살표 함수에서는 다른 룰이 적용된다! 여기서는 this가 <strong>정적</strong>으로 <strong>바인딩</strong>돼서, 그 함수를 어디서 호출하든 바깥 스코프의 this를 그대로 사용한다.</p>
<pre><code>const obj = {
  name: &#39;길동&#39;,
  sayHello: function() {
    console.log(`안녕, 난 ${this.name}이야`);
  },
  sayHelloArrow: () =&gt; {
    console.log(`안녕, 난 ${this.name}이야`);
  }
};

obj.sayHello(); // 안녕, 난 길동이야
obj.sayHelloArrow(); // 안녕, 난 undefined이야</code></pre><p>왜 두 번째는 undefined일까? sayHelloArrow는 화살표 함수라서, this가 함수가 정의된 시점의 this를 가리킨다. 이 경우 전역 객체를 참조하는데, 전역엔 name이라는 변수가 없으니 undefined가 나오는 것.</p>
<p>만약 전역에 name을 추가해 준다면?</p>
<pre><code>const name = &#39;전역 길동&#39;;

const obj = {
  name: &#39;길동&#39;,
  sayHelloArrow: () =&gt; {
    console.log(`안녕, 난 ${this.name}이야`);
  }
};

obj.sayHelloArrow(); // 안녕, 난 전역 길동이야</code></pre><p>이 경우에는 this가 전역 객체를 가리키고, 전역에 name 변수가 정의되어 있으니까 &#39;전역 길동&#39;이 출력된다.</p>
<h3 id="lexical-scope">Lexical Scope?</h3>
<p>Lexical Scope(렉시컬 스코프)란 쉽게 말해 코드가 작성된 위치에 따라 스코프(변수 접근 범위)가 결정된다는 것을 의미한다. 이걸 &quot;정적 스코프&quot;라고도 부르는데 자바스크립트는 런타임이 아닌 작성된 시점에 스코프를 결정한다. 함수가 정의된 곳에 따라 어디까지 변수를 쓸 수 있는지 결정되는 것을 뜻한다.</p>
<pre><code>function outer() {
  const outerVar = &#39;난 바깥이야&#39;;

  function inner() {
    console.log(outerVar); // 난 바깥이야
  }

  inner();
}

outer();</code></pre><p>위 코드에서 inner 함수는 outer 함수 안에서 정의되었다. 그래서 inner는 outerVar에 접근할 수 있음. 이게 바로 렉시컬 스코프인데 함수가 어디서 실행되느냐가 아니라 어디서 정의됐느냐가 중요하다!</p>
<h3 id="this와-lexical-scope의-차이점">this와 Lexical Scope의 차이점</h3>
<p>this는 누가 호출했는지에 따라 변하고, 렉시컬 스코프는 코드가 작성된 위치에 따라 결정된다. 그래서 화살표 함수는 렉시컬 스코프처럼 작동하는 것. 한 번 정의되면 그 위치의 this를 계속 참조한다.</p>
<p>이제 this와 렉시컬 스코프가 좀 더 명확해진 것 같다. 자바스크립트에서 자주 헷갈릴 수도 있는 부분인데, 개념을 잘 잡으면 훨씬 편해질 거 같다! 😎</p>
<p>(쿠키) 바인딩이란...?
무언가를 &#39;연결&#39;하거나 &#39;묶는&#39; 것을 의미한다.</p>
<pre><code>const person = {
  name: &#39;길동&#39;,
  introduce: function() {
    console.log(`안녕! 나는 ${this.name}이야.`);
  }
};

const otherPerson = { name: &#39;재석&#39; };

person.introduce(); // 안녕! 나는 길동이야.
person.introduce.call(otherPerson); // 안녕! 나는 재석이야.</code></pre><p>여기에서 this가 otherPerson으로 바인딩 된 것.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript에서 변수 선언할 때마다 var, let, const 세 가지 중 뭘 써야 할지 헷갈린다면...?]]></title>
            <link>https://velog.io/@sun-ah/JavaScript%EC%97%90%EC%84%9C-%EB%B3%80%EC%88%98-%EC%84%A0%EC%96%B8%ED%95%A0-%EB%95%8C%EB%A7%88%EB%8B%A4-var-let-const-%EC%84%B8-%EA%B0%80%EC%A7%80-%EC%A4%91-%EB%AD%98-%EC%8D%A8%EC%95%BC-%ED%95%A0%EC%A7%80-%ED%97%B7%EA%B0%88%EB%A6%B0%EB%8B%A4%EB%A9%B4</link>
            <guid>https://velog.io/@sun-ah/JavaScript%EC%97%90%EC%84%9C-%EB%B3%80%EC%88%98-%EC%84%A0%EC%96%B8%ED%95%A0-%EB%95%8C%EB%A7%88%EB%8B%A4-var-let-const-%EC%84%B8-%EA%B0%80%EC%A7%80-%EC%A4%91-%EB%AD%98-%EC%8D%A8%EC%95%BC-%ED%95%A0%EC%A7%80-%ED%97%B7%EA%B0%88%EB%A6%B0%EB%8B%A4%EB%A9%B4</guid>
            <pubDate>Sun, 06 Oct 2024 11:57:05 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/sun-ah/post/c4a6588a-0bc7-4fc3-8e2b-d2e6ef4b163e/image.png" alt=""></p>
<p>JavaScript에서 변수 선언할 때마다 var, let, const 세 가지 중 뭘 써야 할지 헷갈린다면...?</p>
<p>사실 나는 var를 한번도 써본적이 없긴하다. js를 배운지 한달밖에 안되었고 처음부터 let과 const만을 사용해서 배웠다.</p>
<p>그런데 이번에 그 차이를 공부해보니 흥미로운 부분이 있었다!
var, let, const의 차이를 알아보자.</p>
<h4 id="var-옛날-방식의-대표주자">var: 옛날 방식의 대표주자</h4>
<p>var는 ES6(2015) 이전부터 쓰였던 변수 선언 방식이고 범위 개념에서 조금 다른점이 있다. 왜냐하면 블록 내부에서 선언해도 함수 전체에서 접근 가능한 점이 특징이다.</p>
<pre><code>function example() {
  if (true) {
    var message = &#39;안녕!&#39;;
    console.log(message); // &#39;안녕!&#39; 출력
  }
  console.log(message); // 안녕! 출력 (블록 밖에서도 접근 가능)
}

example();</code></pre><p>호이스팅도 중요한 특징이라서 var로 선언한 변수는 선언 위치에 상관없이 맨 위로 끌어올려지는 효과가 있다.</p>
<h4 id="let-블록-범위를-존중하는-친구">let: 블록 범위를 존중하는 친구</h4>
<p>ES6 이후에 등장한 let은 훨씬 더 직관적이다. 블록 범위를 따라가기 때문이다. 중괄호로 감싸진 블록 내에서만 변수가 살아있기 때문에, 예상치 못한 값의 변경을 막을 수 있다.</p>
<pre><code>function example() {
  if (true) {
    let message = &#39;안녕!&#39;;
    console.log(message); // &#39;안녕!&#39; 출력
  }
  console.log(message); // 에러! 블록 밖에서는 접근 불가
}

example();</code></pre><p>let도 호이스팅이 일어나긴 하는데, var랑 다르게 선언하기 전에 접근하려고 하면 무조건 에러가 난다.</p>
<pre><code>console.log(message); // ReferenceError!
let message = &#39;안녕!&#39;;</code></pre><h4 id="const-한-번-정하면-끝">const: 한 번 정하면 끝!</h4>
<p>const는 상수를 선언할 때 사용하는 키워드이다.
const도 let과 마찬가지로 블록 스코프를 따른다. 즉, 선언된 블록 내에서만 접근할 수 있다.</p>
<pre><code>function example() {
  if (true) {
    const message = &#39;안녕!&#39;;
    console.log(message); // &#39;안녕!&#39; 출력
  }
  console.log(message); // 에러! 블록 밖에서는 접근 불가
}

example();
</code></pre><p>이 코드에서도 동일하게 message는 블록 스코프 내에서만 유효하기 때문에 if 블록 밖에서는 접근할 수 없어 에러가 발생한다</p>
<p>그리고 const는 기본적으로 한 번 값을 할당하면 다시는 변경할 수 없고 그래서 보통 변경되지 않아야 하는 값이나 객체를 선언할 때 많이 사용한다.</p>
<pre><code>const hi = 하이;
hi = 헬로우; // 오류! 값 변경 불가</code></pre><p>하지만 객체나 배열은 내부 값의 변경은 가능하다. const로 선언된 객체나 배열 자체는 재할당이 불가능하지만, 그 안의 속성이나 요소는 바꿀 수 있음.</p>
<pre><code>const user = { name: &#39;유재석&#39; };
user.name = &#39;김연아&#39;; // 객체 속성은 변경 가능</code></pre><p>그래서 언제 뭘 써야 할까?
var는 이제 거의 안 쓰는 게 좋다! 왜냐면 구식이기 때문ㅎㅎ
더 자세히 얘기하자면 let과 const를 사용하는 것이 더 좋기 때문이다.</p>
<p>let과 const를 사용하면 변수의 유효 범위가 명확하고,
변수 중복 선언이나 호이스팅 문제 등을 방지할 수 있어서
코드를 더 읽기 쉽게 만들고 유지보수를 쉽게 할 수 있는 장점이 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[브라우저는 어떻게 동작할까?]]></title>
            <link>https://velog.io/@sun-ah/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80</link>
            <guid>https://velog.io/@sun-ah/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80</guid>
            <pubDate>Sat, 28 Sep 2024 09:56:06 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/sun-ah/post/7cab896b-dd28-4ae1-907e-071f17390e46/image.png" alt=""></p>
<p>브라우저는 웹 세상을 탐험할 수 있게 해주는 마법 같은 소프트웨어다. 사용자가 웹 주소(URL)를 입력하면 <strong>브라우저</strong>가 서버에 “안녕, 여기 데이터 좀 줘!”라고 <strong>요청</strong>하는데, 이 과정은 HTTP라는 특별한 언어로 이루어진다. 그러면 <strong>서버</strong>가 “여기! 웹 페이지 데이터 받아!”라고 <strong>응답</strong>해 준다. 😎</p>
<p>그다음, 브라우저는 이 데이터들을 해석하는데, <strong>HTML</strong>로 웹 페이지의 뼈대를 만들고, <strong>CSS</strong>로 스타일을 입히고, <strong>JavaScript</strong>로 페이지가 어떻게 움직일지를 결정한다. 이렇게 해서 브라우저는 <strong>DOM</strong>이라는 마법 ✨ 의 목록을 만들어 페이지의 요소를 자유자재로 조작할 수 있게 된다.</p>
<p>이후, <strong>렌더링</strong> 엔진이 등장해 브라우저가 페이지를 화면에 뿌려준다. HTML과 CSS를 섞어 최종적으로 눈에 보이는 멋진 결과물을 만든다. 여기서 레이아웃과 스타일이 다양하게 펼쳐지니, 마치 예술 작품 🤩 이 탄생하는 것과 같다.</p>
<p>사용자가 버튼을 클릭하면 브라우저가 JavaScript를 통해 “오케이 👌, 내가 뭔가 해볼게!”라며 즉각적으로 반응한다.</p>
<p>마지막으로, 브라우저는 <strong>캐시</strong>와 <strong>쿠키</strong>를 관리해 사용자 경험을 업그레이드한다. <strong>캐시</strong>는 이전에 본 페이지 데이터를 저장해 다음에 빠르게 로드하고, <strong>쿠키</strong>는 로그인 🔑🔐 정보 같은 개인 설정을 기억해서 맞춤형 서비스를 제공한다.</p>
<p>결론적으로, <strong>브라우저</strong>는 이렇게 다양한 기능을 통해 우리가 웹을 즐길 수 있도록 도와주는 필수 아이템이다! 📌 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[이 감동을 뭐라고 표현해야 할지 몰라 제목을 못 정하겠다]]></title>
            <link>https://velog.io/@sun-ah/%EC%A0%9C%EB%AA%A9%EB%AA%BB%EC%A0%95%ED%95%A8</link>
            <guid>https://velog.io/@sun-ah/%EC%A0%9C%EB%AA%A9%EB%AA%BB%EC%A0%95%ED%95%A8</guid>
            <pubDate>Sat, 28 Sep 2024 04:42:45 GMT</pubDate>
            <description><![CDATA[<p>오늘 태어나서 처음으로</p>
<blockquote>
<p>객체 배열의 값을 for문을 사용해 DOM에 동적으로 표현하는 경험을 하였다</p>
</blockquote>
<p>내가 느낀 이 감동을 뭐라고 표현해야 할지 몰라 제목을 못 정하겠다
개인적으로 매우 역사적인 순간이네 </p>
<p>총잡이&#39;강~!&#39;사님께 다시한번 정말 감사한 마음을 표하며...</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CSS 자식, 자손 선택하기]]></title>
            <link>https://velog.io/@sun-ah/CSS-%EC%9E%90%EC%8B%9D-%EC%9E%90%EC%86%90-%EC%84%A0%ED%83%9D%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sun-ah/CSS-%EC%9E%90%EC%8B%9D-%EC%9E%90%EC%86%90-%EC%84%A0%ED%83%9D%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 22 Sep 2024 06:39:49 GMT</pubDate>
            <description><![CDATA[<pre><code>&lt;html&gt;
  &lt;body&gt;
    &lt;div class=&quot;abc&quot;&gt;
      &lt;div class=&quot;def&quot;&gt;자손요소1&lt;/div&gt;
      &lt;div class=&quot;ghi&quot;&gt;
        &lt;div class=&quot;def&quot;&gt;자손요소2&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre><br>

<h3 id="abc-def">.abc .def</h3>
<p>=&gt;  클래스 abc를 가진 요소의 자식,자손 요소 중에서 클래스 def를 가진 요소를 선택.</p>
<h3 id="abcdef">.abc.def</h3>
<p>=&gt;  클래스 abc와 def를 동시에 가진 요소를 선택. 한 요소에 두 클래스 모두를 가지고 있어야 함.</p>
<p><br><br></p>
<p>그래서 두 선택자는 사용되는 맥락에 따라 매우 다르게 작용한다.
<br></p>
<p>.abc .def 는 &#39;자손요소1&#39;과 &#39;자손요소2&#39; 를 모두 선택함</p>
<p>반면</p>
<p>.abc.def 는 아무것도 선택되지 않음. =&gt; ( abc와 def 클래스를 동시에 가진 요소가 없기 때문)</p>
<p><br><br></p>
<h4 id="🤷♂️-만약-abc--def-한다면">🤷‍♂️ 만약 .abc &gt; .def 한다면?</h4>
<p>.abc &gt; .def 선택자는 클래스 abc를 가진 요소의 직접적인 자식 요소 중에서 클래스 def를 가진 요소를 선택하므로,</p>
<p>&#39;자손요소1&#39;만 선택하고, &#39;자손요소2&#39;는 선택하지 않는다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CSS? "Cascading"]]></title>
            <link>https://velog.io/@sun-ah/CSS-Cascading</link>
            <guid>https://velog.io/@sun-ah/CSS-Cascading</guid>
            <pubDate>Sun, 15 Sep 2024 14:59:29 GMT</pubDate>
            <description><![CDATA[<p>CSS의 가장 중요한 개념 중 하나가 바로 &quot;Cascading&quot;이다. 이게 실제로는 스타일 적용의 우선순위와 관련된 부분인데, 처음 CSS를 접했을 땐 그냥 &quot;스타일을 입히는 방법&quot; 정도로만 생각했다. 그런데 최근 다시 공부해보다보니 아, 이게 꼭 &quot;스타일 배틀&quot; 같은 느낌이라는 걸 깨닫게 되었다.</p>
<blockquote>
<p>누가 더 우선권을 가질지, 말 그대로 스타일들끼리 한판 붙는 개념이랄까.
(이거 완전 스타일 대전! 👊)</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/sun-ah/post/31a2080e-1f4c-43b2-90b5-edc43434917e/image.jpg" alt=""></p>
<p>&quot;Cascading&quot;이라는 단어가 &quot;폭포수처럼&quot;이라는 뜻인데, 마치 물줄기가 여러 단계로 떨어지는 것처럼 스타일도 적용되는 순서가 있다고 할 수 있다. 그런데 그 순서가 꼭 폭포수처럼 매끄럽게 흘러간다고는 장담 못 한다.</p>
<blockquote>
<p>굳이 표현하면 가끔은 폭포에서 스타일이 튀어나오는 느낌이랄까? 😂</p>
</blockquote>
<p>예를 들어, 같은 요소에 여러 스타일 규칙을 정의했을 때, 어떤 스타일이 최종적으로 이길지를 결정하는 게 바로 이 &quot;Cascade&quot; 원칙이다.</p>
<p>우선순위는 크게 세 가지로 나뉜다.</p>
<h4 id="1-명시적-우선순위">1. 명시적 우선순위</h4>
<p><code>!important</code>를 쓰면 그 스타일이 무조건 이김. 무조건적으로! 그런데 이걸 남용하면 유지보수가 아주 골치 아파진다고 한다. 그래서 중요한 건 정말 중요한 것에만 쓰는 게 좋다.</p>
<blockquote>
<p>(중요한 건 중요할 때만... 철학적이네?)</p>
</blockquote>
<h4 id="2-명시적-선택자-우선순위">2. 명시적 선택자 우선순위</h4>
<p>ID, 클래스, 요소 선택자의 순서에 따라 우선순위가 달라짐. &#39;ID&#39;가 제일 강하고, 그 다음 &#39;클래스&#39;, 그리고 &#39;요소&#39;. 이게 처음엔 헷갈릴 때가 있었는데, 사용하다보면 어느샌가 익숙해지니까 생각보다 직관적이다.</p>
<blockquote>
<p>(뭐, 결국 ID는 신분증처럼 중요한 거니까...)</p>
</blockquote>
<h4 id="3-소스-코드의-순서">3. 소스 코드의 순서</h4>
<p>같은 선택자끼리 우선 순위를 겨룬다면, 나중에 선언된 게 우선된다. (나는 실제 CSS 작성 시 기존코드를 지우지 않고 아래에 추가해 가며 다양한 모양을 시도 해 보며 유용하게 사용하곤 한다.) 그래서 최종 수정 때 스타일 적용 되는 순서를 잘 신경 써야 한다.</p>
<blockquote>
<p>(마지막에 등장하는 게 이긴다는 점에서, 이건 마치 드라마 주인공 공식?)</p>
</blockquote>
<p> 가끔 내가 작성한 CSS 스타일이 왜 안 먹히나 싶은적이 많았는데, 알고 보니 다 이 Cascading 때문이었다. 이제는 CSS를 작성할 때 Cascading을 염두에 두고 우선순위를 잘 고려하면서 짜보려고 한다. 그러다 보면 코드는 더 깔끔해질 것이고, 유지보수도 더 쉬워지겠지...?</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CSS 마진 상쇄 중에 border 값이 다가온다면?]]></title>
            <link>https://velog.io/@sun-ah/margin-collapsing</link>
            <guid>https://velog.io/@sun-ah/margin-collapsing</guid>
            <pubDate>Sat, 14 Sep 2024 05:22:44 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>&quot;CSS 마진 상쇄는 부모와 형제를 가리지 않는다.&quot;</p>
</blockquote>
<p>CSS 마진 상쇄에 대해 공부하던 중,
부모와 형제 간 마진 상쇄는 어떻게 일어나는지
또한 예외 사항은 없는지, 궁금해서 혼자 이리저리 뚝딱거리다가
border 값이 들어갔을 때, 값의 변화를 발견하여 기록해 보기로 했다.</p>
<p>관점은 &#39;div #a&#39; 와 &#39;div #b&#39;의 세로 마진 간격을 비교해 보는 것.</p>
<p>예제1)
<img src="https://velog.velcdn.com/images/sun-ah/post/1ceacab6-e180-4151-8e61-27e3ba663bc0/image.png" alt=""></p>
<pre><code>&lt;body&gt;
  &lt;style&gt;
      #a {
      margin: 30px;
      background-color: rgb(255, 112, 112);
      /* border: 1px solid red; */
    }

    #b {
      margin: 20px;
      background-color: #6c6ceb;
    }

    #c {
      margin: 100px;
      background-color: rgb(83, 148, 83);
    }
  &lt;/style&gt;

  &lt;div id=&quot;a&quot;&gt;
    a
    &lt;div id=&quot;c&quot;&gt;
      c
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div id=&quot;b&quot;&gt;
    b
  &lt;/div&gt;

&lt;/body&gt;</code></pre><p>자식의 마진값이 부모보다 클 때
부모와 자식 마진 간 병합이 일어나며
마진값은 둘 중 더 큰 값으로 적용된다.</p>
<p>&#39;div #a&#39;와 &#39;div #b&#39;의 마진값은 결과적으로
&#39;div #c&#39;의 마진값인 100px이 된다.</p>
<p>예제2)
<img src="https://velog.velcdn.com/images/sun-ah/post/810648de-4757-4b2e-827c-82cc5468192b/image.png" alt=""></p>
<pre><code>&lt;body&gt;
  &lt;style&gt;
    #a {
      margin: 30px;
      background-color: rgb(255, 112, 112);
      border: 1px solid black;
    }

    #b {
      margin: 20px;
      background-color: #6c6ceb;
    }

    #c {
      margin: 100px;
      background-color: rgb(83, 148, 83);
    }
  &lt;/style&gt;

  &lt;div id=&quot;a&quot;&gt;
    a
    &lt;div id=&quot;c&quot;&gt;
      c
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div id=&quot;b&quot;&gt;
    b
  &lt;/div&gt;

&lt;/body&gt;</code></pre><p>&#39;div #a&#39;에 보더가 적용되었을 때,
&#39;div #c&#39;의 마진값은 부모 밖으로
넘쳐흐르지 않으며 div #a 안에서만 적용되게 된다.
즉 이때에는 부모 자식 간 마진상쇄가 일어 나지 않는다.</p>
<p>결과적으로 &#39;div #a&#39;와 &#39;div #b&#39;의 마진값은 서로 상쇄되며
&#39;30px&#39; vs &#39;20px&#39; 중 더 큰 값인 30px로 적용되게 된다.</p>
<blockquote>
<p>CSS 마진 상쇄 曰: &quot;보더값이  오면 무효입니다!&quot;</p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>