<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>mobssie</title>
    <link>https://developer-mobssie.tistory.com/</link>
    <description>frontend developer
기본기 탄탄! 메모 끄적끄적:d</description>
    <language>ko</language>
    <pubDate>Sun, 2 Aug 2026 06:00:31 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Developer Mobssie</managingEditor>
    <image>
      <title>mobssie</title>
      <url>https://tistory1.daumcdn.net/tistory/2998791/attach/84a99df6b50f4deeadd51bb07664017c</url>
      <link>https://developer-mobssie.tistory.com</link>
    </image>
    <item>
      <title>리액트 공통컴포넌트 체크리스트</title>
      <link>https://developer-mobssie.tistory.com/112</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;명확한 인터페이스 설계: &lt;/b&gt;컴포넌트의 props는 명확하고 이해하기 쉬워야 합니다.&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;구조 분해 할당을 사용하면 &lt;/span&gt;&lt;/span&gt;명확한 인터페이스 설계를 통해 컴포넌트의 사용법을 쉽게 파악할 수 있습니다.&lt;br&gt;코드의 가독성이 향상되며, 오류의 가능성을 줄일 수 있습니다.&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// 좋은 예
const Button = ({ label, onClick }) =&amp;gt; (
&amp;nbsp;&amp;nbsp;&amp;lt;button onClick={onClick}&amp;gt;{label}&amp;lt;/button&amp;gt;
);
// 나쁜 예
const Button = (props) =&amp;gt; (
&amp;nbsp;&amp;nbsp;&amp;lt;button onClick={props.handleClick}&amp;gt;{props.text}&amp;lt;/button&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;예를 들어 { label, onClick }을 사용하는 경우, 이 props가 Button 컴포넌트에서 어떻게 사용되는지 바로 알 수 있습니다.&lt;br&gt;label은 버튼에 표시될 텍스트를 나타내고, onClick은 버튼 클릭 시 실행할 함수를 나타냅니다.&lt;br&gt;반면, props로 전체를 받아서 사용하는 경우 (props.handleClick, props.text 같이), 이 props들이 구체적으로 어떤 역할을 하는지 파악하기 위해 추가적인 코드 분석이 필요할 수 있습니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;Props 전달 최소화&lt;/b&gt;: 컴포넌트에 전달하는 props는 최소화하여, 각 컴포넌트의 역할과 책임을 명확하게&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// 좋은 예
const UserProfile = ({ user }) =&amp;gt; (
&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Avatar image={user.avatar} /&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;UserName name={user.name} /&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;
);


// 나쁜 예
const UserProfile = ({ avatar, name }) =&amp;gt; (
&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Avatar image={avatar} /&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;UserName name={name} /&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;Button&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; 컴포넌트에서는 간단하고 명확한 인터페이스를 유지하는 것이 중요하지만 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;UserProfile&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;에서는 &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;user&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; 객체와 같이 복합적인 데이터 구조를 효율적으로 다루는 것이 중요합니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;user&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; 객체를 통째로 넘겨 주어, 나중에 &lt;/span&gt;&lt;/span&gt;user&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; 객체 내 다른 속성이 필요할 때 추가적인 &lt;/span&gt;&lt;/span&gt;props&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; 변경 없이 사용할 수 있어야 합니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;단일 책임 원칙 준수:&lt;/b&gt; 각 컴포넌트는 하나의 기능만 수행해야 합니다.&lt;br&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;코드의 복잡성을 줄이고, 유지보수를 용이하게 만들며, 시스템의 확장성을 향상시키는 데 기여합니다.&lt;/span&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// 좋은 예
const LoginForm = () =&amp;gt; (
&amp;nbsp;&amp;nbsp;&amp;lt;form&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;UsernameInput /&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;PasswordInput /&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;LoginButton /&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;lt;/form&amp;gt; 
);

// 나쁜 예
const LoginForm = () =&amp;gt; (
&amp;nbsp;&amp;nbsp; &amp;lt;form&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;label&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Username:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;input type=&quot;text&quot; name=&quot;username&quot; /&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/label&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;label&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Password:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;input type=&quot;password&quot; name=&quot;password&quot; /&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/label&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;button type=&quot;submit&quot;&amp;gt;Login&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp; &amp;lt;/form&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;* 첫번째 예제 : LoginForm 컴포넌트가 오직 로그인 폼을 구성하는 데 집중하고 있고, 'UsernameInput', 'PasswordInput', 'LoginButton'과 같은 하위 컴포넌트를 사용하여 각각의 입력 필드와 로그인 버튼을 독립적으로 관리합니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;* 두번째 예제 LoginForm 컴포넌트 자체 내에서 모든 요소를 직접 처리합니다. 이 방식은 간단한 폼에서는 작업하기 쉽지만, 각 요소를 수정하거나 확장할 때 전체 폼을 다루어야 하므로 유지보수가 더 복잡해질 수 있습니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;첫 번째 방식은 각 요소를 독립적으로 관리하고 확장하는 데 더 효과적입니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;재사용 가능성 고려:&lt;/b&gt; 컴포넌트는 재사용 가능하도록 유연하게 설계해야 합니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// 좋은 예
const Button = ({ type = 'button', children, ...props }) =&amp;gt; (
&amp;nbsp;&amp;nbsp; &amp;lt;button type={type} {...props}&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {children}
&amp;nbsp;&amp;nbsp; &amp;lt;/button&amp;gt; 
);

// 나쁜 예
const SubmitButton = () =&amp;gt; (
&amp;nbsp;&amp;nbsp; &amp;lt;button type=&quot;submit&quot;&amp;gt;Submit&amp;lt;/button&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;SubmitButton 컴포넌트는 오직 'submit' 유형의 버튼으로만 사용되고, 버튼의 내용도 'Submit'으로 고정하면 컴포넌트의 사용 가능성이 크게 제한되며, 다른 컨텍스트나 다른 텍스트를 요구하는 상황에서는 새로운 컴포넌트를 만들어야 합니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;Button 컴포넌트는 type&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; 속성의 기본값을 'button'으로 설정하고, 다른 값으로 쉽게 변경할 수 있는 기능은 React 컴포넌트에서 프롭스를 활용하여 구현할 수 있습니다. 이는 컴포넌트의 인스턴스를 생성할 때 &lt;/span&gt;&lt;/span&gt;type&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; 프롭스에 원하는 값을 전달함으로써 가능합니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;* type&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;은 기본값이 'button'이지만, 'submit', 'reset' 등 다른 값으로 쉽게 변경가능&lt;/span&gt;&lt;/span&gt;&lt;br&gt;* children&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;을 사용하여 버튼의 내용을 자유롭게 정의&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;* props&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;를 통해 &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;className&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;onClick&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; 같은 이벤트 핸들러나 스타일 등의 속성을 자유롭게 추가가 가능&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;테스트 가능한 컴포넌트 작성:&lt;/b&gt; 컴포넌트는 쉽게 테스트할 수 있도록 작성해야 합니다.&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// 좋은 예 (유연한 초기 상태 설정)
export const Counter1 = ({ initialValue = 0 }) =&amp;gt; {
&amp;nbsp;&amp;nbsp;const [count, setCount] = React.useState(initialValue);
&amp;nbsp;&amp;nbsp; return (
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;Increase&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;p&amp;gt;{count}&amp;lt;/p&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/div&amp;gt; 
&amp;nbsp;&amp;nbsp; );
};

// 나쁜 예 (고정된 초기 상태 설정)
export const Counter2 = () =&amp;gt; {
&amp;nbsp;&amp;nbsp;const [count, setCount] = React.useState(0);
&amp;nbsp;&amp;nbsp;return (
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;Increase&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;p&amp;gt;{count}&amp;lt;/p&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;
&amp;nbsp;&amp;nbsp;);
};&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;* Counter1 컴포넌트는 initialValue prop을 받아서 초기 상태 값을 설정할 수 있습니다.&lt;br&gt;이는 테스트 중에 다양한 초기 값으로 컴포넌트를 쉽게 테스트할 수 있게 합니다.&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;&amp;lt;Counter initialValue={10} /&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;* Counter2 컴포넌트는 초기 상태 값을 고정적으로 0으로 설정하고 있어, 다른 초기 상태 값을 가지고 테스트를 수행하기 어렵습니다.&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;개발 과정에서나 다른 상황에서 컴포넌트를 재사용할 때 제한적일 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;의존성 최소화:&lt;/b&gt; 컴포넌트는 외부 의존성을 최소화해야 합니다.&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// 좋은 예
// 데이터를 가져오는 로직을 포함하지 않기 때문에, 그 자체로는 어떠한 외부 데이터 의존성도 갖지 않습니다.
const UserAvatar = ({ user }) =&amp;gt; (
&amp;nbsp;&amp;nbsp;&amp;lt;img src={user.avatarUrl} alt={user.name} /&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// 나쁜 예
// userId가 변경될 때마다 데이터를 새로 불러오는 로직을 내부적으로 포함하고 있기 때문에, 
// 컴포넌트의 사용이 그 상황에 맞춰져 있고, 데이터를 가져오는 API의 의존성이 큽니다.
const UserAvatar = ({ userId }) =&amp;gt; {
const [user, setUser] = React.useState(null);
&amp;nbsp;&amp;nbsp;React.useEffect(() =&amp;gt; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fetchUserById(userId).then(setUser);
&amp;nbsp;&amp;nbsp;}, [userId]);
&amp;nbsp;&amp;nbsp;if (!user) return &amp;lt;div&amp;gt;Loading...&amp;lt;/div&amp;gt;;
&amp;nbsp;&amp;nbsp;return &amp;lt;img src={user.avatarUrl} alt={user.name} /&amp;gt;;
};&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;스타일&amp;nbsp;캡슐화&lt;/b&gt;: 컴포넌트의 스타일은 독립적이어야 하며, 외부 스타일의 영향을 받지 않도록 설계합니다.&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// 좋은 예 (CSS 클래스를 사용한 스타일링)
const Button = ({ children, variant = 'primary' }) =&amp;gt; (
&amp;nbsp;&amp;nbsp;&amp;lt;button className={`button button-${variant}`}&amp;gt;{children}&amp;lt;/button&amp;gt;
);

// 나쁜 예 (인라인 스타일을 사용한 스타일링)
const Button = ({ children }) =&amp;gt; (
&amp;nbsp;&amp;nbsp;&amp;lt;button style={{ backgroundColor: 'blue', color: 'white' }}&amp;gt;{children}&amp;lt;/button&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;첫번째 예시 버튼 컴포넌트는 &lt;/span&gt;&lt;/span&gt;variant&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; prop을 받아서 이를 기반으로 다양한 스타일을 적용할 수 있습니다. &lt;/span&gt;&lt;/span&gt;&lt;br&gt;className&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;은 &quot;button&quot; 과 &quot;button-{variant}&quot;의 조합을 사용합니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;CSS 파일에 정의된 스타일을 사용하여, 컴포넌트의 스타일이 일관되고, 중복을 피하며, 스타일 변경이 필요할 경우 CSS 파일만 수정하면 되기 때문에 유지보수가 쉽습니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;두번째 예시 버튼 컴포넌트 &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;인라인 스타일을 사용하여 버튼의 배경색과 텍스트 색상을 직접 지정합니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;이 방식은 스타일 변경이 빈번하지 않고, 특정 컴포넌트에만 적용되는 간단한 스타일링에 적합할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;그 상황이 아니라면 인라인 스타일은 스타일 정보를 자바스크립트 파일 내부에 포함시키므로 CSS 캐싱의 이점을 활용할 수 없고, &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;스타일 변경 시 여러 컴포넌트의 코드를 각각 수정해야 할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;첫번째 예시인 CSS 클래스를 사용한 스타일링을 적용했을때&lt;br&gt;styled-components&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;와 같은 CSS-in-JS 라이브러리를 사용하여 스타일을 컴포넌트에 직접 캡슐화합니다. &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;이 방식은 스타일을 완전히 독립적으로 만들고, props를 통해 동적으로 스타일을 조정할 수 있어 유연합니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;컴포넌트의 스타일이 외부 CSS의 영향을 받지 않으며, 테마나 상태에 따라 스타일을 쉽게 변경가능합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;import styled from 'styled-components';

const StyledButton = styled.button`
&amp;nbsp;&amp;nbsp;background-color: ${(props) =&amp;gt; props.theme.primary};
&amp;nbsp;&amp;nbsp;color: white;
&amp;nbsp;&amp;nbsp;padding: 10px;
&amp;nbsp;&amp;nbsp;border: none;
&amp;nbsp;&amp;nbsp;border-radius: 5px;

&amp;nbsp;&amp;nbsp;&amp;amp;:hover {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;background-color: ${(props) =&amp;gt; props.theme.primaryDark};
&amp;nbsp;&amp;nbsp;}
`;

const Button = ({ children }) =&amp;gt; (
&amp;nbsp;&amp;nbsp;&amp;lt;StyledButton&amp;gt;{children}&amp;lt;/StyledButton&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;컴포넌트의 상태 관리를 명확히:&lt;/b&gt; 상태 관리는 내부적으로 캡슐화하여 컴포넌트 외부에서 쉽게 이해할 수 있도록 해야 합니다.&lt;br&gt;Toggle&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; 컴포넌트는 자신의 상태를 내부적으로 관리하고 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;다른 컴포넌트와의 상태 공유나 외부에서의 상태 조작 없이 독립적으로 기능하게 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// 좋은 예
const Toggle = () =&amp;gt; {
&amp;nbsp;&amp;nbsp;const [isOn, setIsOn] = React.useState(false);
&amp;nbsp;&amp;nbsp;const toggle = () =&amp;gt; setIsOn(!isOn);
&amp;nbsp;&amp;nbsp;return &amp;lt;button onClick={toggle}&amp;gt;{isOn ? 'ON' : 'OFF'}&amp;lt;/button&amp;gt;;
};

// 나쁜 예
const Toggle = ({ isOn, toggle }) =&amp;gt; (
&amp;nbsp;&amp;nbsp;&amp;lt;button onClick={toggle}&amp;gt;{isOn ? 'ON' : 'OFF'}&amp;lt;/button&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;상태가 공유되어야 하는 상황에서는 이 방식이 비효율적일 수 있는데 아래와 같습니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;상태 lifting을 적절히 사용&lt;/b&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;const ParentComponent = () =&amp;gt; {
&amp;nbsp;&amp;nbsp;const [activeTab, setActiveTab] = React.useState(0);
&amp;nbsp;&amp;nbsp;return (
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Tabs activeTab={activeTab} setActiveTab={setActiveTab} /&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;TabContent activeTab={activeTab} /&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;
&amp;nbsp;&amp;nbsp;);
};&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;상태 공유&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;ParentComponent&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;는&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;activeTab&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;이라는 상태를 가지며, 이를&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Tabs&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;컴포넌트와&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;TabContent&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;컴포넌트와 공유합니다. 이 구조는&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;activeTab&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;상태가&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Tabs&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;컴포넌트에서 변경되었을 때, 그 변경사항이&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;TabContent&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;에도 반영됩니다. &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;상태를 상위 컴포넌트에서 관리함으로써, 상태 관련 로직이 한 곳에 집중하는게 용이&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;해지고, 상태를 필요로 하는 다른 컴포넌트에 쉽게 전달할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;컴포넌트의 불변성 유지:&lt;/b&gt; 컴포넌트의 상태는 불변성을 유지하도록 처리해야 합니다.&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;불변성을 유지한다는 것은 데이터 구조를 직접 수정하지 않고, 새로운 데이터 구조를 생성하여 갱신하는 것을 의미합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// 좋은 예
const AddItem = ({ items, setItems }) =&amp;gt; {
&amp;nbsp;&amp;nbsp;const [itemName, setItemName] = React.useState(&quot;&quot;);
&amp;nbsp;&amp;nbsp;const addItem = () =&amp;gt; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;setItems([...items, itemName]); // 불변성 유지
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;setItemName(&quot;&quot;);
&amp;nbsp;&amp;nbsp;};
&amp;nbsp;&amp;nbsp;return (
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;input
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;value={itemName}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;onChange={(e) =&amp;gt; setItemName(e.target.value)}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;type=&quot;text&quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;button onClick={addItem}&amp;gt;Add Item&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;
&amp;nbsp;&amp;nbsp;);
};&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;불변성 유지&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;: &lt;/span&gt;&lt;/span&gt;addItem&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; 함수에서 &lt;/span&gt;&lt;/span&gt;items&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; 배열을 직접 변경하지 않고, 새 배열을 생성하여 &lt;/span&gt;&lt;/span&gt;itemName&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;을 추가합니다. 이는 원래 배열을 복사하고 (&lt;/span&gt;&lt;/span&gt;[...items]&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;), 새 항목을 배열의 끝에 추가합니다. &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;React가 상태 변경을 감지하고 컴포넌트를 적절하게 재렌더링하도록 합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;&lt;b&gt;왜 중요한가?&lt;/b&gt;: 불변성을 유지하면 React의 최적화된 상태 관리와 렌더링 메커니즘이 효과적으로 작동합니다. 또한, 미래의 복잡한 버그를 방지하고, 상태의 변경 이력을 추적하기 쉬워집니다.&lt;/li&gt;&lt;/ul&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// 나쁜 예
const AddItem = ({ items, setItems }) =&amp;gt; {
&amp;nbsp;&amp;nbsp;const [itemName, setItemName] = React.useState(&quot;&quot;);
&amp;nbsp;&amp;nbsp;const addItem = () =&amp;gt; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;items.push(itemName); // 직접적인 props 변경
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;setItems(items); // 문제의 소지가 있음
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;setItemName(&quot;&quot;);
&amp;nbsp;&amp;nbsp;};
&amp;nbsp;&amp;nbsp;return (
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;input
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;value={itemName}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;onChange={(e) =&amp;gt; setItemName(e.target.value)}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;type=&quot;text&quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;button onClick={addItem}&amp;gt;Add Item&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;
&amp;nbsp;&amp;nbsp;);
};&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;불변성 위반&lt;/b&gt;: 이 예에서 items.push(itemName)는 기존 items 배열에 직접 아이템을 추가합니다. 이러한 방식은 items 배열의 원본을 변경하기 때문에 React가 상태의 변경을 제대로 감지하지 못할 수 있습니다.&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;왜냐하면 배열 객체의 참조가 변경되지 않았기 때문입니다. 결과적으로, 이로 인해 UI가 제대로 업데이트되지 않을 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;컴포넌트의 사이드 이펙트 제어&lt;/b&gt;: 사이드 이펙트는 useEffect 등을 통해 관리해야 합니다.&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; &lt;/span&gt;&lt;/span&gt;useEffect&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;를 사용하여 사이드 이펙트를 제어하는 것은 컴포넌트의 생명주기에 따른 작업을 정리하고, 리소스의 낭비를 방지하는 데 중요&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// 좋은 예 (useEffect를 통한 사이드 이펙트 제어)
const Timer = () =&amp;gt; {
&amp;nbsp;&amp;nbsp;const [time, setTime] = React.useState(0);
&amp;nbsp;&amp;nbsp;React.useEffect(() =&amp;gt; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const timerId = setInterval(() =&amp;gt; setTime(time + 1), 1000);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return () =&amp;gt; clearInterval(timerId);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// clearInterval을 호출함으로써 컴포넌트가 언마운트 되거나 업데이트 되기 전에 타이머를 정확히 제거
&amp;nbsp;&amp;nbsp;}, [time]);
&amp;nbsp;&amp;nbsp;//&amp;nbsp;&amp;nbsp;[time]에 time을 넣어주어서, time이 변할 때마다 이펙트가 다시 실행
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;return &amp;lt;div&amp;gt;{time} seconds&amp;lt;/div&amp;gt;;
};

// 나쁜 예 (제어되지 않은 사이드 이펙트)
const Timer = () =&amp;gt; {
&amp;nbsp;&amp;nbsp;const [time, setTime] = React.useState(0);
&amp;nbsp;&amp;nbsp;setInterval(() =&amp;gt; setTime(time + 1), 1000);&amp;nbsp;&amp;nbsp;// Uncontrolled side effect
&amp;nbsp;&amp;nbsp;return &amp;lt;div&amp;gt;{time} seconds&amp;lt;/div&amp;gt;;
};&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;setInterval&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;이 &lt;/span&gt;&lt;/span&gt;useEffect&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; 내부에서 관리되지 않기 때문에, 컴포넌트가 언마운트된 후에도 인터벌이 계속 실행될 수 있습니다. &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;이는 메모리 누수를 유발하고 애플리케이션의 성능을 저하시킬 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;컴포넌트가 표현하는 데이터의 타입 체크하기&lt;/b&gt;: 타입 체크를 통해 컴포넌트에 전달되는 데이터가 올바른 형태인지 검증&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;interface User {
&amp;nbsp;&amp;nbsp;name: string;
&amp;nbsp;&amp;nbsp;age: number;
}

interface UserProfileProps {
&amp;nbsp;&amp;nbsp;user: User;
}

const UserProfile: React.FC&amp;lt;UserProfileProps&amp;gt; = ({ user }) =&amp;gt; {
&amp;nbsp;&amp;nbsp;return (
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;h1&amp;gt;{user.name}&amp;lt;/h1&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;p&amp;gt;{user.age} years old&amp;lt;/p&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;
&amp;nbsp;&amp;nbsp;);
};&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;효율적 상태 관리&lt;/b&gt;: 상태가 필요한 경우, 최소한으로 유지하고 가능하다면 &lt;b&gt;계산된 상태를 사용&lt;/b&gt;합니다.&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;React에서는 상태 관리를 위해 &lt;/span&gt;&lt;/span&gt;useState&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; 또는 다른 상태 관리 훅(&lt;/span&gt;&lt;/span&gt;useReducer&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;, &lt;/span&gt;&lt;/span&gt;useContext&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; 등)을 사용하는 것이 필수입니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;상태의 변화가 UI에 자동으로 반영되도록 하고, 상태 변화를 효과적으로 관리됩니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;useState&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;를 사용하여 &lt;/span&gt;&lt;/span&gt;count&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; 상태를 관리하면 &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;상태가 업데이트될 때마다 컴포넌트가 자동으로 리렌더링되도록 보장됩니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;컴포넌트의 &lt;/span&gt;&lt;/span&gt;initialValue&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; prop을 통해 초기 카운트 값을 설정하면 &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;재사용성을 높이고, 다양한 초기 상태를 갖는 카운터를 쉽게 구현 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// 좋은 예 (올바른 상태 관리)
const Counter = ({ initialValue }) =&amp;gt; {
&amp;nbsp;&amp;nbsp;const [count, setCount] = React.useState(initialValue);
&amp;nbsp;&amp;nbsp;return (
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;Increase&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;p&amp;gt;Count: {count}&amp;lt;/p&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;
&amp;nbsp;&amp;nbsp;);
};&lt;/code&gt;&lt;/pre&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// 나쁜 예 (부적절한 상태 관리)
const Counter = () =&amp;gt; {
&amp;nbsp;&amp;nbsp;let count = 0; // This is not reactive and not recommended in React
&amp;nbsp;&amp;nbsp;const increase = () =&amp;gt; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;count++;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;console.log(count); // This will not trigger a re-render
&amp;nbsp;&amp;nbsp;};
&amp;nbsp;&amp;nbsp;return (
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;button onClick={increase}&amp;gt;Increase&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;p&amp;gt;Count: {count}&amp;lt;/p&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;
&amp;nbsp;&amp;nbsp;);
};&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;count++&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;가 실행되어도 React는 이를 감지하지 못하며, 따라서 값이 변경되어도 컴포넌트가 리렌더링되지 않습니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;count&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt; 값이 변경되더라도, 그 변경 사항이 UI에 반영되지 않습니다. &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;데이터 플로우를 명확히 하고 단방향으로 유지&lt;/b&gt;: 데이터는 항상 상위에서 하위 컴포넌트로 흐르도록 설계&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// ParentComponent
const ParentComponent = () =&amp;gt; {
&amp;nbsp;&amp;nbsp;const [message, setMessage] = React.useState(&quot;Initial message&quot;);

&amp;nbsp;&amp;nbsp;const changeMessage = () =&amp;gt; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;setMessage(&quot;Message updated by child&quot;);
&amp;nbsp;&amp;nbsp;};

&amp;nbsp;&amp;nbsp;return (
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;div&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;h1&amp;gt;{message}&amp;lt;/h1&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;ChildComponent onChangeMessage={changeMessage} /&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/div&amp;gt;
&amp;nbsp;&amp;nbsp;);
};&lt;/code&gt;&lt;/pre&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// ChildComponent
// 자식 컴포넌트는 부모 컴포넌트로부터 함수를 prop으로 받아, 해당 함수를 통해 부모 컴포넌트의 상태를 변경
const ChildComponent = ({ onChangeMessage }) =&amp;gt; {
&amp;nbsp;&amp;nbsp;return (
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;button onClick={onChangeMessage}&amp;gt;Change Message&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp;);
};&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;모든 상태 변경 로직이 부모 컴포넌트에 있어서 자식 컴포넌트는 독립적이고 예측 가능한 동작을 유지할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// 나쁜 예
// ChildComponent
// 자식 컴포넌트가 자체적으로 상태를 변경하려고 하면 단방향 데이터 플로우 원칙에 어긋
const ChildComponent = ({ message, setMessage }) =&amp;gt; {
&amp;nbsp;&amp;nbsp;const localChangeMessage = () =&amp;gt; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;setMessage(&quot;Message updated by child&quot;);
&amp;nbsp;&amp;nbsp;};

&amp;nbsp;&amp;nbsp;return (
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;button onClick={localChangeMessage}&amp;gt;Change Message&amp;lt;/button&amp;gt;
&amp;nbsp;&amp;nbsp;);
};.&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;모든 상태 변경이 부모 컴포넌트를 통해 이루어져야 하며, 자식 컴포넌트는 상태를 직접 변경하지 않는다는 단방향 데이터 플로우의 원칙따라야 합니다. &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #0d0d0d;&quot;&gt;데이터 흐름을 명확하게 하고, 상태 관리를 더 쉽게 할 수 있도록 도와줍니다.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>나만보는 업무정리</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/112</guid>
      <comments>https://developer-mobssie.tistory.com/112#entry112comment</comments>
      <pubDate>Mon, 13 May 2024 07:59:02 +0900</pubDate>
    </item>
    <item>
      <title>CloudFront와 EC2의 비용 차이</title>
      <link>https://developer-mobssie.tistory.com/111</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;CloudFront와 EC2의 비용 차이 사용 사례, 구성, 소비되는 트래픽 양이나 리소스에 따라 다르다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Amazon CloudFront&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: left;&quot;&gt;: CloudFront는 CDN(Content Delivery Network) 서비스로서, 전 세계에 분산된 엣지 로케이션을 통해 사용자에게 빠르게 콘텐츠를 제공합니다. 사용자가 여러 지역에 걸쳐 있을 경우, 응답 속도가 빠른 장점&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;콘텐츠 전송 네트워크(CDN)로, 정적 파일을 전 세계 다양한 지역에 위치한 엣지 로케이션에서 빠르게 제공합니다. CloudFront는 주로 데이터 전송량과 HTTP 요청 수에 기반하여 요금이 청구되며, 이는 대량의 데이터를 처리할 때 특히 비용 효율적일 수 있습니다. 예를 들어, CloudFront는 S3 버킷과의 데이터 전송료를 부과하지 않으며, 데이터를 전세계 사용자에게 빠르게 배포할 수 있어 응답 속도가 빨라&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;*&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;데이터 전송량과 요청 수에 기반한 요금이 청구&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;*&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;CloudFront는 캐싱 서비스로 CDN을 제공&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;*&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;비용은 데이터 전송, 요청 수, 함수 실행 횟수 등에 따라 달라짐&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Amazon EC2&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: left;&quot;&gt;: EC2는 가상 서버를 제공하므로, 서버 측 로직을 실행하거나 데이터베이스와 같은 다른 서비스와 상호작용이 필요한 동적 웹 애플리케이션에 적합합니다. EC2 인스턴스에서는 Node.js, Python, Ruby 등 다양한 백엔드 애플리케이션을 실행&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;서버 인스턴스를 제공하며, 이 인스턴스에서는 동적 웹 애플리케이션을 호스팅할 수 있습니다. EC2의 비용은 주로 인스턴스 유형, 운영 시간, 추가 네트워크 사용량 등에 따라 결정됩니다. EC2는 특히 사용자 정의가 필요하거나 서버 사이드 처리가 중요한 동적 콘텐츠를 다룰 때 유용&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;*&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;컴퓨팅 용량에 따라 시간 또는 초 단위로 요금이 청구&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;가상 서버를 제공&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;인스턴스 유형, 운영 시간, 추가적인 스토리지 사용 등에 따라 비용이 달라&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;온디맨드 인스턴스, 예약 인스턴스, 스팟 인스턴스 등 다양한 요금제를 선택&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/111</guid>
      <comments>https://developer-mobssie.tistory.com/111#entry111comment</comments>
      <pubDate>Fri, 19 Apr 2024 11:08:54 +0900</pubDate>
    </item>
    <item>
      <title>json 응답값 표로 쉽게 정리하기</title>
      <link>https://developer-mobssie.tistory.com/110</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;JSON 데이터 복사&lt;/p&gt;
&lt;div data-width-type=&quot;pixel&quot; data-width=&quot;760&quot; data-layout=&quot;center&quot; data-node-type=&quot;mediaSingle&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-04-12 오전 10.54.43.png&quot; data-origin-width=&quot;2066&quot; data-origin-height=&quot;654&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FWyBl/btsGzewmEVf/AwTAyHlya1zuD5O1vbX5GK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FWyBl/btsGzewmEVf/AwTAyHlya1zuD5O1vbX5GK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FWyBl/btsGzewmEVf/AwTAyHlya1zuD5O1vbX5GK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFWyBl%2FbtsGzewmEVf%2FAwTAyHlya1zuD5O1vbX5GK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2066&quot; height=&quot;654&quot; data-filename=&quot;스크린샷 2024-04-12 오전 10.54.43.png&quot; data-origin-width=&quot;2066&quot; data-origin-height=&quot;654&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;// 예제 JSON 데이터
const jsonData = {
    item_id: 6520,
    model_no: &quot;DD1391-100&quot;,
    category_name: &quot;신발&quot;,
    release_date_info: {
        release_date: &quot;2021-04-02 10:30:00&quot;,
        release_date_type_text: &quot;출시일&quot;
    },
    product_info: {
        name_kor: &quot;나이키 덩크 로우 레트로 화이트 블랙&quot;,
        colors: &quot;블랙&quot;,
        details: {
            material: &quot;leather&quot;,
            sizes: [7, 8, 9, 10]
        }
    }
};

let fields = [];

function extractFields(obj, depth = 1) {
    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            const currentDepth = &quot;Depth&quot; + depth;
            fields.push({ [currentDepth]: key });

            if (typeof obj[key] === 'object' &amp;amp;&amp;amp; obj[key] !== null &amp;amp;&amp;amp; !Array.isArray(obj[key])) {
                extractFields(obj[key], depth + 1);
            }
        }
    }
}

extractFields(jsonData);
console.table(fields);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과&lt;/p&gt;
&lt;div data-width-type=&quot;pixel&quot; data-width=&quot;760&quot; data-layout=&quot;center&quot; data-node-type=&quot;mediaSingle&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-04-12 오전 11.05.18.png&quot; data-origin-width=&quot;1718&quot; data-origin-height=&quot;1136&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/daGYtQ/btsGyGGAlAC/malW4SNosZI5rPCRg0tPpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/daGYtQ/btsGyGGAlAC/malW4SNosZI5rPCRg0tPpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/daGYtQ/btsGyGGAlAC/malW4SNosZI5rPCRg0tPpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdaGYtQ%2FbtsGyGGAlAC%2FmalW4SNosZI5rPCRg0tPpK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1718&quot; height=&quot;1136&quot; data-filename=&quot;스크린샷 2024-04-12 오전 11.05.18.png&quot; data-origin-width=&quot;1718&quot; data-origin-height=&quot;1136&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;</description>
      <category>Frontend/Javascript</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/110</guid>
      <comments>https://developer-mobssie.tistory.com/110#entry110comment</comments>
      <pubDate>Fri, 12 Apr 2024 11:05:32 +0900</pubDate>
    </item>
    <item>
      <title>NPM 배포하기 - ESLINT</title>
      <link>https://developer-mobssie.tistory.com/108</link>
      <description>&lt;h3 style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;1. NPM 사이트에 회원가입하기&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;먼저, &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.npmjs.com/&quot;&gt;NPM의 공식 웹사이트&lt;/a&gt;에 접속해 회원가입을 합니다. NPM 계정이 있어야만 패키지를 배포할 수 있습니다.&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. GitHub에서 리포지토리 생성하기&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;코드를 관리할 GitHub 리포지토리를 생성합니다. 리포지토리 이름은 배포할 NPM 패키지의 이름과 일치시키는 것이 좋습니다.&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3. 리포지토리를 로컬에 클론하기&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;생성한 리포지토리를 로컬 컴퓨터에 클론합니다. 터미널에서 다음 명령어를 입력하세요:]]&lt;/p&gt;
&lt;pre id=&quot;code_1712323116500&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git clone &amp;lt;클론할 리포지토리 주소&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;4. package.json 파일 생성하기&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;클론한 리포지토리 폴더로 이동한 뒤, 아래 명령어를 실행하여 package.json 파일을 생성합니다. 이 파일은 패키지의 메타데이터를 담고 있으며, 프로젝트의 심장과도 같은 역할을 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712323967992&quot; class=&quot;gams&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;$ npm init -y
// 또는
$ npm init --scope=&amp;lt;조직-이름&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;--scope&amp;nbsp;옵션으로&amp;nbsp;패키지&amp;nbsp;이름&amp;nbsp;앞에&amp;nbsp;조직&amp;nbsp;이름을&amp;nbsp;붙일&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;예를&amp;nbsp;들어&amp;nbsp;npm&amp;nbsp;패키지&amp;nbsp;설치&amp;nbsp;시&amp;nbsp;다음과&amp;nbsp;같은&amp;nbsp;명령어로&amp;nbsp;설치&amp;nbsp;가능합니다.&lt;br /&gt;$&amp;nbsp;npm&amp;nbsp;install&amp;nbsp;@&amp;lt;조직&amp;nbsp;이름&amp;gt;/&amp;lt;패키지&amp;nbsp;이름&amp;gt;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;5. 배포할 코드 작성하기&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;루트 디렉토리에 index.js 파일을 만들고, 배포할 코드를 작성합니다. 예를 들어, ESLint 규칙을 정의한 모듈을 배포한다면 다음과 같이 작성할 수 있습니다:&lt;/p&gt;
&lt;pre id=&quot;code_1712323204865&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// ESLint 규칙 추가를 위한 설정 
module.exports = {
	rules: { 
    	'no-console': 'off'
    } 
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;6. NPM에 로그인하기&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;NPM에 패키지를 배포하기 전에 먼저 NPM 계정으로 로그인해야 합니다. 터미널에서 다음 명령어를 입력하세요:&lt;/p&gt;
&lt;pre id=&quot;code_1712323249775&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm login&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아이디와 비밀번호를 입력하면 로그인이 완료됩니다.&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;7. 패키지 배포하기&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;모든 준비가 끝났다면, 이제 패키지를 배포할 차례입니다. 다음 명령어로 배포를 진행하세요:&lt;/p&gt;
&lt;pre id=&quot;code_1712323271513&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm publish&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;배포가 성공적으로 완료되면, NPM 사이트에서 로그인한 뒤, 내가 올린 패키지를 확인할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-04-06 오전 9.21.52.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1490&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJ7W1b/btsGo76zdd7/d97IT5Yjy81ADkP6tFHqv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJ7W1b/btsGo76zdd7/d97IT5Yjy81ADkP6tFHqv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJ7W1b/btsGo76zdd7/d97IT5Yjy81ADkP6tFHqv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJ7W1b%2FbtsGo76zdd7%2Fd97IT5Yjy81ADkP6tFHqv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2816&quot; height=&quot;1490&quot; data-filename=&quot;스크린샷 2024-04-06 오전 9.21.52.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1490&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ESLINT (&lt;a href=&quot;https://eslint.org/docs/latest/use/getting-started&quot;&gt;https://eslint.org/docs/latest/use/getting-started&lt;/a&gt;)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;1. eslint 를 글로벌로 설치&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712362874001&quot; class=&quot;cmake&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;npm install -g eslint&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;프로젝트 내에서 설치&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: left;&quot;&gt;ESLint 설정 파일(&lt;/span&gt;.eslintrc&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;또는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;package.json&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;내의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;eslintConfig&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;섹션)을 자동으로 생성&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712362874002&quot; class=&quot;ada&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;eslint --init&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른프로젝트에 적용하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;yarn add &lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;@&amp;lt;조직&amp;nbsp;이름&amp;gt;/&amp;lt;패키지&amp;nbsp;이름&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712363131014&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;yarn add @purejjr/eslint-config --dev -W&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;ESLint 동작 방식&lt;/h4&gt;</description>
      <category>Dev Tool</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/108</guid>
      <comments>https://developer-mobssie.tistory.com/108#entry108comment</comments>
      <pubDate>Fri, 5 Apr 2024 22:21:22 +0900</pubDate>
    </item>
    <item>
      <title>nodemon</title>
      <link>https://developer-mobssie.tistory.com/107</link>
      <description>&lt;h3 style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Nodemon이란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;Nodemon은 Node.js 애플리케이션의 개발을 조금 더 발랄하게 만들어주는 유틸리티입니다. 코드에 변경이 생기면, 자동으로 애플리케이션을 재시작해줍니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;설치 방법&lt;/h3&gt;
&lt;pre id=&quot;code_1712149507943&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install -g nodemon&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;프로젝트의 개발 의존성으로만 추가하고 싶다면(&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;프로젝트 개발 시에만 사용하고 실제 운영 환경(production)에서는 사용X)&lt;/span&gt;:&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712149520103&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install --save-dev nodemon&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;예시 사용법&lt;/h3&gt;
&lt;pre id=&quot;code_1712149537968&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;nodemon app.js&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;app.js&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;는 메인 애플리케이션 파일입니다. 이제 Nodemon이 코드 변경을 감지하고, 애플리케이션을 자동으로 재시작해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Node.js</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/107</guid>
      <comments>https://developer-mobssie.tistory.com/107#entry107comment</comments>
      <pubDate>Wed, 3 Apr 2024 22:11:35 +0900</pubDate>
    </item>
    <item>
      <title>node cors 해결하기</title>
      <link>https://developer-mobssie.tistory.com/106</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;npm &lt;a href=&quot;https://www.npmjs.com/package/cors&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.npmjs.com/package/cors&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1711168396466&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;cors&quot; data-og-description=&quot;Node.js CORS middleware. Latest version: 2.8.5, last published: 5 years ago. Start using cors in your project by running &amp;#96;npm i cors&amp;#96;. There are 14357 other projects in the npm registry using cors.&quot; data-og-host=&quot;www.npmjs.com&quot; data-og-source-url=&quot;https://www.npmjs.com/package/cors&quot; data-og-url=&quot;https://www.npmjs.com/package/cors&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/3kl9n/hyVDxUVP4G/VnQxEeU8Q4KrDO7UlxZvV0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://www.npmjs.com/package/cors&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.npmjs.com/package/cors&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/3kl9n/hyVDxUVP4G/VnQxEeU8Q4KrDO7UlxZvV0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;cors&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Node.js CORS middleware. Latest version: 2.8.5, last published: 5 years ago. Start using cors in your project by running `npm i cors`. There are 14357 other projects in the npm registry using cors.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.npmjs.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cors 패키지를 설치해서 해결가능&lt;/p&gt;
&lt;pre id=&quot;code_1711168411349&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm i cors&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미들웨어를 추가&lt;/p&gt;
&lt;pre id=&quot;code_1711168512468&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const cors = require('cors')
app.use(cors())&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-23 오후 1.35.32.png&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;314&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bliff9/btsF0kylSSF/5c7vnKvyzXihCvu7etygsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bliff9/btsF0kylSSF/5c7vnKvyzXihCvu7etygsK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bliff9/btsF0kylSSF/5c7vnKvyzXihCvu7etygsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbliff9%2FbtsF0kylSSF%2F5c7vnKvyzXihCvu7etygsK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;694&quot; height=&quot;314&quot; data-filename=&quot;스크린샷 2024-03-23 오후 1.35.32.png&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;314&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;옵션 설정하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: left;&quot;&gt;특정 도메인만 허용하거나, 특정 HTTP 메서드만 허용하는 등의 세밀한 제어가 필요할 때는 &lt;/span&gt;cors&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: left;&quot;&gt; 미들웨어의 옵션을 설정할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1711182228472&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const corsOptions = {
  origin: 'https://example.com',
  optionsSuccessStatus: 200 // 일부 구형 브라우저를 위한 옵션
}

app.use(cors(corsOptions));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://example.com&quot;&gt;https://example.com&lt;/a&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: left;&quot;&gt; 도메인에서 오는 요청만 허용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;특정 경로에 대해 CORS 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: left;&quot;&gt;전체 앱이 아닌 특정 경로에 대해서만 CORS를 설정하고 싶을 때는, 해당 경로에 &lt;/span&gt;cors&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: left;&quot;&gt; 미들웨어를 적용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1711182302879&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;app.get('/products/:id', cors(), function (req, res, next) {
  res.json({msg: '이 경로는 CORS를 허용합니다!'});
})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Node.js</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/106</guid>
      <comments>https://developer-mobssie.tistory.com/106#entry106comment</comments>
      <pubDate>Sat, 23 Mar 2024 14:18:30 +0900</pubDate>
    </item>
    <item>
      <title>node로 API 만들기 (express)</title>
      <link>https://developer-mobssie.tistory.com/105</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;node express&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.npmjs.com/package/express&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.npmjs.com/package/express&lt;/a&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1711165060818&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm init
npm i express
node app.js&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-23 오후 12.42.26.png&quot; data-origin-width=&quot;1004&quot; data-origin-height=&quot;492&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1cH1c/btsF0u8Ln9w/BJKgLKAvBcVWnzmHmXZTJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1cH1c/btsF0u8Ln9w/BJKgLKAvBcVWnzmHmXZTJ0/img.png&quot; data-alt=&quot;node app.js로 실행이 되는지 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1cH1c/btsF0u8Ln9w/BJKgLKAvBcVWnzmHmXZTJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1cH1c%2FbtsF0u8Ln9w%2FBJKgLKAvBcVWnzmHmXZTJ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;537&quot; height=&quot;263&quot; data-filename=&quot;스크린샷 2024-03-23 오후 12.42.26.png&quot; data-origin-width=&quot;1004&quot; data-origin-height=&quot;492&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;node app.js로 실행이 되는지 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-23 오후 12.44.37.png&quot; data-origin-width=&quot;554&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkGgqr/btsF00GkejB/KC4Lf83TRKgJO1d7F8ySp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkGgqr/btsF00GkejB/KC4Lf83TRKgJO1d7F8ySp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkGgqr/btsF00GkejB/KC4Lf83TRKgJO1d7F8ySp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkGgqr%2FbtsF00GkejB%2FKC4Lf83TRKgJO1d7F8ySp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;511&quot; height=&quot;214&quot; data-filename=&quot;스크린샷 2024-03-23 오후 12.44.37.png&quot; data-origin-width=&quot;554&quot; data-origin-height=&quot;232&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;body parsing하기&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711166144534&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;app.use(express.json())
app.use(express.urlencoded({ extended: true }))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711166235527&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let id = 2;
const todoList = [{
  id: 1,
  test: '할일',
  done: false
}];

app.get('/api/todo', (req, res) =&amp;gt; {
  res.json(todoList)
})

app.post('/api/todo', (req, res) =&amp;gt; {
  const { test, done } = req.body;
  todoList.push({
    id: id++,
    test,
    done,
  });
  return res.send('success')
})

app.listen(3000, () =&amp;gt; {
  console.log('server');
})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버를 껏다가 다시 켜서 http://localhost:3000/api/todo에서 확인&lt;/p&gt;
&lt;pre class=&quot;json&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;[{&quot;id&quot;:1,&quot;test&quot;:&quot;할일&quot;,&quot;done&quot;:false}]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;POSTMAN으로도 잘 동작하는지 확인&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-23 오후 1.10.35.png&quot; data-origin-width=&quot;1260&quot; data-origin-height=&quot;710&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dEojHT/btsF3dDZgr8/kWSga5GIkf6oECIfqLjrnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dEojHT/btsF3dDZgr8/kWSga5GIkf6oECIfqLjrnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dEojHT/btsF3dDZgr8/kWSga5GIkf6oECIfqLjrnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdEojHT%2FbtsF3dDZgr8%2FkWSga5GIkf6oECIfqLjrnk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1260&quot; height=&quot;710&quot; data-filename=&quot;스크린샷 2024-03-23 오후 1.10.35.png&quot; data-origin-width=&quot;1260&quot; data-origin-height=&quot;710&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-23 오후 1.11.46.png&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;1166&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o0ZoT/btsF1r4yomf/4jYOk0UximS8VeGKjTfnz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o0ZoT/btsF1r4yomf/4jYOk0UximS8VeGKjTfnz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o0ZoT/btsF1r4yomf/4jYOk0UximS8VeGKjTfnz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fo0ZoT%2FbtsF1r4yomf%2F4jYOk0UximS8VeGKjTfnz1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;862&quot; height=&quot;1166&quot; data-filename=&quot;스크린샷 2024-03-23 오후 1.11.46.png&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;1166&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Node.js</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/105</guid>
      <comments>https://developer-mobssie.tistory.com/105#entry105comment</comments>
      <pubDate>Sat, 23 Mar 2024 13:12:29 +0900</pubDate>
    </item>
    <item>
      <title>[ETC] AWS EC2_콘솔에 로그인하기</title>
      <link>https://developer-mobssie.tistory.com/104</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;루트 사용자&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AWS 루트 사용자는 회원가입 시 만든 계정으로서 모든 AWS 권한을 갖고 있는 사용자&lt;/li&gt;
&lt;li&gt;이&amp;nbsp;계정은&amp;nbsp;탈취당할&amp;nbsp;시&amp;nbsp;복구가&amp;nbsp;매우&amp;nbsp;어려울&amp;nbsp;뿐만&amp;nbsp;아니라,&amp;nbsp;최근에는&amp;nbsp;해커들이&amp;nbsp;비트코인&amp;nbsp;채굴에&amp;nbsp;AWS&amp;nbsp;계정을&amp;nbsp;착취하여&amp;nbsp;사용하기&amp;nbsp;때문에&amp;nbsp;상상을&amp;nbsp;초월하는&amp;nbsp;과금폭탄을&amp;nbsp;맞을&amp;nbsp;수&amp;nbsp;있다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IAM 사용자 (&lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;Identity and Access Management)&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AWS&amp;nbsp;관리를&amp;nbsp;제외한&amp;nbsp;서비스&amp;nbsp;관리용&amp;nbsp;계정&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;IAM은 지역별(region) 서비스가 아닌 글로벌 서비스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;IAM 사용자는 IAM을 통해 생성한 사용자로 루트 사용자로부터 권한을 부여받은 서비스만 관리가 가능&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-02-08 오전 9.57.46.png&quot; data-origin-width=&quot;764&quot; data-origin-height=&quot;702&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pazqR/btsEyPsVQh1/lPY8kMjl2ABMjKqWXINFd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pazqR/btsEyPsVQh1/lPY8kMjl2ABMjKqWXINFd0/img.png&quot; data-alt=&quot;먼저 지역설정하기 지역을 설정해야 인스턴스에 접근했을때 응답이 빠르다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pazqR/btsEyPsVQh1/lPY8kMjl2ABMjKqWXINFd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpazqR%2FbtsEyPsVQh1%2FlPY8kMjl2ABMjKqWXINFd0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;407&quot; height=&quot;702&quot; data-filename=&quot;스크린샷 2024-02-08 오전 9.57.46.png&quot; data-origin-width=&quot;764&quot; data-origin-height=&quot;702&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;먼저 지역설정하기 지역을 설정해야 인스턴스에 접근했을때 응답이 빠르다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;먼저 지역설정합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;이유는 지역을 설정해야 인스턴스에 접근했을때 응답이 빠르기때문이죠.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스에서 EC2검색합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-02-08 오전 10.01.00.png&quot; data-origin-width=&quot;2144&quot; data-origin-height=&quot;970&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d2aD6T/btsECmvHkZP/jV5VPuBVh0tpKpnZfLvwM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d2aD6T/btsECmvHkZP/jV5VPuBVh0tpKpnZfLvwM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d2aD6T/btsECmvHkZP/jV5VPuBVh0tpKpnZfLvwM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd2aD6T%2FbtsECmvHkZP%2FjV5VPuBVh0tpKpnZfLvwM1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2144&quot; height=&quot;970&quot; data-filename=&quot;스크린샷 2024-02-08 오전 10.01.00.png&quot; data-origin-width=&quot;2144&quot; data-origin-height=&quot;970&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-02-08 오전 10.03.13.png&quot; data-origin-width=&quot;2148&quot; data-origin-height=&quot;1146&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWGhXk/btsEy26xcUa/nc9FtVSJcs6k5QSmDH8qxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWGhXk/btsEy26xcUa/nc9FtVSJcs6k5QSmDH8qxK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWGhXk/btsEy26xcUa/nc9FtVSJcs6k5QSmDH8qxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWGhXk%2FbtsEy26xcUa%2Fnc9FtVSJcs6k5QSmDH8qxK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2148&quot; height=&quot;1146&quot; data-filename=&quot;스크린샷 2024-02-08 오전 10.03.13.png&quot; data-origin-width=&quot;2148&quot; data-origin-height=&quot;1146&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인스턴스 &amp;gt; 인스턴스로 들어갑니다. 아직 인스턴스가 없기때문에 없다고 뜹니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인스턴스 시작을 누르고 Quick Start에서 Amazon Linux를 사용해볼께요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #c1bef9;&quot;&gt;t2.micro 프리 티어 사용가능&lt;/span&gt;은 체험판 인스턴스라고 할수있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-02-08 오전 10.09.17.png&quot; data-origin-width=&quot;1516&quot; data-origin-height=&quot;1490&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1ZhFS/btsEA6f3An1/1mP4h2MmMdLbFEoUEZ9W51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1ZhFS/btsEA6f3An1/1mP4h2MmMdLbFEoUEZ9W51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1ZhFS/btsEA6f3An1/1mP4h2MmMdLbFEoUEZ9W51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1ZhFS%2FbtsEA6f3An1%2F1mP4h2MmMdLbFEoUEZ9W51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1516&quot; height=&quot;1490&quot; data-filename=&quot;스크린샷 2024-02-08 오전 10.09.17.png&quot; data-origin-width=&quot;1516&quot; data-origin-height=&quot;1490&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-02-08 오전 10.15.47.png&quot; data-origin-width=&quot;1492&quot; data-origin-height=&quot;716&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEw1AD/btsECsCGxyB/7KJgpDuGDQmm1gkS0xkVw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEw1AD/btsECsCGxyB/7KJgpDuGDQmm1gkS0xkVw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEw1AD/btsECsCGxyB/7KJgpDuGDQmm1gkS0xkVw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEw1AD%2FbtsECsCGxyB%2F7KJgpDuGDQmm1gkS0xkVw1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;369&quot; height=&quot;177&quot; data-filename=&quot;스크린샷 2024-02-08 오전 10.15.47.png&quot; data-origin-width=&quot;1492&quot; data-origin-height=&quot;716&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock floatLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-02-08 오전 10.17.00.png&quot; data-origin-width=&quot;1520&quot; data-origin-height=&quot;1594&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WiJdF/btsEBYPlXlx/YIz49G3KMyiBkPOagTctw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WiJdF/btsEBYPlXlx/YIz49G3KMyiBkPOagTctw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WiJdF/btsEBYPlXlx/YIz49G3KMyiBkPOagTctw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWiJdF%2FbtsEBYPlXlx%2FYIz49G3KMyiBkPOagTctw0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;519&quot; height=&quot;544&quot; data-filename=&quot;스크린샷 2024-02-08 오전 10.17.00.png&quot; data-origin-width=&quot;1520&quot; data-origin-height=&quot;1594&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최소 8 로 사용해야하고 연습용이기 때문에 범용 SSD볼륨인 gp2를 선택하겠습니다. [&lt;a title=&quot;관련내용&quot; href=&quot;https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/ebs-volume-types.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;관련내용&lt;/a&gt;]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>firebase</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/104</guid>
      <comments>https://developer-mobssie.tistory.com/104#entry104comment</comments>
      <pubDate>Thu, 8 Feb 2024 09:47:41 +0900</pubDate>
    </item>
    <item>
      <title>Invalid hook call</title>
      <link>https://developer-mobssie.tistory.com/103</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Invalid&amp;nbsp;hook&amp;nbsp;call.&amp;nbsp;Hooks&amp;nbsp;can&amp;nbsp;only&amp;nbsp;be&amp;nbsp;called&amp;nbsp;inside&amp;nbsp;of&amp;nbsp;the&amp;nbsp;body&amp;nbsp;of&amp;nbsp;a&amp;nbsp;function&amp;nbsp;component.&amp;nbsp;This&amp;nbsp;could&amp;nbsp;happen&amp;nbsp;for&amp;nbsp;one&amp;nbsp;of&amp;nbsp;the&amp;nbsp;following&amp;nbsp;reasons:&lt;br /&gt;1.&amp;nbsp;You&amp;nbsp;might&amp;nbsp;have&amp;nbsp;mismatching&amp;nbsp;versions&amp;nbsp;of&amp;nbsp;React&amp;nbsp;and&amp;nbsp;the&amp;nbsp;renderer&amp;nbsp;(such&amp;nbsp;as&amp;nbsp;React&amp;nbsp;DOM)&lt;br /&gt;2.&amp;nbsp;You&amp;nbsp;might&amp;nbsp;be&amp;nbsp;breaking&amp;nbsp;the&amp;nbsp;Rules&amp;nbsp;of&amp;nbsp;Hooks&lt;br /&gt;3.&amp;nbsp;You&amp;nbsp;might&amp;nbsp;have&amp;nbsp;more&amp;nbsp;than&amp;nbsp;one&amp;nbsp;copy&amp;nbsp;of&amp;nbsp;React&amp;nbsp;in&amp;nbsp;the&amp;nbsp;same&amp;nbsp;app&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1682408435802&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;useEffect(()=&amp;gt; {
  const checkedItems = checkboxRefs.reduce&amp;lt;TCart[]&amp;gt;((res, ref, i)=&amp;gt; {
    if(ref.current!.checked) res.push(items[i])
    return res
  }, [])
  setCheckedCartState(checkedItems)
}, [items, formData])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; &lt;a href=&quot;https://ko.legacy.reactjs.org/docs/hooks-rules.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Hook의 규칙&lt;/a&gt;을 어기고 useEffect의 위치를 잘못 넣어서 나는 오타 에러.&lt;/p&gt;</description>
      <category>error 처리</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/103</guid>
      <comments>https://developer-mobssie.tistory.com/103#entry103comment</comments>
      <pubDate>Tue, 25 Apr 2023 16:49:42 +0900</pubDate>
    </item>
    <item>
      <title>PWA - 서비스 워커 웹 캐싱(service worker)</title>
      <link>https://developer-mobssie.tistory.com/102</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;* 서비스워커는 백그라운드에서 실행하는 스크립트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 클라이언트에 설치되는 프록시 =&amp;gt; Request를&amp;nbsp;가로채&amp;nbsp;Proxy&amp;nbsp;Server와&amp;nbsp;비슷하게&amp;nbsp;동작&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저 백그라운드에서 네트워크를 가로채는 Thread&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 캐싱은 CacheStorage를 사용. &lt;br /&gt;Sqlite 같은 클라이언트 데이터베이스인데, Key:value 로 구성된 데이터베이스&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ServiceWorker&amp;nbsp;적용&amp;nbsp;전&amp;nbsp;알아두어야할&amp;nbsp;점은&amp;nbsp;서비스워커는&amp;nbsp;보안상의&amp;nbsp;이유로&amp;nbsp;HTTPS에서만&amp;nbsp;실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;public폴더(index.html이&amp;nbsp;있는)에&amp;nbsp;생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인&amp;nbsp;script파일에&amp;nbsp;다음과&amp;nbsp;같이&amp;nbsp;service-worker를&amp;nbsp;불러오는&amp;nbsp;구문을&amp;nbsp;추가&lt;/p&gt;
&lt;pre id=&quot;code_1680513470236&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// navigator (브라우저)에 serviceWorker 기능이 있는지 확인
if (&quot;serviceWorker&quot; in navigator) {
  // 서비스워커 설치시 DOM 블로킹을 막아준다.
  window.addEventListener(&quot;load&quot;, function () {
    // 서비스워커를 register 하면 promise를 반환한다.
    navigator.serviceWorker
      .register(&quot;/sw.js&quot;)
      .then(() =&amp;gt; {
        console.log(&quot;서비스 워커가 등록되었다.&quot;);
      })
      .catch((error) =&amp;gt; {
        console.log(error);
      });
  });
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1680513709928&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// service-worker.js

var PRE_CACHE_NAME = &quot;캐시-스토리지1&quot;;
// 캐시하고 싶은 리소스
var urlsToCache = [
  &quot;/public/image/image1.png&quot;,
  &quot;/public/css/font-awesome.min.css&quot;,
];

// 서비스워커가 설치될 때
self.addEventListener(&quot;install&quot;, (event) =&amp;gt; {
  // 캐시 등록 이벤트가 끝날 때까지 기다려
  event.waitUntil(
    // '캐시-스토리지1'을 연다.
    // @return {Promise} 연결된 Cache Database를 반환한다.
    caches
      .open(PRE_CACHE_NAME)
      .then((cache) =&amp;gt; {
        console.log(&quot;캐시 디비와 연결됨&quot;);
        // addAll 메소드로 내가 캐싱할 리소스를 다 넣어주자.
        return cache.addAll(urlsToCache);
      })
      .then(() =&amp;gt; {
        // 설치 후에 바로 활성화 단계로 들어갈 수 있게 해준다.
        return self.skipWaiting();
      })
  );
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오래된&amp;nbsp;캐시&amp;nbsp;삭제&lt;/p&gt;
&lt;pre id=&quot;code_1680513810808&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 서비스 워커가 활성화 될 때
self.addEventListener(&quot;activate&quot;, (event) =&amp;gt; {
  // 영구적으로 가져갈 캐시 스트리지 화이트리스트
  var cacheWhiteList = [PRE_CACHE_NAME, DYNAMIC_CACHE_NAME];

  event.waitUntil(
    // 캐시 스토리지의 모든 스토리지명을 가져온다.
    caches.keys().then((cacheNames) =&amp;gt; {
      // 캐시를 삭제하는 건 Promise를 반환하므로 Promise.all을 사용해 끝날 시점을 잡아야한다.
      return Promise.all(
        // 이 결과는 [Promise, Promise...] 형태가 되시겠다.
        cacheNames.map((cacheName) =&amp;gt; {
          // 각각의 캐시 스토리지명이 화이트 리스트와 같지 않을 경우
          if (cacheWhitelist.indexOf(cacheName) === -1) {
            // 캐시를 삭제하는 Promise를 배열에 추가한다.
            return caches.delete(cacheName);
          }
        })
      );
    })
  );

  // activate 시에는 clients claim 메소드를 호출해서
  // 브라우저에 대한 제어권을 가져와야한다.
  return self.clients.claim();
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과적으로&amp;nbsp;DYNAMIC_CACHE_NAME이&amp;nbsp;아닌&amp;nbsp;캐시&amp;nbsp;스토리지는&amp;nbsp;삭제된다.&lt;/p&gt;</description>
      <category>Frontend/Javascript</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/102</guid>
      <comments>https://developer-mobssie.tistory.com/102#entry102comment</comments>
      <pubDate>Tue, 25 Apr 2023 16:39:44 +0900</pubDate>
    </item>
    <item>
      <title>GraphQLError: Syntax Error: Expected Name, found &amp;quot;$&amp;quot;</title>
      <link>https://developer-mobssie.tistory.com/101</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;GraphQLError:&amp;nbsp;Syntax&amp;nbsp;Error:&amp;nbsp;Expected&amp;nbsp;Name,&amp;nbsp;found&amp;nbsp;&quot;$&quot;&lt;/p&gt;
&lt;pre id=&quot;code_1672579265478&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export const UPDATE_CART = gql`
  mutation UPDATE_CART($id: id, $amount: amount) {
    id
    imageUrl
    price
    title
    amount
  }
`&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* $표기를 안붙여서 나는 에러&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;($episode: Episode)변수 정의&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://graphql.org/learn/queries/#variables&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://graphql.org/learn/queries/#variables&lt;/a&gt;&lt;/p&gt;</description>
      <category>error 처리</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/101</guid>
      <comments>https://developer-mobssie.tistory.com/101#entry101comment</comments>
      <pubDate>Sun, 1 Jan 2023 22:27:57 +0900</pubDate>
    </item>
    <item>
      <title>스택이용해 배열 거꾸로 출력하기</title>
      <link>https://developer-mobssie.tistory.com/100</link>
      <description>&lt;pre id=&quot;code_1666606409291&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(num_list) {
    const answer = [];
    while(num_list.length){
       answer.push(num_list.pop())     
    }
    return answer;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘, 자료구조</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/100</guid>
      <comments>https://developer-mobssie.tistory.com/100#entry100comment</comments>
      <pubDate>Mon, 24 Oct 2022 19:13:50 +0900</pubDate>
    </item>
    <item>
      <title>[leetcode] 20. Valid Parentheses</title>
      <link>https://developer-mobssie.tistory.com/99</link>
      <description>&lt;pre id=&quot;code_1666603920866&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function isValid(s) {
    let stack =[];
    let obj = {
        '(': ')',
        '[': ']',
        '{': '}'
    }
    for(let i = 0; i &amp;lt; s.length; i++){
        if(s[i] === '(' || s[i] === '{' || s[i] === '['){
            stack.push(s[i]);
        } else {
            let peek = stack.pop();
            if(s[i] !== obj[peek]){
                return false
            }
        }
    }
    return !stack.length;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://leetcode.com/problems/valid-parentheses/submissions/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://leetcode.com/problems/valid-parentheses/submissions/&lt;/a&gt;&lt;/p&gt;</description>
      <category>알고리즘, 자료구조</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/99</guid>
      <comments>https://developer-mobssie.tistory.com/99#entry99comment</comments>
      <pubDate>Mon, 24 Oct 2022 18:56:47 +0900</pubDate>
    </item>
    <item>
      <title>[vue] Property 'props' does not exist on type '{}' (ts 2339)</title>
      <link>https://developer-mobssie.tistory.com/98</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-10-24 오후 5.02.35.png&quot; data-origin-width=&quot;770&quot; data-origin-height=&quot;285&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LDi63/btrPmEVGge7/OL16kaYWm16B6GzPv2pzSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LDi63/btrPmEVGge7/OL16kaYWm16B6GzPv2pzSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LDi63/btrPmEVGge7/OL16kaYWm16B6GzPv2pzSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLDi63%2FbtrPmEVGge7%2FOL16kaYWm16B6GzPv2pzSk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;770&quot; height=&quot;285&quot; data-filename=&quot;스크린샷 2022-10-24 오후 5.02.35.png&quot; data-origin-width=&quot;770&quot; data-origin-height=&quot;285&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #213547;&quot;&gt;TypeScript가 구성 요소 옵션 내에서 유형을 올바르게 추론할 수 있도록 하려면 &lt;u&gt;&lt;b&gt;defineComponent()&lt;/b&gt;&lt;/u&gt;사용하여 구성 요소를 정의해야한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1666598419713&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { defineComponent } from '@vue/composition-api';
export default defineComponent({
  name: 'ColorList',
  props: {
    colorInfo: { type: Array, default: ()=&amp;gt; [] },
  },
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식문서 참고 : &lt;a href=&quot;https://vuejs.org/guide/typescript/overview.html#definecomponent&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://vuejs.org/guide/typescript/overview.html#definecomponent&lt;/a&gt;&lt;/p&gt;</description>
      <category>error 처리</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/98</guid>
      <comments>https://developer-mobssie.tistory.com/98#entry98comment</comments>
      <pubDate>Mon, 24 Oct 2022 17:05:26 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 분수의 덧셈</title>
      <link>https://developer-mobssie.tistory.com/97</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;[프로그래머스]&amp;nbsp;분수의&amp;nbsp;덧셈&lt;/p&gt;
&lt;pre id=&quot;code_1666165470029&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(denum1, num1, denum2, num2) {
    let answer = [];
    let denum = denum1 * num2 + num1 * denum2; // 분자
    let num = num1 * num2; // 분모
    
    function getGcd(a, b) {
        while ( b !== 0) {
            n = a % b;
            a = b;
            b = n;
        }
        return a;
    }
    const calcGcd = getGcd(denum, num); // 분자와 분모의 최대공약수
    return [denum, num].map(v =&amp;gt; v/calcGcd);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최대공약수를 사용해서 분자와 분모의 초대공약수를 구해서 나눠 리턴한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최대공약수 구하는 방법은 이전 블로그 내용을 참고.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer-mobssie.tistory.com/96&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer-mobssie.tistory.com/96&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘, 자료구조</category>
      <category>분수의 덧셈</category>
      <category>자바스크립트</category>
      <category>프로그래머스</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/97</guid>
      <comments>https://developer-mobssie.tistory.com/97#entry97comment</comments>
      <pubDate>Wed, 19 Oct 2022 16:47:25 +0900</pubDate>
    </item>
    <item>
      <title>[js] 최대 공약수, 최소공배수 구하기 (feat. 유클리드 호제법)</title>
      <link>https://developer-mobssie.tistory.com/96</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;공약수는 두 개 이상의 자연수의 공통된 약수이고, &lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;공약수 중에서 가장 큰 공약수를 바로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;최대공약수&lt;/b&gt;라 하고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;두 수의 공약수가 1밖에 없을 때 이 두 수를 &lt;b&gt;서로소&lt;/b&gt;라고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;12와 18의 최대공약수는?&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;12의 약수: 1, 2, 3, 4, &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;6&lt;/b&gt;&lt;/span&gt;, 12&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;18의 약수: 1, 2, 3, &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;6&lt;/b&gt;&lt;/span&gt;, 9, 18&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;두 수의 공약수는 1, 2, 3, 6이고 이 중 가장 큰 공약수, 최대공약수가 6&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;유클리드 호제법을 이용한 풀이&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- a, b 를 서로 나눌때, 나누어진다면 b가 최대 공약수 이다. (a&amp;gt;b)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 만약 a,b가 나누어지지 않으면 b와 a를 b로 나눈 나머지를 다시 나눈다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 서로가 나누어지면 a%b 가 최대공약수이다. 나누어지지 않는다면 위처럼 b와 a를 b를 나눈 나머지를 다시 나눈다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1666156723996&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const solutuon = (n, m) =&amp;gt; {
  const gcd = (a, b) =&amp;gt; {
    if (b === 0) return a; // 나누어지면 a 리턴
    return gcd(b, a % b); // 나누어지지 않는다면 b와 a%b를 다시 나눈다
  };
  const lcm = (a, b) =&amp;gt; (a * b) / gcd(a, b); // 두 수의 곱을 최대공약수로 나눈다.
  return console.log(
    `최대 공약수는? ${gcd(n, m)}, 최대 공배수는? ${lcm(n, m)}`
  );
};
console.log(solutuon(6, 12));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는&lt;/p&gt;
&lt;pre id=&quot;code_1666158764224&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let N = 24, M = 18;

function getGcd(a, b) {
  while (b !== 0) {
    n = a % b;
    a = b;
    b = n;
  }
  return a;
}

let gcd = getGcd(N, M); //최대공약수
let gcf = (N * M) / gcd; //최소공배수&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;유클리드 호제법(- 互除法, Euclidean Algorithm)은 2개의 자연수 또는 정식(整式)의&lt;/span&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;최대공약수(Greatest Common Divisor)&lt;/b&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;를 구하는 알고리즘의 하나이다.&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;호제법이란 말은 두 수가 서로(互) 상대방 수를 나누어(除)서 결국 원하는 수를 얻는 알고리즘을 나타낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;2개의 자연수(또는 정식) a, b에 대해서 a를 b로 나눈 나머지를 r이라 하면(단, a&amp;gt;b), a와 b의 최대공약수는 b와 r의 최대공약수와 같다.&lt;br /&gt;이 성질에 따라, b를 r로 나눈 나머지 r'를 구하고, 다시 r을 r'로 나눈 나머지를 구하는 과정을 반복하여 나머지가 0이 되었을 때 나누는 수가 a와 b의 최대공약수이다.&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 명시적으로 기술된 가장 오래된 알고리즘으로서도 알려져 있으며, 기원전 300년경에 쓰인 유클리드의 《원론》 제7권, 명제 1부터 3까지에 해당한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 위키백과, 우리 모두의 백과사전.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;약수 구하기 (배열)&lt;/p&gt;
&lt;pre id=&quot;code_1666157408642&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(num) {
	const arr = [];
    for(let i = 2; i &amp;lt; num; i++){
    	if(num % i === 0) {
        	arr.push(i)
        }
    }
    return arr;
}


console.log(solution(28));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;배수 구하기 (배열)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1666157775401&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(num){
	let arr = [];
	for(let i = 0; i &amp;lt;= 1000; i++) {
    	if(i % num === 0 &amp;amp;&amp;amp; i !== 0){
        	arr.push(i)
        }
    }
    return arr;
}

console.log(solution(50))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘, 자료구조</category>
      <category>JavaScript</category>
      <category>JS</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/96</guid>
      <comments>https://developer-mobssie.tistory.com/96#entry96comment</comments>
      <pubDate>Wed, 19 Oct 2022 15:54:45 +0900</pubDate>
    </item>
    <item>
      <title>[node] node 삭제 및 nvm이용해 node 설치하기(feat. brew)</title>
      <link>https://developer-mobssie.tistory.com/95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;여러가지 노드버전을 사용해야하는경우&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;기존 노드 삭제후&lt;/span&gt;&lt;/b&gt; 설치할것!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://velog.io/@minidoo/Node-mac%EC%97%90%EC%84%9C-Node.js-%EC%99%84%EC%A0%84%ED%9E%88-%EC%82%AD%EC%A0%9C%ED%95%98%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://velog.io/@minidoo/Node-mac%EC%97%90%EC%84%9C-Node.js-%EC%99%84%EC%A0%84%ED%9E%88-%EC%82%AD%EC%A0%9C%ED%95%98%EA%B8%B0&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;홈브로우 설치(&lt;a href=&quot;https://brew.sh/index_ko.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://brew.sh/index_ko.html&lt;/a&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;* brew 여부 체크&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1665733115233&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ which brew&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Homebrew가 설치되어있지 않다면&amp;nbsp;&lt;/span&gt;brew not found&lt;span style=&quot;color: #000000;&quot;&gt;가 출력된다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설치되어있다면, 다음 명령어로 기존 Homebrew를 삭제&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1665733315612&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ /bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;brew&lt;span style=&quot;color: #000000;&quot;&gt;를 실행했을 때&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;command not found&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;에러가 나면 잘 삭제된 것&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;간혹 삭제해도&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;brew&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;명령어가 남아있거나, Homebrew가 서로 다른 경로에 여러 벌 설치되는 경우가 있는데, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;brew&lt;span style=&quot;color: #000000;&quot;&gt;가 실행되지 않을 때까지 uninstall을 반복하면 된다고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설치후 실행&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1665733701028&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ echo 'eval &quot;$(/opt/homebrew/bin/brew shellenv)&quot;' &amp;gt;&amp;gt; /Users/&amp;lt;USER_ID&amp;gt;/.zprofile
$ eval &quot;$(/opt/homebrew/bin/brew shellenv)&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1665733751612&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ which brew
/opt/homebrew/bin/brew

$ brew --version
Homebrew 3.6.5
Homebrew/homebrew-core (git revision b3db74ae86e; last commit 2022-10-14)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;* 설치&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1665728491819&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ /bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;* 브로우를 이용해 nvm 설치 시작&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1665727889229&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ brew install nvm&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;* 환경 셋팅&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1665727901738&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# zsh 은 둘 중에 하나만 사용해도 된다.
$ vim ~/.zshenv 
$ vim ~/.zprofile 

# bash
$ vim ~/.bash_profile&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;* Edit, i 를 눌러 insert해서 아래 내용을 zsh, bash안에 넣기&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1665727921196&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export NVM_DIR=&quot;$HOME/.nvm&quot;
[ -s &quot;/opt/homebrew/opt/nvm/nvm.sh&quot; ] &amp;amp;&amp;amp; \. &quot;/opt/homebrew/opt/nvm/nvm.sh&quot;  # This loads nvm
[ -s &quot;/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm&quot; ] &amp;amp;&amp;amp; \. &quot;/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm&quot;  # This loads nvm bash_completion&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;상단 내용을 넣고 ESC + wq!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1665728237438&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# zsh 
$ source ~/.zshenv 
$ source ~/.zprofile 

# bash
$ source ~/.bash_profile&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;source로 환경 변수를 적용 시킨다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1665728266100&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ nvm -v&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;버전확인해 설치가 잘 되었는지 확인해 보고 원하는 node 버전을 설치한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1665728290195&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ nvm install 16.0.0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;사용시&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1665728331732&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ nvm ls
$ nvm use 16.0.0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참조, &lt;a href=&quot;https://www.lainyzine.com/ko/article/how-to-install-homebrew-for-m1-apple-silicon/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.lainyzine.com/ko/article/how-to-install-homebrew-for-m1-apple-silicon/&lt;/a&gt;&lt;/p&gt;</description>
      <category>error 처리</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/95</guid>
      <comments>https://developer-mobssie.tistory.com/95#entry95comment</comments>
      <pubDate>Fri, 14 Oct 2022 15:21:58 +0900</pubDate>
    </item>
    <item>
      <title>순열</title>
      <link>https://developer-mobssie.tistory.com/91</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #57606a;&quot;&gt;순열이란, 서로 다른 N개 중에서 R개를 선택하는 경우 (순서 중요&lt;/span&gt; &lt;span style=&quot;background-color: #ffffff; color: #57606a;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;swap을 이용한 순열 만들기&lt;/h2&gt;
&lt;pre class=&quot;zephir&quot;&gt;&lt;code&gt;/**
 *
 * @param {array} array
 * @param {number} deep
 * @param {number} target
 */
const permutation = (array, res = [], target = array.length, deep = 0) =&amp;gt; {
	if (deep === target) {
		res.push(array.slice(0, target));
		return;
	}
	for (let index = deep; index &amp;lt; array.length; index++) {
		swap(array, deep, index);
		permutation(array, res, target, deep + 1);
		swap(array, deep, index);
	}
};

const swap = (array, a, b) =&amp;gt; {
	let tmp = array[a];
	array[a] = array[b];
	array[b] = tmp;
};

const getPermutationList = (array, target) =&amp;gt; {
	let res = [];
	permutation(array, res, target);
	return res;
};

const array = Array(3)
	.fill()
	.map((_, i) =&amp;gt; i + 1);
console.log(getPermutationList(array));

/* --------------------------------------------------
[ 1, 2, 3 ]
[ 1, 3, 2 ]
[ 2, 1, 3 ]
[ 2, 3, 1 ]
[ 3, 2, 1 ]
[ 3, 1, 2 ]
*/&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘, 자료구조</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/91</guid>
      <comments>https://developer-mobssie.tistory.com/91#entry91comment</comments>
      <pubDate>Sat, 17 Sep 2022 11:08:23 +0900</pubDate>
    </item>
    <item>
      <title>CI/CD</title>
      <link>https://developer-mobssie.tistory.com/90</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CI/CD&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CI는 빌드/테스트 자동화 과정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CD는&amp;nbsp;간단히&amp;nbsp;말하면&amp;nbsp;배포&amp;nbsp;자동화&amp;nbsp;과정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/90</guid>
      <comments>https://developer-mobssie.tistory.com/90#entry90comment</comments>
      <pubDate>Thu, 15 Sep 2022 19:54:07 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 성격 유형 검사하기</title>
      <link>https://developer-mobssie.tistory.com/89</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잇몸으로 윽깬 나의 코드&lt;/p&gt;
&lt;pre id=&quot;code_1660898048956&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(survey, choices){
    let answer = ''
    let selectType = ''
    let score = [0, 3, 2, 1, 0, 1, 2, 3]
    let surveyType = ['RT','CF','JM','AN']
    let surveyList = surveyType.join('').split('')
    let surveyMap = new Map()
    
    for(let i = 0; i &amp;lt; surveyList.length; i++){
        surveyMap.set(surveyList[i], 0)
    }
    for(let i = 0; i &amp;lt; survey.length; i++){
        if(choices[i] &amp;gt; 4) selectType = survey[i].charAt(1)
        else if(choices[i] &amp;lt; 4) selectType = survey[i].charAt(0)
        surveyMap.set(selectType, surveyMap.get(selectType) + score[choices[i]])
    }
    
    answer = surveyType.map(v =&amp;gt; {
        const keys = v.split('')
        return (surveyMap.get(keys[0]) || 0) &amp;gt;= (surveyMap.get(keys[1]) || 0) ? keys[0] : keys[1]
    })
    
    return answer.join('');
}
const survey = ['AN', 'CF', 'MJ', 'RT', 'NA']
const choices = [5, 3, 2, 7, 5]
solution(survey, choices)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참조하고 수정한 다른 코드&lt;/p&gt;
&lt;pre id=&quot;code_1660890417458&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(survey, choices){
    let answer = ''
    let surveyType = ['RT','CF','JM','AN']
    let surveyList = surveyType.join('').split('')
    
    var surveyMap = new Map()
    for(let i = 0; i &amp;lt; surveyList.length; i++){
        surveyMap.set(surveyList[i], 0)
    }
    choices.forEach((score, i) =&amp;gt; {
        let [A, B] = survey[i].split('');
        if(score &amp;gt; 4) surveyMap.set(B, surveyMap.get(B)+score-4);
        else if(score &amp;lt; 4) surveyMap.set(A, surveyMap.get(A)+4-score);
    })
    answer = surveyType.map(v =&amp;gt; {
        const keys = v.split('')
        return (surveyMap.get(keys[0]) || 0) &amp;gt;= (surveyMap.get(keys[1]) || 0) ? keys[0] : keys[1]
    })
    
    return answer.join('');
}
const survey = ['AN', 'CF', 'MJ', 'RT', 'NA']
const choices = [5, 3, 2, 7, 5]
solution(survey, choices)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;j&lt;/p&gt;</description>
      <category>알고리즘, 자료구조</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/89</guid>
      <comments>https://developer-mobssie.tistory.com/89#entry89comment</comments>
      <pubDate>Fri, 19 Aug 2022 15:28:46 +0900</pubDate>
    </item>
    <item>
      <title>ES2022 (ES13) Class Fields 변경된 내용</title>
      <link>https://developer-mobssie.tistory.com/88</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Class&amp;nbsp;Public&amp;nbsp;Instance&amp;nbsp;Fields&amp;nbsp;&amp;amp;&amp;nbsp;Private&amp;nbsp;Instance&amp;nbsp;Fields&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;before&lt;/p&gt;
&lt;pre id=&quot;code_1660794136635&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class ColorButton extends HTMLElement {
  
  constructor() {
    this.color = &quot;red&quot;
    this._clicked = false
  }
}

const button = new ColorButton()
// Public fields can be accessed and changed by anyone
button.color = &quot;blue&quot; 

// Curse your sudden but inevitable betrayal 
console.log(button._clicked) // Prints: false, can be accessed from the instance
button._clicked = true // Doesn't throw an error, can be read from the instance&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;after : 필드를 정의와 동시에 초기화가 가능해졌다.&lt;/p&gt;
&lt;pre id=&quot;code_1660794156053&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class ColorButton extends HTMLElement {
  color = &quot;red&quot;
  _clicked = false
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;after : &lt;span style=&quot;background-color: #ffffff; color: #3d4852;&quot;&gt;private fields _ 대신 #사용해 프라이빗하게 사용 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1660794297004&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class ColorButton extends HTMLElement {
  // All fields are public by default
  color = &quot;red&quot;

  // Private fields start with a #, can only be changed from inside the class
  #clicked = false
}

const button = new ColorButton()
// Public fields can be accessed and changed by anyone
button.color = &quot;blue&quot;

// SyntaxError here 
console.log(button.#clicked) // Cannot be read from outside
button.#clicked = true // Cannot be assigned a value from outside&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fafafa; color: #49545e;&quot;&gt;Private instance methods and accessors&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1660794593347&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Banner extends HTMLElement {
  // Private variable that cannot be reached directly from outside, but can be modified by the methods inside:

  #slogan = &quot;Hello there!&quot;
  #counter = 0

  // private getters and setters (accessors):

  get #slogan() {return #slogan.toUpperCase()}
  set #slogan(text) {this.#slogan = text.trim()}

  get #counter() {return #counter}
  set #counter(value) {this.#counter = value}

  constructor() {
    super();
    this.onmouseover = this.#mouseover.bind(this);
  }

  // private method:
  #mouseover() {
    this.#counter = this.#counter++;
    this.#slogan = `Hello there! You've been here ${this.#counter} times.`
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;https://yagmurcetintas.com/journal/whats-new-in-es2022?ref=morioh.com&amp;amp;utm_source=morioh.com&lt;/p&gt;</description>
      <category>Frontend/Javascript</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/88</guid>
      <comments>https://developer-mobssie.tistory.com/88#entry88comment</comments>
      <pubDate>Fri, 19 Aug 2022 12:11:47 +0900</pubDate>
    </item>
    <item>
      <title>ES2022 (ES13) Top-level Await Operator</title>
      <link>https://developer-mobssie.tistory.com/87</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;async 없이 사용 가능해졌다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;import {getUser} from &quot;./data/User&quot;
let user = await getUser();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;https://yagmurcetintas.com/journal/whats-new-in-es2022?ref=morioh.com&amp;amp;utm_source=morioh.com&lt;/p&gt;</description>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/87</guid>
      <comments>https://developer-mobssie.tistory.com/87#entry87comment</comments>
      <pubDate>Thu, 18 Aug 2022 12:37:16 +0900</pubDate>
    </item>
    <item>
      <title>ES2021 (ES12) Logical assignment operators (논리 할당 연산자)</title>
      <link>https://developer-mobssie.tistory.com/86</link>
      <description>&lt;pre id=&quot;code_1660793005458&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// before
obj.prop = obj.prop || foo(); // obj.prop이 잘못된 값일 경우 할당
obj.prop = obj.prop &amp;amp;&amp;amp; foo(); // obj.prop이 올바른 값일 경우 할당
obj.prop = obj.prop ?? foo(); // obj.prop이 null이나 undefined일 경우 할당

// after
obj.prop ||= foo();
obj.prop &amp;amp;&amp;amp;= foo();
obj.prop ??= foo();&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Frontend/Javascript</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/86</guid>
      <comments>https://developer-mobssie.tistory.com/86#entry86comment</comments>
      <pubDate>Thu, 18 Aug 2022 12:23:30 +0900</pubDate>
    </item>
    <item>
      <title>[monorepo] nx를 이용하여 App 생성하기</title>
      <link>https://developer-mobssie.tistory.com/85</link>
      <description>&lt;pre id=&quot;code_1659494955831&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npx create-nx-workspace [만들고 싶은 APP 이름] --preset=react&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;nx는 npx 를 이용하여 workspace를 생성할 수 있고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고 :&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://nx.dev/generators/workspace-generators&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://nx.dev/generators/workspace-generators&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://medium.com/@trustyoo86/nx%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-react-monorepo-%EB%A7%8C%EB%93%A4%EA%B8%B0-workspace-%EB%A7%8C%EB%93%A4%EA%B8%B0-a53cd5374bcd&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://medium.com/@trustyoo86/nx%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-react-monorepo-%EB%A7%8C%EB%93%A4%EA%B8%B0-workspace-%EB%A7%8C%EB%93%A4%EA%B8%B0-a53cd5374bcd&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1659495035069&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;nx를 이용한 react monorepo 만들기 &amp;mdash; workspace 만들기&quot; data-og-description=&quot;monorepo란, 다양한 모듈을 여러개의 repository로 관리하지 않고, 하나의 repository에서 패키지 등으로 분기하여 관리하는 것을 의미합니다.&quot; data-og-host=&quot;medium.com&quot; data-og-source-url=&quot;https://medium.com/@trustyoo86/nx%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-react-monorepo-%EB%A7%8C%EB%93%A4%EA%B8%B0-workspace-%EB%A7%8C%EB%93%A4%EA%B8%B0-a53cd5374bcd&quot; data-og-url=&quot;https://medium.com/@trustyoo86/nx%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-react-monorepo-%EB%A7%8C%EB%93%A4%EA%B8%B0-workspace-%EB%A7%8C%EB%93%A4%EA%B8%B0-a53cd5374bcd&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/s9OJd/hyPjl7g3ad/U3zqGyxW7W459x1gFH1if0/img.jpg?width=1200&amp;amp;height=605&amp;amp;face=0_0_1200_605,https://scrap.kakaocdn.net/dn/jjP91/hyPhrgVtDh/CNoOlMobNVtc4KAKZzROX0/img.png?width=474&amp;amp;height=1030&amp;amp;face=0_0_474_1030,https://scrap.kakaocdn.net/dn/vQMMS/hyPhze0pTa/xXeFMjEFDbSOqrlfW7CRq1/img.jpg?width=1400&amp;amp;height=706&amp;amp;face=0_0_1400_706&quot;&gt;&lt;a href=&quot;https://medium.com/@trustyoo86/nx%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-react-monorepo-%EB%A7%8C%EB%93%A4%EA%B8%B0-workspace-%EB%A7%8C%EB%93%A4%EA%B8%B0-a53cd5374bcd&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://medium.com/@trustyoo86/nx%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-react-monorepo-%EB%A7%8C%EB%93%A4%EA%B8%B0-workspace-%EB%A7%8C%EB%93%A4%EA%B8%B0-a53cd5374bcd&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/s9OJd/hyPjl7g3ad/U3zqGyxW7W459x1gFH1if0/img.jpg?width=1200&amp;amp;height=605&amp;amp;face=0_0_1200_605,https://scrap.kakaocdn.net/dn/jjP91/hyPhrgVtDh/CNoOlMobNVtc4KAKZzROX0/img.png?width=474&amp;amp;height=1030&amp;amp;face=0_0_474_1030,https://scrap.kakaocdn.net/dn/vQMMS/hyPhze0pTa/xXeFMjEFDbSOqrlfW7CRq1/img.jpg?width=1400&amp;amp;height=706&amp;amp;face=0_0_1400_706');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;nx를 이용한 react monorepo 만들기 &amp;mdash; workspace 만들기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;monorepo란, 다양한 모듈을 여러개의 repository로 관리하지 않고, 하나의 repository에서 패키지 등으로 분기하여 관리하는 것을 의미합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;medium.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Javascript</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/85</guid>
      <comments>https://developer-mobssie.tistory.com/85#entry85comment</comments>
      <pubDate>Fri, 5 Aug 2022 15:21:32 +0900</pubDate>
    </item>
    <item>
      <title>[monorepo] 모노레포 nx 설치</title>
      <link>https://developer-mobssie.tistory.com/83</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;모노레포 환경 설치&lt;/p&gt;
&lt;pre id=&quot;code_1658285070575&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo npm install -g nx
npm create-nx-workspace&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-07-20 오전 11.54.28.png&quot; data-origin-width=&quot;759&quot; data-origin-height=&quot;202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/H9fkd/btrHKPhJqW1/DWTNFkR7E4kANoCH6pMNy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/H9fkd/btrHKPhJqW1/DWTNFkR7E4kANoCH6pMNy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/H9fkd/btrHKPhJqW1/DWTNFkR7E4kANoCH6pMNy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FH9fkd%2FbtrHKPhJqW1%2FDWTNFkR7E4kANoCH6pMNy1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;759&quot; height=&quot;202&quot; data-filename=&quot;스크린샷 2022-07-20 오전 11.54.28.png&quot; data-origin-width=&quot;759&quot; data-origin-height=&quot;202&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* workspace name : 작업공간에 일반적으로 조직 이름인 이름을 지정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리 조직의 모든 프로젝트를 포함하는 모델 리포지토리이므로 회사의 이름을 지정하거나 이름을 넣는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-07-20 오전 11.48.45.png&quot; data-origin-width=&quot;827&quot; data-origin-height=&quot;192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ncgmj/btrHIHFA6hU/IVYR0MNQz4Y1JpzuE6AeJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ncgmj/btrHIHFA6hU/IVYR0MNQz4Y1JpzuE6AeJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ncgmj/btrHIHFA6hU/IVYR0MNQz4Y1JpzuE6AeJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNcgmj%2FbtrHIHFA6hU%2FIVYR0MNQz4Y1JpzuE6AeJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;827&quot; height=&quot;192&quot; data-filename=&quot;스크린샷 2022-07-20 오전 11.48.45.png&quot; data-origin-width=&quot;827&quot; data-origin-height=&quot;192&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* What to create in the new workspace : 내부에 단일 응용프로그램을 생성하게된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-07-20 오후 12.00.33.png&quot; data-origin-width=&quot;186&quot; data-origin-height=&quot;537&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfuj7t/btrHIlJbMmV/B0GRS8ZlLAj8lgfxbU2fjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfuj7t/btrHIlJbMmV/B0GRS8ZlLAj8lgfxbU2fjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfuj7t/btrHIlJbMmV/B0GRS8ZlLAj8lgfxbU2fjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcfuj7t%2FbtrHIlJbMmV%2FB0GRS8ZlLAj8lgfxbU2fjk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;186&quot; height=&quot;537&quot; data-filename=&quot;스크린샷 2022-07-20 오후 12.00.33.png&quot; data-origin-width=&quot;186&quot; data-origin-height=&quot;537&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단일 저장소는 여러개의 서로 다른 프로젝트를 포함하는 저장소일 뿐이고&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잠재적으로 전체 조직의 모든 단일 프로젝트 일 수 도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모두 같은 유형일 필요는 없고 프로젝트 환경을 새로 만들 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;react, angular, vue, express, next.js 등 설정할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;app폴더 안에 여러 다른 응용 프로그램 간 공유하려는 모든 코드는 이 lib 폴더 안에 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서로 다른 앱간에 쉽게 공유할 수 있다는 이점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;libs 폴더에 일종의 공유 ui 라이브러리를 가질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 응용 프로그램에 단일 라이브러리를 사용 할 수있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[확장프로그램 : nx console]&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-07-20 오후 12.17.29.png&quot; data-origin-width=&quot;364&quot; data-origin-height=&quot;588&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctmEYb/btrHL2nMGnx/0wL9nk1QDkBabgcOB2k74k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctmEYb/btrHL2nMGnx/0wL9nk1QDkBabgcOB2k74k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctmEYb/btrHL2nMGnx/0wL9nk1QDkBabgcOB2k74k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctmEYb%2FbtrHL2nMGnx%2F0wL9nk1QDkBabgcOB2k74k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;364&quot; height=&quot;588&quot; data-filename=&quot;스크린샷 2022-07-20 오후 12.17.29.png&quot; data-origin-width=&quot;364&quot; data-origin-height=&quot;588&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-07-20 오후 12.19.41.png&quot; data-origin-width=&quot;364&quot; data-origin-height=&quot;624&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/O4hQJ/btrHKnMFU79/sUqiO0IDdmwPjEUaD4zfWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/O4hQJ/btrHKnMFU79/sUqiO0IDdmwPjEUaD4zfWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/O4hQJ/btrHKnMFU79/sUqiO0IDdmwPjEUaD4zfWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FO4hQJ%2FbtrHKnMFU79%2FsUqiO0IDdmwPjEUaD4zfWK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;364&quot; height=&quot;624&quot; data-filename=&quot;스크린샷 2022-07-20 오후 12.19.41.png&quot; data-origin-width=&quot;364&quot; data-origin-height=&quot;624&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다양한 옵션을 클릭하고 사용 가능한 명령을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-07-20 오후 12.20.50.png&quot; data-origin-width=&quot;1627&quot; data-origin-height=&quot;676&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ekeXJ8/btrHIGNuFU4/tyviXNGvaqMAPG7WTwXVSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ekeXJ8/btrHIGNuFU4/tyviXNGvaqMAPG7WTwXVSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ekeXJ8/btrHIGNuFU4/tyviXNGvaqMAPG7WTwXVSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FekeXJ8%2FbtrHIGNuFU4%2FtyviXNGvaqMAPG7WTwXVSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1627&quot; height=&quot;676&quot; data-filename=&quot;스크린샷 2022-07-20 오후 12.20.50.png&quot; data-origin-width=&quot;1627&quot; data-origin-height=&quot;676&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작은 창이 나타나는데 여기에서 명령 사이에 새 응용 프로그램을 생성하고 싶다면 리스트에서 선택&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1658295121372&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;nx serve [projectname]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex: nx&amp;nbsp;serve&amp;nbsp;api&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex: nx serve my-nx&lt;/p&gt;</description>
      <category>Frontend/Javascript</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/83</guid>
      <comments>https://developer-mobssie.tistory.com/83#entry83comment</comments>
      <pubDate>Wed, 20 Jul 2022 12:38:42 +0900</pubDate>
    </item>
    <item>
      <title>computed property names in JavaScript</title>
      <link>https://developer-mobssie.tistory.com/82</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1652695244942&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const key = 'name';
const value = 'Atta';

const user = {};
user[key] = value;

console.log(user.name); // Atta&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1652695334477&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const key = 'name';
const value = 'Atta';

const user = {
    [key]: value
};

console.log(user.name);&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1652695367054&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const key = 'name';
const value = 'Atta';

const user = {
    [key + '34']: value
};

console.log(user.name34); // Atta&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1652695389294&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const key = 'name';
const value = 'Atta';

const user = {
    [`${key}34`]: value
};

console.log(user.name34); // Atta&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Javascript</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/82</guid>
      <comments>https://developer-mobssie.tistory.com/82#entry82comment</comments>
      <pubDate>Mon, 16 May 2022 19:03:39 +0900</pubDate>
    </item>
    <item>
      <title>TypeError: firebase_compat_app__WEBPACK_IMPORTED_MODULE_0__.default.auth is not a function</title>
      <link>https://developer-mobssie.tistory.com/80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;[에러 메세지]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeError:&amp;nbsp;firebase_compat_app__WEBPACK_IMPORTED_MODULE_0__.default.auth&amp;nbsp;is&amp;nbsp;not&amp;nbsp;a&amp;nbsp;function&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Modularv9 와&lt;span&gt;&amp;nbsp;&lt;/span&gt;Compat라이브러리 유형&lt;span&gt;&amp;nbsp;&lt;/span&gt;사이에 구문을 혼합해서 사용한 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[인증 상태 관찰자 설정 및 사용자 데이터 가져오기]&lt;/p&gt;
&lt;pre id=&quot;code_1648641872985&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { getAuth, onAuthStateChanged } from &quot;firebase/auth&quot;;

const auth = getAuth();
onAuthStateChanged(auth, (user) =&amp;gt; {
  if (user) {
    // User is signed in, see docs for a list of available properties
    // https://firebase.google.com/docs/reference/js/firebase.User
    const uid = user.uid;
    // ...
  } else {
    // User is signed out
    // ...
  }
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;doc&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://firebase.google.com/docs/auth/web/start&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://firebase.google.com/docs/auth/web/start&lt;/a&gt;&lt;/p&gt;</description>
      <category>firebase</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/80</guid>
      <comments>https://developer-mobssie.tistory.com/80#entry80comment</comments>
      <pubDate>Wed, 30 Mar 2022 21:06:06 +0900</pubDate>
    </item>
    <item>
      <title>vue 3.0 프로젝트</title>
      <link>https://developer-mobssie.tistory.com/79</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;vue3 + pinia + vue-router + vite + tailwind&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #282c34; color: #ffffff;&quot;&gt;npm i -g @vue/cli&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #282c34; color: #ffffff;&quot;&gt;vue --version&lt;/span&gt;&lt;/p&gt;</description>
      <category>Frontend/Vue, Nuxt</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/79</guid>
      <comments>https://developer-mobssie.tistory.com/79#entry79comment</comments>
      <pubDate>Mon, 24 Jan 2022 18:07:38 +0900</pubDate>
    </item>
    <item>
      <title>UNMET PEER DEPENDENCY 에러시</title>
      <link>https://developer-mobssie.tistory.com/78</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UNMET&amp;nbsp;PEER&amp;nbsp;DEPENDENCY&amp;nbsp;에러시&lt;/p&gt;
&lt;pre id=&quot;code_1643015220026&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install -g npm&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;npm 업데이트하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>error 처리</category>
      <category>UNMET PEER DEPENDENCY 에러시</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/78</guid>
      <comments>https://developer-mobssie.tistory.com/78#entry78comment</comments>
      <pubDate>Mon, 24 Jan 2022 18:07:12 +0900</pubDate>
    </item>
    <item>
      <title>ESLINT 설정</title>
      <link>https://developer-mobssie.tistory.com/77</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;ESLINT는 코드 품질&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Prettier는 코드 스타일, 포멧팅에만 관점.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정파일 우선순위가 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. .eslintrc.js 2. .eslintrc.cjs 3. .eslintrc.yaml 4. .eslintrc.yml 5. .eslintrc.json 6. package.json&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1642053326787&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
	env: {
		// 환경은 사전 정의된 전역 변수를 제공합니다
		&quot;browser&quot;: true, // browser 전역변수 사용
    &quot;node&quot;: true // NODE 전영변수 사용
	},
	extends: [
		// ESLINT에서 Default Rules
		&quot;eslint:recommended&quot;,
		&quot;plugin:vue/recommended&quot;,
		&quot;plugin:@typescript-eslint/recommended&quot;,
	],
	plugins: [
		// 외부 모둘을 통한 파싱작업을 수행을 지정.
		// `eslint-plugin-` 접두사 플러그인 이름에서 생략
		&quot;vue&quot; // eslint-plugin-vue
		&quot;@typescript-eslint&quot;,
	],
	rules: {
		// [rule name]: [ Error Level, Option ]
		// Error Level: off/warn/error
		// Option: rule에 따른 설정
		indent: [&quot;error&quot;, 2]
	},
	...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고: &lt;a href=&quot;https://hyovelop.notion.site/ESLINT-8dd655f716dd42a1b9a9320214b33e65&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://hyovelop.notion.site/ESLINT-8dd655f716dd42a1b9a9320214b33e65&lt;/a&gt;&lt;/p&gt;</description>
      <category>Dev Tool</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/77</guid>
      <comments>https://developer-mobssie.tistory.com/77#entry77comment</comments>
      <pubDate>Thu, 13 Jan 2022 14:55:44 +0900</pubDate>
    </item>
    <item>
      <title>URL.revokeObjectURL()</title>
      <link>https://developer-mobssie.tistory.com/76</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;URL.revokeObjectURL()&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;정적 메서드는 이전에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/URL/createObjectURL&quot;&gt;URL.createObjectURL()&lt;/a&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;을 통해 생성한 객체 URL을 해제.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;객체 URL을 더는 쓸 일이 없을 때 사용해서, 브라우저가 이제 해당 객체를 메모리에 들고 있지 않아도 된다&lt;/span&gt;&lt;/p&gt;</description>
      <category>Frontend/Javascript</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/76</guid>
      <comments>https://developer-mobssie.tistory.com/76#entry76comment</comments>
      <pubDate>Mon, 27 Dec 2021 18:50:52 +0900</pubDate>
    </item>
    <item>
      <title>in 연산자</title>
      <link>https://developer-mobssie.tistory.com/75</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;in&amp;nbsp;연산자&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;는 명시된 속성이 명시된 객체에 존재하면&amp;nbsp;&lt;/span&gt;true&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;를 반환&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1640436151759&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;속성 in 객체명&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 배열의 내용이 아닌, 인덱스 값을 명시&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- length는 Array(배열) 객체의 속성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;- 반드시 &lt;/span&gt;in&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt; 연산자의 오른쪽에 객체를 명시하여야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- in&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;&amp;nbsp;연산자는 프로토타입 체인에 의하여&amp;nbsp;접근할 수 있는 속성에 대하여&amp;nbsp;&lt;/span&gt;true&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;를 반환&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/in&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/in&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Frontend/Javascript</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/75</guid>
      <comments>https://developer-mobssie.tistory.com/75#entry75comment</comments>
      <pubDate>Sat, 25 Dec 2021 21:48:53 +0900</pubDate>
    </item>
    <item>
      <title>Axios stream</title>
      <link>https://developer-mobssie.tistory.com/74</link>
      <description>&lt;pre id=&quot;code_1639551268984&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import axios, { AxiosInstance } from 'axios';
import { Readable } from 'stream';

const response = await axios.get('', { responseType: 'stream'});
const readable: Readable = response.data&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;axios의&amp;nbsp;config에&amp;nbsp;responseType:&amp;nbsp;&amp;lsquo;stream&amp;rsquo;으로&amp;nbsp;설정하여&amp;nbsp;반환되는&amp;nbsp;데이터를&amp;nbsp;readable&amp;nbsp;객체로&amp;nbsp;받을&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;</description>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/74</guid>
      <comments>https://developer-mobssie.tistory.com/74#entry74comment</comments>
      <pubDate>Wed, 15 Dec 2021 15:54:48 +0900</pubDate>
    </item>
    <item>
      <title>원격 브런치 삭제하기</title>
      <link>https://developer-mobssie.tistory.com/73</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 사용하던 git default 브런치 명이 master에 main으로 바꼈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main으로 변경 후에 remote에 있는 브랜치 삭제&lt;/p&gt;
&lt;pre id=&quot;code_1639450666247&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git push origin --delete master&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>git</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/73</guid>
      <comments>https://developer-mobssie.tistory.com/73#entry73comment</comments>
      <pubDate>Tue, 14 Dec 2021 11:57:23 +0900</pubDate>
    </item>
    <item>
      <title>WebApi를 이용한 JS기능</title>
      <link>https://developer-mobssie.tistory.com/72</link>
      <description>&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&lt;a href=&quot;https://youtu.be/Vatd-V0pLXo&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;https://youtu.be/Vatd-V0pLXo&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</description>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/72</guid>
      <comments>https://developer-mobssie.tistory.com/72#entry72comment</comments>
      <pubDate>Sun, 12 Sep 2021 20:57:58 +0900</pubDate>
    </item>
    <item>
      <title>생성자 함수(constructor Function)</title>
      <link>https://developer-mobssie.tistory.com/71</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;- 자바스크립트 객체 생성 방법은 다양하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 클래스를 사용해도 되지만, 단순하고 심플하게 함수를 클래스처럼 사용 할 수있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 클래스와 마찬가지로 생성자 키워드인 new로 인스턴스를 생성할 수 있고, 내부 메서드와 변수를 사용할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 클래스처럼 상속을 통해 확장을 할 수는 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Javascript</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/71</guid>
      <comments>https://developer-mobssie.tistory.com/71#entry71comment</comments>
      <pubDate>Wed, 8 Sep 2021 14:30:49 +0900</pubDate>
    </item>
    <item>
      <title>Computed : get, set</title>
      <link>https://developer-mobssie.tistory.com/70</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;computed&lt;/b&gt;&lt;span style=&quot;background-color: #f8f9fa; color: #212529;&quot;&gt;는 기본적으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;읽기 전용&lt;/b&gt;&lt;span style=&quot;background-color: #f8f9fa; color: #212529;&quot;&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Computed프로퍼티는 method와 비슷하지만 Computed는 proxy역활을 한다. 때로는 캐싱.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt;&amp;gt;&amp;nbsp; 연결하는 역할을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;set&lt;/b&gt;&lt;/span&gt; methods 을 설정하면, newValue 매개변수를 받음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods&quot;&gt;https://vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods&lt;/a&gt;&lt;/p&gt;</description>
      <category>Frontend/Vue, Nuxt</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/70</guid>
      <comments>https://developer-mobssie.tistory.com/70#entry70comment</comments>
      <pubDate>Wed, 8 Sep 2021 11:13:36 +0900</pubDate>
    </item>
    <item>
      <title>WindowEventHandlers.onpopstate</title>
      <link>https://developer-mobssie.tistory.com/69</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WindowEventHandlers.onpopstate&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/WindowEventHandlers/onpopstate&quot;&gt;https://developer.mozilla.org/ko/docs/Web/API/WindowEventHandlers/onpopstate&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;window의 popstate 이벤트 핸들러&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 같은 document에 관한 두개의 히스토리 엔트리에 변화가 일어날 때마다, popstate event가 window 객체에 붙게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 만약 활성화된 엔트리가 &lt;b&gt;history.pushState()&lt;/b&gt; 메서드나 &lt;b&gt;history.replaceState()&lt;/b&gt; 메서드에 의해 생성되면,&lt;u&gt; popstate 이벤트의 state 속성은 히스토리 엔트리 state 객체의 복사본을 갖게 된다.&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- history.pushState() 또는 history.replaceState()는 &lt;u&gt;popstate 이벤트를 발생시키지 않는 것에 유의&lt;/u&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;popstate 이벤트는 브라우저의 백 버튼이나 (history.back() 호출) 등을 통해서만 발생&lt;/b&gt;된다. 그리고 그 이벤트는 같은 document에서 &lt;b&gt;두 히스토리 엔트리 간의 이동이 있을 때만 발생&lt;/b&gt;이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 브라우저는 popstate 이벤트를 페이지 로딩시에 다르게 처리한다. Chrome(v34 이전버전) 와 Safari는 popstate 이벤트를 페이지 로딩시에 발생시킨다. 하지만 Firefox 는 그렇지 않다.&lt;/p&gt;</description>
      <category>Frontend/Javascript</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/69</guid>
      <comments>https://developer-mobssie.tistory.com/69#entry69comment</comments>
      <pubDate>Wed, 11 Aug 2021 11:56:25 +0900</pubDate>
    </item>
    <item>
      <title>History.pushState()</title>
      <link>https://developer-mobssie.tistory.com/68</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;History.pushState()&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/History/pushState&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/ko/docs/Web/API/History/pushState&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저의 세션 기록 스택에 상태를 추가한다.&lt;/p&gt;
&lt;pre id=&quot;code_1628648262176&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;history.pushState(state, title[, url]);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;state&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 새로운 세션 기록 항목에 연결할 상태 객체.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 사용자가 새로운 상태로 이동할 때마다&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/Window/popstate_event&quot;&gt;popstate&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이벤트가 발생! 이 때 이벤트 객체의&lt;span&gt;&amp;nbsp;&lt;/span&gt;state&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성에 해당 상태의 복제본이 담겨 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 상태 객체는 직렬화 가능한 객체라면 모두 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;title&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 빈 문자열을 지정하면 나중의 변경사항에도 안전하다. 아니면, 상태에 대한 짧은 제목을 제공할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;url&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;- 브라우저를 재시작할 경우 탐색을 시도할 수도 있음.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;- 상대 URL을 지정할 수 있으며, 이 땐 현재 URL을 기준으로 사용. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;- 새로운 URL은 현재 URL과 같은&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot; href=&quot;https://developer.mozilla.org/ko/docs/Glossary/Origin&quot;&gt;출처&lt;/a&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;를 가져야 하며, 그렇지 않을 경우 예외가 발생. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;- 지정하지 않은 경우 문서의 현재 URL을 사용.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Frontend/Javascript</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/68</guid>
      <comments>https://developer-mobssie.tistory.com/68#entry68comment</comments>
      <pubDate>Wed, 11 Aug 2021 11:42:47 +0900</pubDate>
    </item>
    <item>
      <title>Object.entries()</title>
      <link>https://developer-mobssie.tistory.com/67</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/entries&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/entries&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Object.entries()&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;메서드는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/for...in&quot;&gt;for...in&lt;/a&gt;와 같은 순서로 주어진 객체 자체의 enumerable 속성&lt;span&gt;&amp;nbsp;&lt;/span&gt;[key, value]&lt;span&gt;&amp;nbsp;&lt;/span&gt;쌍의 배열을 반환합니다.&amp;nbsp;(for-in&lt;span&gt;&amp;nbsp;&lt;/span&gt;루프가 다른점은 프로토 타입 체인의 속성도 열거한다는 점입니다).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Object.entries()&lt;/b&gt;&amp;nbsp;에 의해 반환된 배열(array)의 순서는&amp;nbsp;객체가 정의된 방법과 관련이 없습니다.&amp;nbsp; 배열 순서가 쓸 곳이 있다면, 다음과 같이 정렬을 먼저 하시는 것이 좋습니다&amp;nbsp;Object.entries(obj).sort((a, b) =&amp;gt;&amp;nbsp;b[0].localeCompare(a[0]));.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1623981606517&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const object1 = {
  a: 'somestring',
  b: 42
};

for (const [key, value] of Object.entries(object1)) {
  console.log(`${key}: ${value}`);
}

// expected output:
// &quot;a: somestring&quot;
// &quot;b: 42&quot;
// order is not guaranteed
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Javascript</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/67</guid>
      <comments>https://developer-mobssie.tistory.com/67#entry67comment</comments>
      <pubDate>Fri, 18 Jun 2021 11:00:15 +0900</pubDate>
    </item>
    <item>
      <title>node.js 와 Typescript module system에 대해서</title>
      <link>https://developer-mobssie.tistory.com/66</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;node.js와 Typescript의 module system&lt;br /&gt;&lt;br /&gt;타입스크립트 모듈 시스템은 자바스크립트 최신문법을 계승했기 때문에 차이를&amp;nbsp;잘&amp;nbsp;알아야&amp;nbsp;한다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 48.3721%; height: 87px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;node.js&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;typescript&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;common.js&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;module.js&amp;nbsp;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Javascript file과 Typescript file은 module화 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;module화 하는 이유는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 다른파일에서 사용할 수 있게 해줌.&lt;br /&gt;* 가독성과 재사용성을 높히기 위해서 사용함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;[node.js에서 module화 하는 방법]&lt;/p&gt;
&lt;pre id=&quot;code_1622858389257&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const hello = 'module'
module.exports = 'hello';&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@module.js&lt;/p&gt;
&lt;pre id=&quot;code_1622858418865&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const hi = require('./module');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@run.js&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;▶ require만 하면 다시 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체를 export할 때 에는 export자체가 객체(object)&lt;/p&gt;
&lt;pre id=&quot;code_1622858561853&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const hello = 'module'

exports.a = 'b';
exports.b = false;

//또는
module.exports = {
    a: 'b',
    b: false,
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@module.js&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1622858593459&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const {a, b} = require('./module');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@run.js&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1622858617160&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const hello = 'module'
const a = 'b'
const b = false
export { a };
export { b };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@module.js&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1622858627829&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import   hello, { a, b } from './module';
console.log(a,b)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@run.js&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;▶ module.exports 파일에서 한번만 사용가능.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;b&gt;export 들밑에 module.exports 사용하게 되면&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Result:&lt;/b&gt;&amp;nbsp;module.exports 사라짐.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Because:&lt;/b&gt; overriding~! 덮어 써버림! (exports는 === 임)&lt;br /&gt;&lt;b&gt;But:&lt;/b&gt;&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;export default&lt;/u&gt;&lt;/span&gt;는 덮어쓰지 않는다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;타입스크립트도&amp;nbsp;import&amp;nbsp;export로&amp;nbsp;사용하는데&amp;nbsp;&lt;br /&gt;타입스크립트에서 가져올때에는&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1622859050277&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import * as hi from 'module'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;▶ 문법적으로 맞음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1622859117120&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import hi from 'module'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;▶&amp;nbsp;config.js에서 옵션으로&amp;nbsp;esModuleInterop: true 로 설정하면 사용 가능하다.&lt;br /&gt;&lt;br /&gt;▶▶▶&amp;nbsp;차이는&amp;nbsp;알아두는게&amp;nbsp;좋음&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1622859171382&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;exports interface Card {

}

export class Hero implements Card {

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;▶ 같은 파일 안에서 interface나 class도&amp;nbsp; module화도 가능하다.&lt;br /&gt;&lt;br /&gt;▶ import와 export가 있으면 모듈이고, 없으면 그냥 스크립트이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;▶ d.ts 는 d.ts 는 타입스크립트 코드의 타입 추론을 돕는 파일이고, 보통 내 프로젝트가 라이브러리일때 사용 한다.&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[import 사용법]&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1622859436693&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// ES2015모드
import {Card, Player} from './types'
// common.js 모드
import A = require('./common')
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>Frontend/Node.js</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/66</guid>
      <comments>https://developer-mobssie.tistory.com/66#entry66comment</comments>
      <pubDate>Wed, 2 Jun 2021 22:51:47 +0900</pubDate>
    </item>
    <item>
      <title>[Vue Error] Consider upgrading your version of 'tslib'</title>
      <link>https://developer-mobssie.tistory.com/65</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;This&amp;nbsp;syntax&amp;nbsp;requires&amp;nbsp;an&amp;nbsp;imported&amp;nbsp;helper&amp;nbsp;named&amp;nbsp;'__spreadArray'&amp;nbsp;which&amp;nbsp;does&amp;nbsp;not&amp;nbsp;exist&amp;nbsp;in&amp;nbsp;'tslib'.&amp;nbsp;Consider&amp;nbsp;upgrading&amp;nbsp;your&amp;nbsp;version&amp;nbsp;of&amp;nbsp;'tslib'.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1622528436588&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm ls -g --depth=0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버젼 확인 해보니 공동으로 사용하는 eslint package 기준 버젼이 달라 에러가 났던것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sudo npm install -g &amp;lt;package&amp;gt;@&amp;lt;version&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용하여 해결&lt;/p&gt;</description>
      <category>error 처리</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/65</guid>
      <comments>https://developer-mobssie.tistory.com/65#entry65comment</comments>
      <pubDate>Tue, 1 Jun 2021 14:53:15 +0900</pubDate>
    </item>
    <item>
      <title>async, await, try, catch</title>
      <link>https://developer-mobssie.tistory.com/64</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;promise를 좀 더 편하게 사용할 수 있는 async, await에 대해서 정리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.&amp;nbsp;function 앞에 async를 붙이면 해당 함수는 항상 프라미스를 반환한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;promise가 아닌 값을 반환하더라도 이행 상태의 프라미스(resolved promise)로 값을 감싸 이행된 프라미스가 반환되도록 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 함수 안에서 await를 사용할 수 있다.&lt;/p&gt;</description>
      <category>Frontend/Javascript</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/64</guid>
      <comments>https://developer-mobssie.tistory.com/64#entry64comment</comments>
      <pubDate>Tue, 1 Jun 2021 11:38:07 +0900</pubDate>
    </item>
    <item>
      <title>document.onvisibilitychange</title>
      <link>https://developer-mobssie.tistory.com/63</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;document.onvisibilitychange&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;syntax&lt;/p&gt;
&lt;pre id=&quot;code_1622463578396&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;obj.oncisibilitychange = function;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;example&lt;/p&gt;
&lt;pre id=&quot;code_1622463633681&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;document.onvisibilitychange = function() {
  console.log(&quot;visibility of page has changed!&quot;)
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Frontend/Javascript</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/63</guid>
      <comments>https://developer-mobssie.tistory.com/63#entry63comment</comments>
      <pubDate>Mon, 31 May 2021 21:20:36 +0900</pubDate>
    </item>
    <item>
      <title>Document.visibilityState</title>
      <link>https://developer-mobssie.tistory.com/62</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Document.visibiltyState는 읽기전용 property로, 이 element가 현재 표시된 컨텍스트를 나타내는 document의 가시성을 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;document가 background 또는 보이지 않는 탭(다른 탭)에 있는지, 또는 pre-rendering을 위해 로드 된 것인지를 아는 것은 유용하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가능한 값은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 'visible' : 페이지 내용은 적어도 부분적으로 보일 수 있다. 실제로 아는 페이지가 최소화 되지 않은 창에서의 선택된 탭을 의미함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 'hidden' : 페이지 내용은 사용자에게 표시되지 않다. 실제로 이는 docuement가 background-tap(다른탭)이거나, 최소화 된 창의 일부이거나, OS 화면 잠금이 활성 상태임을 의미&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 'prerender' : 페이지 내용이 pre-rendering되어 사용자에게 보이지 않는다. (document.hidden 목적으로 숨겨진 것으로 간주 한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;document는 이 상태에서 시작 될 수 있지만, 절대로 다른 값에서 이 값으로 전환되지는 않습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 'unloaded' : 페이지가 메모리에서 로드죄지 않는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;property의 값이 변경되면 visibilitychange이벤트가 Document로 전송&lt;/b&gt;&lt;/span&gt;된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 document pre-rendering시에 일부 assets의 다운로드를 막을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;document가 백그라운드에 있거나 최소화 된 상태에서 일부 작어블 중지 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1622458250211&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;document.addEventListener(&quot;visibilitychange&quot;, function() {
  console.log(document.hidden);
  // 숨김 여부가 변했을 때의 행동
});&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Frontend/Javascript</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/62</guid>
      <comments>https://developer-mobssie.tistory.com/62#entry62comment</comments>
      <pubDate>Mon, 31 May 2021 19:45:45 +0900</pubDate>
    </item>
    <item>
      <title>typescript 설치부터 사용법 정리</title>
      <link>https://developer-mobssie.tistory.com/57</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: rgba(0, 0, 0, 0.847);&quot;&gt;타입스크립트는 변수랑 함수의매개변수랑 리턴값에 타입이 붙은 것이다.&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: rgba(0, 0, 0, 0.847);&quot;&gt;설치&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: rgba(0, 0, 0, 0.847);&quot;&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: rgba(0, 0, 0, 0.847);&quot;&gt;npm init&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;npm i typescript&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;npm i -g typescript (명령어로 설치/+ 전역설치)]&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;u&gt;= npx tsc lecture.ts -w&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트에 설치한 버젼이랑 같이 설치가되서 npx로 해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tsc 엔터 (타입스크립트 컴파일 하는명령어)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tsc lecture (해당하는 폴더에)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tsc를 통해서 ts를 컴파일해서 js로 변경해서 html에는 항상 js를 연결.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;[자동으로 컴파일]&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tsc lecture.ts -w&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTMLDivElement : 타입스크립트에서 만들어 &amp;nbsp;놓음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Package-lock : lock파일은 github에 같이 올려야함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확한 버젼이기때문에 똑같은 버젼이 깔림.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Package.js : 범위&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[tsconfig.ts]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Target&lt;/b&gt;: &amp;nbsp;es6로 하고 바벨,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;module&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;undefined와 null을 구분하는 module&lt;/p&gt;
&lt;pre id=&quot;code_1621867721223&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;strictNullChecks&quot;: true,&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[error 해결]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에러코드 나오면 코드를 구글에 검색&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예//&amp;nbsp;TS2304&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tsconfig.ts에서 &amp;ldquo;lib&amp;rdquo;: [&amp;ldquo;ES5&amp;rdquo; .. ..]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도저히 해결 할 수없는 에러일때에는 뒤에 느낌표를 붙여준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[this와 타입 범위 이해]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;this를 썻다. 그런데 arrow function이 아닌 그냥 function이면 this의 타입을&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;첫번째 매개변수&lt;/b&gt;로 넣어 줘야 한다. this 타입추론이 정확해진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1621867741123&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;btn.addEventListener('click', function(this: HTMLButtonElement, e: Event){
const myChoice = this.textContext as keyof RSP;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;as 를 써서 타입을 정확하게 맞춰주는것.&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입스크립트가 스스로 추론하지 못하는것들을 범위를 쫍혀줘야 한다.(타이트하게)&lt;/p&gt;
&lt;pre id=&quot;code_1621867763202&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let imgCoords: RSP[keyof RSP] = '0';&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;범위를 잘 이해해야함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[interface]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;interface는 확장할수있다. 객체에서 사용.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따로따로 적어주면 합쳐진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤값이 들어올지 모르면 엄격하게 하지 않을때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Interface RSP {&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; [c: string] : string&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;}&lt;/p&gt;
&lt;pre id=&quot;code_1621867779064&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Interface RSP {
  [c: string] : string
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 식으로 클래스 표현이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1621867794350&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Example {
  new (a: number, b: number): number
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;new를 붙이면 class를 interface로 표현 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1621867835239&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Example {
    add: (a: number, b: number) =&amp;gt; number
  } // 객체의 속성. 함수타입
  const ex: Example = {
    add: (a, b) =&amp;gt; {
    return a + b;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[제네릭]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;짝마추기&lt;/p&gt;
&lt;pre id=&quot;code_1621867850825&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;document.addEventListener&amp;lt;'submit'&amp;gt;('submit', () =&amp;gt; {

})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rsquo;submit&amp;rsquo;이 가능한 이유는 타입스크립트에 선언되어있기때문,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;submita 이렇게 다른 문자열이 오면 에러가 난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1621867870487&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function add(a: string, b: string): string{
  return a + b;
}
function add(a: number, b: number): number{
  return a + b;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 표현하고 싶을때 사용한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1621867897372&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface obj&amp;lt;T&amp;gt; {
  add: (a: T, b: T) =&amp;gt; T;
}
const a: obj&amp;lt;number&amp;gt; = {
  add: (a, b) =&amp;gt; a + b,
}
const b: obj&amp;lt;string&amp;gt; = {
  add: (a, b) =&amp;gt; a + b,
}
a.add(1, 2);
a.add('1', '2'); // error
b.add(1, 2); // error
b.add('1', '2');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제네릭 타입제한&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex &amp;lt;T extends string&amp;gt;&lt;/p&gt;
&lt;pre id=&quot;code_1621867925556&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface obj&amp;lt;T extends string&amp;gt; {
  add: (a: T, b: T) =&amp;gt; T;
}
const a: obj&amp;lt;number&amp;gt; = {
  add: (a, b) =&amp;gt; a + b,
} // error
const b: obj&amp;lt;string&amp;gt; = {
  add: (a, b) =&amp;gt; a + b,
}
a.add(1, 2);
b.add('1', '2');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[type]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유니언이 필요한경우 | type을 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[keyof]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;let imgCoords: RSP[keyof RSP] = &amp;lsquo;0&amp;rsquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt;&amp;gt; 중복을 줄일수잇어서 좋다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[as]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강제로 변환해주는 것(범위를 좁혀주는 작업)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작은 집합은 큰 집합에 들어갈수있는데 큰 집합은 작은 집합으로 들어가지 못하기때문에 똑같이 마춰주는게 베스트!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[private, public, protected]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;public &amp;lt; protected &amp;lt; private&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;public: 인스턴스에서도 접근가능.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;protected: 자식들도 접근가능. extends 로 접근가는데. (부모는 안됨)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;private: 나한테에서만 접근할수있는것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[implements]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;new를 쓴다면 class를 사용하고, extends를 실제로 사용하면 class&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;interface를 implements로 구현만 하면.. implements&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Typescript</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/57</guid>
      <comments>https://developer-mobssie.tistory.com/57#entry57comment</comments>
      <pubDate>Mon, 24 May 2021 23:46:30 +0900</pubDate>
    </item>
    <item>
      <title>Vue 데이터 전달하기</title>
      <link>https://developer-mobssie.tistory.com/56</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;pass props : 부모에서 자식에게 데이터를 전달&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Emit Events : 자식이 부모에게 데이터를 전달&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;독립적으로 컴포넌트가 존재 자식이나 부모가 누군지 몰라서 동작함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네이밍 규칙&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트내에 속성으로는 kebab-case / 스크립트 내부에서는 camelCase 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동적 Props&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-bind를 이용해서 데이터를 전달해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모 컴포넌트의 message가 변경된 경우 자식 컴포넌트는 다시 message 데이터를 받아 다시 렌더링을 함.(v-bind 생량가능)&lt;/p&gt;
&lt;pre id=&quot;code_1621345785475&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div id=&quot;app&quot;&amp;gt;
  &amp;lt;input type=&quot;text&quot; v-model=&quot;message&quot;&amp;gt;
  &amp;lt;simple-component :message=&quot;message&quot;&amp;gt;&amp;lt;/simple-component&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;script&amp;gt;
  var simpleComponent = {
    props: ['message'],
    template: '&amp;lt;div&amp;gt;{{message}}&amp;lt;/div&amp;gt;'
  }
  new Vue ({
    el: '#app',
    data: {
      message: 'Hello, Vue!'
    },
    component: {
      'simple-component': simpleComponent
    }
  });
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;주의점:&lt;/span&gt; 단방향이기 때문에 부모에서 업데이트가되면 자식에게도 업데이트가되지만, 그 반대는 안됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;props를 변경하고 싶다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. props의 초기 값을 컴포넌트 로컬 데이터로 정의&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.&amp;nbsp; props로 부터 계산된 속성을 정의&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;props 검증하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;props의 데이터타입이 중요하다면 props 데이터 타입을 강제할 수 있다. 협업할때 유용하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 validation도 가능하다&lt;/p&gt;
&lt;pre id=&quot;code_1621478627602&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
&amp;lt;div id=&quot;app&quot;&amp;gt;
  &amp;lt;simple-component :price=&quot;price&quot;&amp;gt;&amp;lt;/simple-component&amp;gt;
&amp;lt;/div&amp;gt;
...
&amp;lt;script&amp;gt;
  var simpleComponent = {
    props: {
      name: {
        type: String,
        defalut: '구형 스마트폰' //기본값을 정의할 수 있음. 
      },
      price: {
        type: Number,
        validation: function (value) {
          // value 값이 50000이상이 아니면 검증 실패
          return value &amp;gt;= 500000
        }
      },
      message: {
        type: [String, Object],
        requeired: true
      },
      object: {
        type: Object,
        // 타입이 Object인 경우 함수를 통해 반환해야 함
        default: function () {
          return { message: '메세지' }
        }
      }
    },
    template: '&amp;lt;div&amp;gt;{{ name }}, {{ price }}원, {{ message }}&amp;lt;/div&amp;gt;'
  };
  
  new Vue({
    el: '#app',
    data: {
      name: '최신형 스마트폰',
      price: 497000,
      message: '최신형 스마트폰 싸게 팝니다!'
    },
    components: {
      'simple-component': simpleComponent
    }
  })
&amp;lt;/script&amp;gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;type, default, required, validation&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;type 옵션에서 사용 가능한 타입은&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;String, Number, Boolean, Function, Object, Array&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 Object와 Array의 경우 default를 정의할때 함수를 이용해 반환해 줘야함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자식 컴포넌트가 부모컴포넌트에게 데이터를 전달 할 순 없지만 이벤트를 통해 메시지를 전달할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-on을 이용해 템플릿에 사용자 지정 이벤트를 만들 수 있다. 이때 자식 컴포넌트는 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;$emit&lt;/b&gt;&lt;/span&gt;을 이용해 이벤트를 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Vue, Nuxt</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/56</guid>
      <comments>https://developer-mobssie.tistory.com/56#entry56comment</comments>
      <pubDate>Tue, 18 May 2021 20:00:22 +0900</pubDate>
    </item>
    <item>
      <title>Vue 컴포넌트 분리하는 방법</title>
      <link>https://developer-mobssie.tistory.com/55</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트는 Vue 오브젝트를 확장한 오브젝트이다. 확장이란 미리 Vue 오브젝트에 옵션을 정의해 이미 옵션이 정의된 Vue오브젝트를 생성하는 것을 의미함. 컴포넌트를 생성하면 확장된 Vue 인스턴스가 생성.&lt;/p&gt;
&lt;pre id=&quot;code_1621323595212&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div id=&quot;app&quot;&amp;gt;
  &amp;lt;date&amp;gt;&amp;lt;/date&amp;gt;
  &amp;lt;date&amp;gt;&amp;lt;/date&amp;gt;
  &amp;lt;date&amp;gt;&amp;lt;/date&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;script&amp;gt;
  Vue.Component('date',{
    template: '&amp;lt;div&amp;gt;{{ now }}&amp;lt;/div&amp;gt;',
    data: function () {
      return {
        now: new Date()
      }
    }
  })
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.Component는 컴포넌트를 글로벌하게 등록하는 메서드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트를 사용하면 공통적인 로직이나 템플릿을 엘리먼트를 통해 재활용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;주의할점! :&lt;/span&gt;&amp;nbsp; 확장된 Vue 인스턴스, 즉 컴포넌트에서&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt; data를 정의할 때 반드시 함수로 정의&lt;/b&gt;&lt;/span&gt;해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트 이름은 하이픈을 포함한 소문자이어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 컴포넌트 : Vue 인스턴스 혹은 컴포넌트의 옵션으로 등록해 해당 컴포넌트 내부에서만 사용하도록 지정 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1621325814661&quot; class=&quot;html javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var dateComponent = {
  template: '&amp;lt;div&amp;gt;{{ now }}&amp;lt;/div&amp;gt;',
  data: function () {
    return {
      now: new Date()
    }
  }
}
new Vue({
  el: '#app',
  components: {
  	date: dateComponent
  }
})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ul, ol, table, select같은 내부에 엘리먼트가 정해져있는 컴포넌트는 is 옵션을 사용해 렌더링해야함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;템플릿 분리&lt;/p&gt;
&lt;pre id=&quot;code_1621330918121&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script type=&quot;text/x-template&quot; id=&quot;todo-component&quot;&amp;gt;
  &amp;lt;div&amp;gt;
  	&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/script&amp;gt;
&amp;lt;script&amp;gt;
  var todoComponent = {
    template: '#todo-component',
    data: function () {
      return {
        todos: [
          '열심히 일하기',
          '효도하기',
          '연애하기'
        ]
      }
    }
  };
  new Vue({
    el: '#app',
    components: {
      'todo-component' : todoComponent
    }
  })
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;script type=&quot;text/x-template&quot; id=&quot;todo-component&quot;&amp;gt; 와 &amp;lt;template id=&quot;todo-component&quot;&amp;gt; 같다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Vue, Nuxt</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/55</guid>
      <comments>https://developer-mobssie.tistory.com/55#entry55comment</comments>
      <pubDate>Tue, 18 May 2021 16:34:40 +0900</pubDate>
    </item>
    <item>
      <title>Vue 인스턴스 사용하는 방법</title>
      <link>https://developer-mobssie.tistory.com/54</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;템플릿 문법은 주로 디렉티브(Directive)로 이루어져있음. DOM 엘리먼트에 속성을 추가하는 것을 의미.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;데이터바인딩&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mustache : {{ expression }}&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-text : Mustache와 거의 동일하게 작동. 중괄호로 감싸는 대신 디렉티브를 이용해서 데이터를 바인딩 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-html : HTML 문자열을 그대로 바인딩.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-bind : View의 텍스트를 렌더링하는 문법이 아닌 태그의 속성에 데이터를 바인딩하는 문법.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;조건문&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-if : 조건에 따라 템플릿을 보여줌 (v-else, v-else-if)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;template if : v-if는 디렉티브이기때문에 한 가지 엘레먼트에만 적용가능하지만 template 엘레먼트 한 번에 처리 가능하다. 엘레먼트는 가상의 엘레먼트이기 때문에 자식들만 묶어서 렌더링 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-show: true 일 경우 렌더링&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;** v-if vs v-show&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style9&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;v-if&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;v-show&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;초기 조건이 false일 경우 렌더링하지 않음.&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;항상 렌더링 됨.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;조건이 false가 될 경우 엘리먼트가 삭제됨&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;CSS display 속성을 토글함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;template구문을 지원함.&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;template 구문을 지원하지 않음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;v-else 를 사용할 수 있음.&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;v-else를 사용할 수 없음.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;▶ v-if는 조건이 false일 경우 DOM 트리에서 삭제되지만 v-show는 단순히 display속성을 토글.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;▶ 만약 조건이 자주 바뀌는 로직이라면 v-if 보다 v-show를 쓰는것이 성능 면에서 우세.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;반복문&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-for : 이 디렉티브는 반복적인 엘리먼트를 렌더링해야 할 때 유용함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;template v-for: 여러개의 엘리먼트를 포함해서 반복 렌더링할때 사용.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;▶ v-if / v-for : 같은 엘리먼트에 존재할때 우선순위는 v-for가 v-if보다 높습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000; color: #ffffff;&quot;&gt;이벤트 수식어&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-on : v-on:{이벤트}=&quot;자바스크립트 표현식&quot;, click, keyup, keydown, input&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;capture&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML DOM 이벤트 : 클릭, 입력과 같은 유저 상호작용이 일어나면 브라우저는 HTML DOM 이벤트가 발생하는데 이때 이벤트는 부모 엘리먼트, 자식엘리먼트로 전달된다. &lt;u&gt;자식엘리먼트 쪽으로 전파되는것을 버블링, 부모 엘리먼트 쪽으로 전파 되는것을 캡처링이라고 한다.&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본값은 버블링 페이즈&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@click.capture&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;stop&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;stop 수식어는 이벤트가 전파되어 원하지 않는 결과가 생기는 일이 많기 때문에 이를 막을 수 있게 만드는 수식어.&lt;/p&gt;
&lt;pre id=&quot;code_1621309080152&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func2 : function(){
	
},
func2_original : function(){
	e.stopPropagation();
}

@click=&quot;func2.stop&quot;는 func2_original()과 완전히 동일한 동작을 함
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@click.stop / e.stopPropagation();&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;self 수식어는 이벤트 전파로 실행되는 것이 아닌, 이벤트의 근원지가 해당 엘리먼트일 때 핸드러를 호출하도록 함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(event.target이 해당 엘리먼트일 때에만 실행되도록 함)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@click.self&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;prevent&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저엔 기본적으로 특정 태그에 대한 액션을이 미리 정의되어있는데 막아주는 역활을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@click.prevent / event.preventDefault()&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;once&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한번만 실행해야하는경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@click.once&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000; color: #ffffff;&quot;&gt;키 수식어&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1621310175146&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;input type=&quot;text&quot; @keydown=&quot;preventKey&quot;&amp;gt;

new Vue({
  el: '#app',
  methods:{
    preventKey: function () {
      if(event.keyCode == 8 || event.keyCode == 46)
      event.preventDefault();
    }
  }
})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;delete를 막는예제 (키 수식어를 사용하지 않음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키 수식어를 사용한 예제&lt;/p&gt;
&lt;pre id=&quot;code_1621314399752&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;

&amp;lt;input type=&quot;text&quot; @click.delete=&quot;preventKey&quot;&amp;gt;

new Vue({
  el: #app,
  methods: {
    preventKey: function () {
      event.preventDefault();
    }
  }
})

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;▶ delete(+backspace), enter, tab, esc, space, up, down, left, right&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;수식어 체이닝&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키 입력 하나에만 대응할 수 있는 것이 아니라, 수식어로 달아 놓은 여러 키 모두에 대해 핸들링 할 수있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;보조키 수식어&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;shift, alt, control, meta-window or command key 또한 미리&amp;nbsp; Vue에 정의 되어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보조키 수식어는 키 수식어 뿐만 아니라 마우스수식어와도 함께 쓸수있으며, 다른키와 입력될 때만 트리거 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, shift키 하나만 입력하는 것은 이벤트가 트리거되지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) @keyup.shift라고만 사용했을 대엔 shift와 다른 모든 키의 조합에 트리거 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사용자 정의 키 수식어&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키 코드를 직업쓰거나, 직접 해당 키 코드의 별칭을 옵션으로 설정하고 별칭으로 정의한 수식어로 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) @key.a&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-on, v-bind는 생략가능하다. 단, @ 기호를 붙여한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;모델&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-model : 폼과 데이터를 바인딩하는 디렉티브이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js는 기본적으로 단방향 바인딩이지만, v-model은 양방향 바인딩입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1621317798294&quot; class=&quot;html javascript xml&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div id=&quot;app&quot;&amp;gt;
  &amp;lt;input v-model=&quot;name&quot;&amp;gt;
&amp;lt;/div&amp;gt;

&amp;lt;script&amp;gt;
  new Vue({
    el: #app,
    data: {
      name: 'Mobssie'
    }
  })
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 실행했을 때 input 엘리먼트의 값을 수정한다면 name 변수의 값도 input 엘리먼트에 입력한 값과 동일하게 변경된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 name 데이터의 값을 변경한다면, input 엘리먼트에 입력된 값 또한 name 데이터의 값과 동일하게 수정된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 엄밀히로는 이는 데이터 양방향 바인딩은 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-model은 사용자의 입력에 대해 매핑된 변수를 업데이트 해주는 이벤트가 포함되어있는것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엘레먼트 속성에 정의된 값은 무시되고 데이터값이 우선시 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한글자가 완성될 때에만 데이터에 반영되기 때문에 이럴 경우에는 v-model이 아닌 v-on:input을 이용하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;값 바인딩하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폼 엘리먼트의 속성으로 정의해 놓은 정적 value가 아니라, 동적으로 vue instance의 변수를 폼의 값으로 바인딩할때&lt;/p&gt;
&lt;pre id=&quot;code_1621320017475&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div id=&quot;app&quot;&amp;gt;
  &amp;lt;input type=&quot;checkbox&quot; v-model=&quot;checkboxModel&quot; 
  		  v-bind:true-value=&quot;trueValue&quot; v-bind:false-value=&quot;falseValue&quot;&amp;gt;
  {{ checkboxModel }}        
&amp;lt;/div&amp;gt;

&amp;lt;script&amp;gt;
  new Vue({
    el: '#app',
    data: {
      checkboxModel: 'hello',
      trueValue: 'hello',
      falseValue: 'world'
    }
  });
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000; color: #ffffff;&quot;&gt;수식어&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-model을 이용할때, vue에선 작은 편의성 기능들을 수식어로 제공&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;.lazy&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;input값을 변경할 대 즉시 값이 동기화 되지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;v-model.lazy&lt;/u&gt; 사용하면 즉시 데이터가 동기화 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;.trim&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력값의 앞뒤 공백들 제거한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;v-model.trim&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;.number&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력값을 number로 형변환가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;v-model.number&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;필터&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필터는 자바스크립트 표현식 뒤에 적용하고 싶은 필터를 파이프 기호( | )와 함께 추가하면 된다. 이렇게 필터를 정의하면 공통적으로 같은 서식을 적용해야 하는 상황에 편리하게 대처할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1621321442564&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div id=&quot;app&quot;&amp;gt;
  {{ price | number }}
&amp;lt;/div&amp;gt;
&amp;lt;script&amp;gt;
  new Vue({
    el: #app,
    data: {
      price: 24300
    },
    filters: {
      number : function(value) {
        retrun new Intl.NumberFormat().format(value)
      }
    }
  })
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Vue, Nuxt</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/54</guid>
      <comments>https://developer-mobssie.tistory.com/54#entry54comment</comments>
      <pubDate>Mon, 17 May 2021 18:38:53 +0900</pubDate>
    </item>
    <item>
      <title>Vue 속성 사용</title>
      <link>https://developer-mobssie.tistory.com/53</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;methods&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;computed :&lt;/b&gt; 데이터의 경우에는 methods보다 computed를 사용하는 것이 좋음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계산된 속성은 getter, setter&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;watch :&lt;/b&gt; Vue 인스턴스의 데이터가 변경되는 시점을 감시해 메서드를 호출&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터가 변경되면 watch는 변경됨을 확인하고 메서드를 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;▶ 라이프사이클이 Vue 인스턴스의 이벤트를 후킹하는 것이라면, watch는 Vue 인스턴스의 데이터의 변경을 후킹하는 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Vue, Nuxt</category>
      <author>Developer Mobssie</author>
      <guid isPermaLink="true">https://developer-mobssie.tistory.com/53</guid>
      <comments>https://developer-mobssie.tistory.com/53#entry53comment</comments>
      <pubDate>Mon, 17 May 2021 17:38:23 +0900</pubDate>
    </item>
  </channel>
</rss>