<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Written by coh at home</title>
    <link>https://cheol5.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 20 May 2026 19:23:49 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>och</managingEditor>
    <item>
      <title>개발자로서 1년차를 회고하다</title>
      <link>https://cheol5.tistory.com/189</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;사실 1년이 지난 지는 꽤나 지난 시점이다. 25년 11월 11일에 1년차가 되었고, 이미 설연휴까지 지난 시점이다. 이미 많은 시간이 지났지만 스스로 다짐과 목표를 다시금 상기하는 의미로 블로그에 회고를 공개하고자 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;25년에는 참 많은 야근을 했던 것 같다. 지금 생각하면 바보 같은 일이지만, 신입으로서 뛰어난 퍼포먼스를 보여주고 싶었고 무리를 해서라도 일정 내에 일을 끝내고 싶었다. 그래서 밤 10시에 퇴근하기도 했고, 부모님 환갑 휴가도 쓰지 않고 반납하며 일을 진행했다. 팀원으로서 인정을 받았을지언정 나의 건강이나 내면은 나빠져갔다. 그러다가 이렇게 일을 하면 안 된다는 것을 1년차에 깨닫게 되었다.&amp;nbsp;&lt;/p&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년차가 되어서야 깨달았다. 그 사실을 아무도 알려주지 않았고, 회사를 다니며 다른 동료직원이 일정을 못 맞춰서 팀장님에게 깨지는 것을 옆에서 듣고 깨달았다. 그래서 1월부터는 그렇게 일정을 세웠다. 그 결과 저녁이 있는 삶이 보장이 되었고 그 결과 회사는 꽤나 다닐만한 곳이었다. 일정을 세울 때 간트차트로 이야기하게 되었고, 이를 통해 내 업무의 자율성을 획득하고 야근 압박에서 벗어나게 되었다. 빨리 알았다면 참 좋았을 텐데.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;25년도 내 성과 평과는 B를 받았다. 시키는 것만 잘했다는 의미이다. 그래서 이번엔 시키는 것 + a를 하고 있고, 도전적인 주제를 전달해서 우리 팀의 생산성과 성과를 높이고자 한다. 무엇을 만들면 좋을지 고민하고 그것을 개발해서 내 성과를 높이고자 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;25.12 ~ 26.01 Agent DB design&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;26.01 ~ 26.01 Parameter Validation 고도화 기능 -&amp;gt; (+a 장비의 전체뷰, 보고서 엑셀 기능 추가)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;26.02 ~ 26.02 Machine Issue Management 요청사항 처리 -&amp;gt; (+a 로 댓글기능에서의 알림기능을 추가하고자 함)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2월 4째주는 회사 워크숍교육으로 인해 일을 못한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;26.03 Agent Web FrontEnd 작업&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;26.03 ~ 26.04 Server Monitoring (제안)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;26.04 ~ 26.05 Asset Monitoring (제안)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Etc/life</category>
      <author>och</author>
      <guid isPermaLink="true">https://cheol5.tistory.com/189</guid>
      <comments>https://cheol5.tistory.com/189#entry189comment</comments>
      <pubDate>Wed, 18 Feb 2026 23:59:31 +0900</pubDate>
    </item>
    <item>
      <title>[혼공바코] 3주차</title>
      <link>https://cheol5.tistory.com/188</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;- 학습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;# Claude.md&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;proj의 구조, 코딩스타일, 핵심명령어를 문서화한 설정파일. 클로드코드 실행 시 자동으로 읽어들임. 3가지 특징이 핵심.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 맥락유지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 규칙저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 자동로드&lt;/p&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;처음에 /init명령어를 통해 기본 프로젝트 구조를 클로드가 파악한 후 작성하게 된다.&lt;/p&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1210&quot; data-origin-height=&quot;1162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pJFcD/dJMcabXlOoj/ZOasEWLN64WD560m4ux1y1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pJFcD/dJMcabXlOoj/ZOasEWLN64WD560m4ux1y1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pJFcD/dJMcabXlOoj/ZOasEWLN64WD560m4ux1y1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpJFcD%2FdJMcabXlOoj%2FZOasEWLN64WD560m4ux1y1%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;1210&quot; height=&quot;1162&quot; data-origin-width=&quot;1210&quot; data-origin-height=&quot;1162&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;</description>
      <category>Etc/도서</category>
      <author>och</author>
      <guid isPermaLink="true">https://cheol5.tistory.com/188</guid>
      <comments>https://cheol5.tistory.com/188#entry188comment</comments>
      <pubDate>Wed, 18 Feb 2026 22:40:47 +0900</pubDate>
    </item>
    <item>
      <title>[혼공바코] 2주차</title>
      <link>https://cheol5.tistory.com/187</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;2주차 기본미션&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle; background-color: #ffffff; color: #24292f; text-align: start;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li style=&quot;list-style-type: unset;&quot;&gt;PROJECT 2. 마케팅 포트폴리오 웹페이지 만들고 캡처하기&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1924&quot; data-origin-height=&quot;1274&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brfneM/dJMcagxuwkU/4fq4OZ4vO0lrWKuUxqTjJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brfneM/dJMcagxuwkU/4fq4OZ4vO0lrWKuUxqTjJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brfneM/dJMcagxuwkU/4fq4OZ4vO0lrWKuUxqTjJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrfneM%2FdJMcagxuwkU%2F4fq4OZ4vO0lrWKuUxqTjJ0%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;1924&quot; height=&quot;1274&quot; data-origin-width=&quot;1924&quot; data-origin-height=&quot;1274&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2164&quot; data-origin-height=&quot;2058&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfjDPi/dJMcaf6qivO/2bRLbOSG5yZE6J8RjLzbyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfjDPi/dJMcaf6qivO/2bRLbOSG5yZE6J8RjLzbyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfjDPi/dJMcaf6qivO/2bRLbOSG5yZE6J8RjLzbyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfjDPi%2FdJMcaf6qivO%2F2bRLbOSG5yZE6J8RjLzbyk%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;2164&quot; height=&quot;2058&quot; data-origin-width=&quot;2164&quot; data-origin-height=&quot;2058&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle; background-color: #ffffff; color: #24292f; text-align: start;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li style=&quot;list-style-type: unset;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f; text-align: left;&quot;&gt;p.66, p.80-81 확인 문제 풀고 인증하기&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f; text-align: left;&quot;&gt;P66&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f; text-align: left;&quot;&gt;1. 3번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f; text-align: left;&quot;&gt;2. 5W1H&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f; text-align: left;&quot;&gt;3. 2번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f; text-align: left;&quot;&gt;4. 2번/구체적인 프롬프트&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f; text-align: left;&quot;&gt;P80-81&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f; text-align: left;&quot;&gt;1. 3번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f; text-align: left;&quot;&gt;2. 2번&lt;/span&gt;&lt;/p&gt;</description>
      <category>Etc/도서</category>
      <author>och</author>
      <guid isPermaLink="true">https://cheol5.tistory.com/187</guid>
      <comments>https://cheol5.tistory.com/187#entry187comment</comments>
      <pubDate>Sun, 18 Jan 2026 19:30:32 +0900</pubDate>
    </item>
    <item>
      <title>[혼공바코 with 클로드코드] 1주차</title>
      <link>https://cheol5.tistory.com/186</link>
      <description>&lt;h1&gt;바이브코딩이란?&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI와 대화를 하며 개발하는 코딩 방식&lt;/p&gt;
&lt;h1&gt;모델선택형 vs 전용 모델형&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델 선택 : 커서, 윈드서프 -&amp;gt; 도구사용료 + 모델비용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전용 모델 : 클로드, 제미나이 -&amp;gt; 모델비용만 지불. 로컬 파일 접근 가능&lt;/p&gt;
&lt;h1&gt;웹페이지 만들어보기&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/taehojo/vibecoding/blob/master/PROMPTS.md&quot;&gt;https://github.com/taehojo/vibecoding/blob/master/PROMPTS.md&lt;/a&gt;&lt;br /&gt;클로드 홈페이지에서 앤트로픽의 아티팩트를 이용하여 생성.&lt;br /&gt;아티팩트 &amp;gt; 새 아티팩트 &amp;gt; 웹/앱 만들기&lt;/p&gt;
&lt;h1&gt;프롬프트의 중요성&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 프롬프트란? 정확하고 구체적인 명령.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;명확성 : 모호한 표현 피하고 원하는 결과 전달&lt;/li&gt;
&lt;li&gt;구체성 : 필요한 기능이나 조건 세부적 지시&lt;/li&gt;
&lt;li&gt;맥락제공 : 왜 필요한지, 어떤 상황에 사용되는지 전달&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2196&quot; data-origin-height=&quot;776&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/df2n6F/dJMcaa44A03/XwVyYfC8r0sT054wa21lR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/df2n6F/dJMcaa44A03/XwVyYfC8r0sT054wa21lR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/df2n6F/dJMcaa44A03/XwVyYfC8r0sT054wa21lR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdf2n6F%2FdJMcaa44A03%2FXwVyYfC8r0sT054wa21lR0%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;2196&quot; height=&quot;776&quot; data-origin-width=&quot;2196&quot; data-origin-height=&quot;776&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 프롬프트를 만드는 프레임워크 : 5W1H&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Why&lt;/li&gt;
&lt;li&gt;Who&lt;/li&gt;
&lt;li&gt;What&lt;/li&gt;
&lt;li&gt;When&lt;/li&gt;
&lt;li&gt;Where&lt;/li&gt;
&lt;li&gt;How&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 결국 PRD와 일치하게 된다.&lt;br /&gt;PRD란, 제품 기획서로 개발 전에 작성하는 문서&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;778&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNlZcc/dJMcachv9WQ/shCREOmjP6SsMSQ1vMFI9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNlZcc/dJMcachv9WQ/shCREOmjP6SsMSQ1vMFI9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNlZcc/dJMcachv9WQ/shCREOmjP6SsMSQ1vMFI9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNlZcc%2FdJMcachv9WQ%2FshCREOmjP6SsMSQ1vMFI9K%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;1138&quot; height=&quot;778&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;778&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI에게 PRD를 만든 후 이를 기반으로 작성하는 것이 가장 효과적인 프롬프트.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;뼈대 : 기본 HTML구조 및 섹션 별 고유 아이디&lt;/li&gt;
&lt;li&gt;기능 : 실제 데이터 추가 및 로직 구현&lt;/li&gt;
&lt;li&gt;디자인 : UI/UX 적용 및 레퍼런스 (WD press)&lt;/li&gt;
&lt;li&gt;점검 : 테스트 및 품질 검수&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;기본미션&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 나의 첫웹페이지 만들고 캡쳐하기&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1128&quot; data-origin-height=&quot;2130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5BA4N/dJMcaacWgZr/z090TzouRX6VlyZqcVik5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5BA4N/dJMcaacWgZr/z090TzouRX6VlyZqcVik5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5BA4N/dJMcaacWgZr/z090TzouRX6VlyZqcVik5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5BA4N%2FdJMcaacWgZr%2Fz090TzouRX6VlyZqcVik5k%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;1128&quot; height=&quot;2130&quot; data-origin-width=&quot;1128&quot; data-origin-height=&quot;2130&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. p33, p54-55&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;p33&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번문제. 순서대로. 챗지피티, 커서, 클로드코드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2번문제. 순서대로. 바이브코딩, AI어시스턴트, 모델 선택형, 전용 모델형&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;p54-55&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번문제. 딥러닝 -&amp;gt; 뉴럴넷 -&amp;gt; 트랜스포머 -&amp;gt; LLM&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2번문제. 도구사용료와 모델 비용을 모두 지불한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3번문제. 아티팩트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4번문제. 게시&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5번문제. 사용자지정&lt;/p&gt;</description>
      <category>Etc/도서</category>
      <author>och</author>
      <guid isPermaLink="true">https://cheol5.tistory.com/186</guid>
      <comments>https://cheol5.tistory.com/186#entry186comment</comments>
      <pubDate>Sun, 11 Jan 2026 17:15:04 +0900</pubDate>
    </item>
    <item>
      <title>[도서리뷰] 혼자공부하는 바이브코딩</title>
      <link>https://cheol5.tistory.com/185</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #0900ff;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;&quot;한빛미디어 서평단 &amp;lt;나는리뷰어다&amp;gt; 활동을 위해서 책을 협찬&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;받아 작성된 서평입니다.&quot;&lt;/span&gt;&lt;/span&gt;&lt;/b&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-origin-width=&quot;454&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dubeFA/dJMcadm3X4q/tQTaog7gMrJ0Lsf3arISnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dubeFA/dJMcadm3X4q/tQTaog7gMrJ0Lsf3arISnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dubeFA/dJMcadm3X4q/tQTaog7gMrJ0Lsf3arISnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdubeFA%2FdJMcadm3X4q%2FtQTaog7gMrJ0Lsf3arISnk%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;454&quot; height=&quot;630&quot; data-origin-width=&quot;454&quot; data-origin-height=&quot;630&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;/p&gt;
&lt;p data-ke-size=&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;개발자로서 책에서 좋았던 것은 3가지 입니다.&lt;/p&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. 어떻게 프롬프트를 이용해야 하는가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 클로드 설정 파일(CLAUDE.md)을 어떻게 이용해야 하는가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 클로드 코드를 처음 사용할 때 알면 좋은 기능 정보들.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 AI를 활용하면서 5W1H(프롬프트를 작성할 때 전달할 내용)을 작성해보진 않았는데, 제가 지금껏 느낌적으로 작성했던 프롬프트와는 좀 달라서 한번 적용해보려고 합니다. ㅎㅎ 그리고 클로드 설정파일은 저는 무조건 활용해야한다고 생각했는데 책에서 다루고 있어서 그 점이 좋았습니다. 마지막으로 저는 클로드 코드를 처음 접했을 때, 모르는 것이 많아서 못 쓰는 기능이 많았습니다. 그런 부분을 혼공바에선 확실하게 긁어주고 있습니다. 혼공바에선 기능들을 실습과 함께 어떻게 사용하는지 배울 수 있어서 사용자가 문서를 읽는 시간을 아낄 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI시대, 어떻게 개발이 진행되고 있는지 관심이 있다면 꼭 추천해주고 싶은 책입니다.&lt;/p&gt;</description>
      <category>Etc/도서</category>
      <author>och</author>
      <guid isPermaLink="true">https://cheol5.tistory.com/185</guid>
      <comments>https://cheol5.tistory.com/185#entry185comment</comments>
      <pubDate>Mon, 29 Dec 2025 22:24:19 +0900</pubDate>
    </item>
    <item>
      <title>[Real Mysql] 시스템변수</title>
      <link>https://cheol5.tistory.com/184</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;/p&gt;</description>
      <category>CS/DataBase</category>
      <author>och</author>
      <guid isPermaLink="true">https://cheol5.tistory.com/184</guid>
      <comments>https://cheol5.tistory.com/184#entry184comment</comments>
      <pubDate>Sat, 13 Dec 2025 15:41:53 +0900</pubDate>
    </item>
    <item>
      <title>[DB] 백업 및 복원 고도화</title>
      <link>https://cheol5.tistory.com/183</link>
      <description>&lt;h1&gt;개요&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;https://velog.velcdn.com/images/coh/post/03f952bd-1d68-4a6a-bf98-66763bf1b26c/image.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2&gt;목적&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;기존의 백업도구(mysqldump)는 데이터량에 따라 백업과 복원 시간이 선형적 혹은 그 이상으로 증가한다. 이를 개선한다.&lt;/li&gt;
&lt;li&gt;백업과 복원이 얼마나 진행되었는지 정보를 제공한다.&lt;/li&gt;
&lt;li&gt;백업과 복원에 대한 히스토리를 제공한다.&lt;h2&gt;목표&lt;/h2&gt;
&lt;/li&gt;
&lt;li&gt;백업과 복원 속도를 개선한다.&lt;/li&gt;
&lt;li&gt;백업과 복원에 대한 정보를 제공한다.&lt;h2&gt;배경&lt;/h2&gt;
&lt;/li&gt;
&lt;li&gt;DB의 메모리는 서버의 50%까지 사용한다.&lt;/li&gt;
&lt;li&gt;서버의 하드디스크 크기는 1Tb이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;운영환경&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;DB에 5초마다 730건의 record가 insert가 되고 있다.&lt;/li&gt;
&lt;li&gt;최초 풀백업 데이터량은 약 5억건이다.&lt;/li&gt;
&lt;li&gt;이미지, 동영상 파일도 백업이 되어야한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;테스트 환경&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;0.1초마다 730 record insert를 1000회 수행 후 증분백업 진행. (약 5000초 가정)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;기존 시스템&lt;/h1&gt;
&lt;p&gt;우리의 DB에는 약 9억건의 데이터가 존재하는 DB가 있다. 이를 mysqldump로 풀백업 및 복원을 했을 때 시간은 다음과 같다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;백업 : 약 1시간&lt;/li&gt;
&lt;li&gt;복원 : 약 14시간&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이는 mysqldump의 특징으로 데이터의 양이 많을 수록 복원 성능이 무척 떨어진다. 이를 이해하기 위해선 &lt;code&gt;논리적 백업과 물리적 백업&lt;/code&gt;에 대해 이해할 필요가 있다.&lt;/p&gt;
&lt;h2&gt;논리적 백업 vs 물리적 백업&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;논리적 백업 : 데이터를 sql문으로 저장한다. 실제로 mysqldump의 파일을 열어보면 insert로 백업이 되는 것을 확인할 수 있다. &lt;/li&gt;
&lt;li&gt;물리적 백업 : 데이터 파일을 직접 복사한다. 따라서 백업된 파일의 크기가 DB의 크기와 비슷하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;논리적 백업은 insert를 계속하게 되면 OS에서는 더티페이지가 쌓이게 되고 이것을 주기적으로 플러싱하는 과정이 발생하게 된다. 따라서 데이터양이 많을수록 복원시간은 선형시간보다 더 증가하게 된다.&lt;/p&gt;
&lt;p&gt;물리적 백업은 데이터 파일을 직접 복사하다보니 백업 파일의 용량이 크다. 따라서 용량 관리가 필수적이다. 복원도 파일을 다시 복사하는 방식이다보니 백업 속도와 비슷하다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;각 백업 종류에 따른 풀백업 및 복원 시간 비교&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;9억건&lt;/th&gt;
&lt;th&gt;논리적 백업&lt;/th&gt;
&lt;th&gt;물리적 백업&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;백업시간&lt;/td&gt;
&lt;td&gt;1시간 8분&lt;/td&gt;
&lt;td&gt;57분&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;복원시간&lt;/td&gt;
&lt;td&gt;14시간 52분&lt;/td&gt;
&lt;td&gt;45분&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;</description>
      <category>CS/DataBase</category>
      <author>och</author>
      <guid isPermaLink="true">https://cheol5.tistory.com/183</guid>
      <comments>https://cheol5.tistory.com/183#entry183comment</comments>
      <pubDate>Fri, 7 Nov 2025 22:57:23 +0900</pubDate>
    </item>
    <item>
      <title>&amp;lt;소문난 명강의&amp;gt; 크리핵티브의 한 권으로 끝내는 웹 해킹 바이블</title>
      <link>https://cheol5.tistory.com/182</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;306&quot; data-origin-height=&quot;394&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ca3zge/dJMb9WMdtEZ/Eg7Yvc0LwyWDfYKKRk6kFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ca3zge/dJMb9WMdtEZ/Eg7Yvc0LwyWDfYKKRk6kFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ca3zge/dJMb9WMdtEZ/Eg7Yvc0LwyWDfYKKRk6kFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fca3zge%2FdJMb9WMdtEZ%2FEg7Yvc0LwyWDfYKKRk6kFk%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;306&quot; height=&quot;394&quot; data-origin-width=&quot;306&quot; data-origin-height=&quot;394&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;b&gt;&lt;span style=&quot;color: #0900ff;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;&quot;한빛미디어 서평단 &amp;lt;나는리뷰어다&amp;gt; 활동을 위해서 책을 협찬&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;받아 작성된 서평입니다.&quot;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;공격을 알아야 방어가 보인다&amp;rdquo;라는 문구가 딱 맞는 책이다. 이 책은 웹 개발자와 정보보안 입문자가 &lt;span&gt;&lt;b&gt;실무에서 통하는 보안 감각&lt;/b&gt;&lt;/span&gt;을 빠르게 기를 수 있도록 구성된 실용서다. 단순한 공격 나열이나 도구 사용법에 그치지 않고, 왜 그런 공격이 가능한지(원리)와 프로그램&amp;middot;프레임워크&amp;middot;운영체제&amp;middot;네트워크 관점에서 취약점이 어떻게 연결되는지를 함께 설명하려는 점이 가장 큰 장점이다.&lt;/p&gt;
&lt;p data-ke-size=&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;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;기본기부터 실습까지의 자연스러운 흐름&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;웹 기술의 기초를 다진 뒤, 웹 프록시 등 실습 도구로 직접 공격을 재현해보는 구조라 따라가기가 쉽다. 이론 &amp;rarr; 도구 이해 &amp;rarr; 실습의 흐름이 학습 곡선을 완만하게 만들어 준다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;핵심 공격 기법의 실전적 접근&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;SQL 인젝션, OS 커맨드 인젝션, XSS 등 주요 취약점에 대해 단편적 예제가 아니라 실제 환경에서의 재현과 해석을 통해 &amp;ldquo;왜 취약한가&amp;rdquo;를 체득하게 한다. 이 때문에 단순히 시그니처만 찾는 수준을 넘어서 구조적&amp;middot;근본적 취약점 식별 능력이 생긴다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;시스템 전반을 보는 시야 확장&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;코드 수준뿐 아니라 프레임워크, 라이브러리, 운영체제, 네트워크 등 다양한 층(layer)을 연결해 설명해 주므로, 문제를 더 넓게 보는 습관이 생긴다. 이는 보안 실무에서 매우 중요한 능력이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&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;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;초보자에게는 일부 심화 설명이 빠르게 느껴질 수 있다. 기본 개념에 아주 서투른 독자라면 별도의 기초 자료와 병행 학습하면 더 효과적이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Etc/도서</category>
      <author>och</author>
      <guid isPermaLink="true">https://cheol5.tistory.com/182</guid>
      <comments>https://cheol5.tistory.com/182#entry182comment</comments>
      <pubDate>Mon, 27 Oct 2025 07:25:34 +0900</pubDate>
    </item>
    <item>
      <title>[혼공학습단] 후기</title>
      <link>https://cheol5.tistory.com/180</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이야,,, 회사일을 병행하면서 공부를 하는 게 쉽지 않더라구요,, 특히 7월말부터 플젝 마감과 이슈 대응을 하면서 저녁 늦게 야근을 많이했는데요... 거의 회사에 있는 시간만 12시간이 넘어갔어요... (오전 8시 ~ 오후 8:30)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러다보니 혼공스를 읽는 속도도 더뎌지더라구요,,, 매번 기한 늘려주신 족장님 다시한번 감사하고 죄송합니다 ㅜㅜ&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;259&quot; data-origin-height=&quot;194&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgnI2s/btsP4kOD6ID/XwbNm4OKJ5WK9GgIRkOWTK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgnI2s/btsP4kOD6ID/XwbNm4OKJ5WK9GgIRkOWTK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgnI2s/btsP4kOD6ID/XwbNm4OKJ5WK9GgIRkOWTK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgnI2s%2FbtsP4kOD6ID%2FXwbNm4OKJ5WK9GgIRkOWTK%2Fimg.jpg&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;330&quot; height=&quot;247&quot; data-origin-width=&quot;259&quot; data-origin-height=&quot;194&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;물론 아직 ch8이 남아있어서 불완전한 완주지만요 ㅠㅠ 이건 반드시 다음주 내로 다 읽고 업데이트 하도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;749&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brHiKP/btsP4ZDejU3/vzj3pIrtRDGzxcfMha73YK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brHiKP/btsP4ZDejU3/vzj3pIrtRDGzxcfMha73YK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brHiKP/btsP4ZDejU3/vzj3pIrtRDGzxcfMha73YK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrHiKP%2FbtsP4ZDejU3%2Fvzj3pIrtRDGzxcfMha73YK%2Fimg.jpg&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;749&quot; height=&quot;512&quot; data-origin-width=&quot;749&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Etc/도서</category>
      <author>och</author>
      <guid isPermaLink="true">https://cheol5.tistory.com/180</guid>
      <comments>https://cheol5.tistory.com/180#entry180comment</comments>
      <pubDate>Sun, 24 Aug 2025 22:32:37 +0900</pubDate>
    </item>
    <item>
      <title>[혼공스] 6주차 Ch7, 8</title>
      <link>https://cheol5.tistory.com/179</link>
      <description>&lt;h1&gt;숙제&lt;/h1&gt;
&lt;p&gt;p352 누적예제를 활용하여 본인의 할 일 목록을 만들어 캡쳐하기&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1226&quot; data-origin-height=&quot;468&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDCWsB/btsP4uDuyUA/GCoKe1yKyT5yZrSuV56jdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDCWsB/btsP4uDuyUA/GCoKe1yKyT5yZrSuV56jdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDCWsB/btsP4uDuyUA/GCoKe1yKyT5yZrSuV56jdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDCWsB%2FbtsP4uDuyUA%2FGCoKe1yKyT5yZrSuV56jdK%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;1226&quot; height=&quot;468&quot; data-origin-width=&quot;1226&quot; data-origin-height=&quot;468&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;script&amp;gt;

document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;gt; {

    const todoList = document.querySelector(&amp;#39;#todo-list&amp;#39;)
    const input = document.querySelector(&amp;#39;#todo&amp;#39;)
    const addBtn = document.querySelector(&amp;#39;#add-button&amp;#39;)

    let keyCount = 0;
    const addTodo = () =&amp;gt; {
        if (input.value.trim() === &amp;#39;&amp;#39;) {
            alert (&amp;#39;Add your todo-list&amp;#39;)
            return
        }
        const item = document.createElement(&amp;#39;div&amp;#39;)
        const checkBox = document.createElement(&amp;#39;input&amp;#39;)
        const text = document.createElement(&amp;#39;span&amp;#39;)
        const button = document.createElement(&amp;#39;button&amp;#39;)

        const key = keyCount
        keyCount += 1

        item.setAttribute(&amp;#39;data-key&amp;#39;, key)
        item.appendChild(checkBox)
        item.appendChild(text)
        item.appendChild(button)
        todoList.appendChild(item)

        checkBox.type = &amp;#39;checkbox&amp;#39;
        checkBox.addEventListener(&amp;#39;change&amp;#39;, (e) =&amp;gt; {
            item.style.textDecoration = e.target.checked ? &amp;#39;line-through&amp;#39; : &amp;#39;&amp;#39;
        })

        text.textContent = input.value;
        button.textContent = &amp;#39;remove&amp;#39;
        button.addEventListener(&amp;#39;click&amp;#39;, (e) =&amp;gt; {
            // item.parentNode.removeChild(item)
            removeTodo(key);
        })

        input.value =&amp;#39;&amp;#39;

    }
    const removeTodo = (key) =&amp;gt; {
            const item = document.querySelector(`[data-key=&amp;quot;${key}&amp;quot;]`)
            todoList.removeChild(item);
        }

    addBtn.addEventListener(&amp;#39;click&amp;#39;, addTodo)
        input.addEventListener(&amp;#39;keyup&amp;#39;, (e) =&amp;gt; {
            const ENTER = 13; 
            if (e.keyCode === ENTER)
                addTodo()
        })
})
&amp;lt;/script&amp;gt;
&amp;lt;style&amp;gt;
    h1 { user-select: none;}
&amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;할 일 목록&amp;lt;/h1&amp;gt;
    &amp;lt;input id=&amp;quot;todo&amp;quot; /&amp;gt;
    &amp;lt;button id=&amp;quot;add-button&amp;quot;&amp;gt;ADD&amp;lt;/button&amp;gt;
    &amp;lt;div id=&amp;quot;todo-list&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;ch7 문서책체&lt;/h1&gt;
&lt;p&gt;html의 태그들을 자바스크립트에서는 document object라고 부른다. 이런 태그들로 만든 형태를 문서객체모델(DOM)이라고 한다.&lt;/p&gt;
&lt;h2&gt;DOMContentLoaded&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;title&amp;gt;Doc&amp;lt;/title&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;웹브라우저의 실행 순서는 다음과 같다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;: html5문서구나&lt;/li&gt;
&lt;li&gt;html 태그 만들어야지&lt;/li&gt;
&lt;li&gt;head 태그 만들어야지&lt;/li&gt;
&lt;li&gt;title 태그가 있으니 반영해야지&lt;/li&gt;
&lt;li&gt;body 태그가 있으니 반영해야지&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;만약 body태그가 만들어지지 않았는데 body에 무언가를 출력하려고 하면 문제가 발생한다.&lt;br&gt;따라서 이를 해결하기 위해서, 웹브라우저가 문서 객체를 모두 읽고 나서 실행하는 이벤트가 DOMContentLoaded이다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;documnet.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;gt; {
    const h1 = (text) =&amp;gt; `&amp;lt;h1&amp;gt;${text}&amp;lt;/h1&amp;gt;`;
    document.body.innerHTML += h1(&amp;#39;hello&amp;#39;);
});&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;문서객체 가져오기&lt;/h2&gt;
&lt;p&gt;head, body, title태그를 제외한 다른 요소들은 querySelector라는 메서드를 통해서 요소를 가져올 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;document.body
document.head
document.title

document.querySelector(선택자) // 문서객체 한 개
document.querySelctorAll(선택자) // 문서객체 여러개 &lt;/code&gt;&lt;/pre&gt;&lt;p&gt;선택자 부분에는 CSS 선택자를 입력해야한다. 기본적인 CSS 선택자는 다음과 같다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;이름&lt;/th&gt;
&lt;th&gt;선택자형태&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;태그 선택자&lt;/td&gt;
&lt;td&gt;태그&lt;/td&gt;
&lt;td&gt;특정 태그를 가진 요소 추출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;아이디 선택자&lt;/td&gt;
&lt;td&gt;#아이디&lt;/td&gt;
&lt;td&gt;특정 id 속성을 가진 요소를 추출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;클래스 선택자&lt;/td&gt;
&lt;td&gt;.클래스&lt;/td&gt;
&lt;td&gt;특정 class 속성을 가진 요소를 추출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;속성 선택자&lt;/td&gt;
&lt;td&gt;[속성=값]&lt;/td&gt;
&lt;td&gt;특정 속성 값을 갖고 있는 요소를 추출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;후손 선택자&lt;/td&gt;
&lt;td&gt;선택자_A 선택자_B&lt;/td&gt;
&lt;td&gt;선택자_A 아래의 선택자_B를 선택&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;querySelector&lt;br&gt;문서 객체 한 개 선택.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;gt; {
        const header = document.querySelector(&amp;#39;h1&amp;#39;)

        header.textContent = &amp;#39;HEADER&amp;#39;
        header.style.color = &amp;#39;white&amp;#39;
        header.style.backgroundColor = &amp;#39;black&amp;#39;
        header.style.padding = &amp;#39;10px&amp;#39;
    })&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;querySelectorAll&lt;br&gt;문서객체 여러 개 선택. forEach문을 사용해서 활용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;gt; {
        const header = document.querySelectorAll(&amp;#39;h1&amp;#39;)

        header.forEach((header, idx) =&amp;gt; {
            header.textContent = &amp;#39;HEADER_&amp;#39; + idx
            header.style.color = &amp;#39;white&amp;#39;
            header.style.backgroundColor = &amp;#39;black&amp;#39;
            header.style.padding = &amp;#39;10px&amp;#39;
        })
    })&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;글자 조작하기&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;속성이름&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;문서객체.innerHTML&lt;/td&gt;
&lt;td&gt;입력된 문자열을 html형식으로 넣는다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;문서객체.textContent&lt;/td&gt;
&lt;td&gt;입력된 문자열 그대로 넣는다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code&gt;    document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;gt; {
        const a = document.querySelector(&amp;#39;#a&amp;#39;)
        const b = document.querySelector(&amp;#39;#b&amp;#39;)

        a.textContent = &amp;#39;&amp;lt;h1&amp;gt;textContent&amp;lt;/h1&amp;gt;&amp;#39;
        b.innerHTML = &amp;#39;&amp;lt;h1&amp;gt;innerHTML&amp;lt;/h1&amp;gt;&amp;#39;
    })&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;206&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dctB65/btsP2DhlQAB/E481kfuzyGKtGPKhOioda0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dctB65/btsP2DhlQAB/E481kfuzyGKtGPKhOioda0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dctB65/btsP2DhlQAB/E481kfuzyGKtGPKhOioda0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdctB65%2FbtsP2DhlQAB%2FE481kfuzyGKtGPKhOioda0%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;644&quot; height=&quot;206&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;206&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2&gt;속성 조작하기&lt;/h2&gt;
&lt;p&gt;메서드를 통해 문서 객체의 속성을 조작할 수 있다. class, src, id 등 속성을 부여하거나 가져올 수 있다.&lt;br&gt;setAttribute(속성이름, 값)&lt;br&gt;getAttribute(속성이름)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &amp;lt;img class=&amp;quot;rect&amp;quot; /&amp;gt;
    &amp;lt;img class=&amp;quot;rect&amp;quot; /&amp;gt;
    &amp;lt;img class=&amp;quot;rect&amp;quot; /&amp;gt;
    &amp;lt;img class=&amp;quot;rect&amp;quot; /&amp;gt;
...

document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;gt; {
        const rects = document.querySelectorAll(&amp;#39;.rect&amp;#39;);

        rects.forEach((rect, idx) =&amp;gt; {
            const width = (idx + 1) * 100;
            const src = `http//placekitten.com/${width}/250`
            rect.setAttribute(&amp;#39;src&amp;#39;, src);
        })
    })&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;스타일 조작하기&lt;/h2&gt;
&lt;p&gt;문서 객체의 스타일을 먹이기 위해서 style 속성을 사용한다. CSS파일을 이용할 때와 이름이 살짝 다르다. 낙타표기법을 사용한다.&lt;br&gt;text-align -&amp;gt; textAlign 이렇게!&lt;/p&gt;
&lt;p&gt;속성을 먹이는 방법은 다음과 같다.&lt;br&gt;h1.style.backgroundColor = &amp;#39;black&amp;#39;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;gt; {
        const divs = document.querySelectorAll(&amp;#39;div&amp;#39;)

        divs.forEach((div, idx) =&amp;gt; {
            console.log(div, idx)
            const val = idx * 10;
            div.style.height = `10px`
            div.style.backgroundColor = `rgba(${val}, ${val}, ${val})`;
        });
    });&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1204&quot; data-origin-height=&quot;518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RFQU2/btsP47BeZig/GuqKcC2YrQKlcscjZMndp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RFQU2/btsP47BeZig/GuqKcC2YrQKlcscjZMndp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RFQU2/btsP47BeZig/GuqKcC2YrQKlcscjZMndp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRFQU2%2FbtsP47BeZig%2FGuqKcC2YrQKlcscjZMndp0%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;1204&quot; height=&quot;518&quot; data-origin-width=&quot;1204&quot; data-origin-height=&quot;518&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2&gt;문서객체 생성하기&lt;/h2&gt;
&lt;p&gt;document.createElement(문서객체이름) 메서드를 통해 문서객체를 생성할 수 있고 이것을 어떤 요소 아래에 달 건지를 결정해야한다. 트리구조와 똑같다. 따라서 appendChild메서드가 있다.&lt;/p&gt;
&lt;p&gt;부모객체.appendChild(자식객체);&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;gt; {
    const h1 = document.createElement(&amp;#39;h1&amp;#39;);
    h1.textContent = &amp;#39;hello&amp;#39;;
    h1.style.color = &amp;#39;white&amp;#39;;
    h1.style.backgroundColor = &amp;#39;black&amp;#39;;
    h1.setAttribute(&amp;quot;data-custom&amp;quot;, &amp;#39;사용자 정의속성&amp;#39;);
    document.body.appendChild(h1);
})&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;문서객체 이동하기&lt;/h2&gt;
&lt;p&gt;appendChild()는 문서객체를 이동할 때도 사용할 수 있다. 해당 객체에 대한 부모는 언제나 하나여야 한다.&lt;br&gt;따라서 문서객체를 다른 문서객체에 추가하면 문서 객체가 이동한다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;gt; {

    const divA = document.querySelector(&amp;#39;#first&amp;#39;)
    const divB = document.querySelector(&amp;#39;#second&amp;#39;)

    const h1 = document.createElement(&amp;#39;h1&amp;#39;)
    h1.textContent = &amp;#39;이동하는 h1 tag&amp;#39;

    const toFirst = () =&amp;gt; {
        divA.appendChild(h1);
        setTimeout(toSecond, 1000)
    }

    const toSecond = () =&amp;gt; {
        divB.appendChild(h1);
        setTimeout(toFirst, 2000)

    }
    toFirst()
})&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;문서객체 제거하기&lt;/h2&gt;
&lt;p&gt;부모객체.removeChild(자식객체)&lt;/p&gt;
&lt;p&gt;자식객체.parentNode.removeChild(자식객체)&lt;br&gt;자식은 부모에 parentNode를 통해 접근할 수 있다. 그래서 일반적으로 위와 같은 코드를 많이 사용한다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    setTimeout(() =&amp;gt; {
        const h1 = document.querySelector(&amp;#39;h1&amp;#39;)
        h1.parentNode.removeChild(h1);
    }, 3000);&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;이벤트 설정하기&lt;/h2&gt;
&lt;p&gt;addEventListener를 통해서 진행한다.&lt;br&gt;user-select:none 으로 지정하면, 해당태그를 마우스로 드래그할 수 없다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;script&amp;gt;
document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;gt; {
    let count = 0;

    const h1 = document.querySelector(&amp;#39;h1&amp;#39;);
    h1.addEventListener(&amp;#39;click&amp;#39;, (e) =&amp;gt; {
        count++;
        h1.textContent = count;
    });
})
&amp;lt;/script&amp;gt;
&amp;lt;style&amp;gt;
    h1 { user-select: none;}
&amp;lt;/style&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;이벤트 제거하기&lt;/h2&gt;
&lt;p&gt;removeEventListener를 통해서 제거한다.&lt;br&gt;문서객체.removeEventListener(이벤트이름, 이벤트리스너)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;gt; {
    let count = 0;
    let isConnect = false;

    const h1 = document.querySelector(&amp;#39;h1&amp;#39;);
    const p = document.querySelector(&amp;#39;p&amp;#39;);
    const connectButton = document.querySelector(&amp;#39;#connect&amp;#39;)
    const disconnectButton = document.querySelector(&amp;#39;#disconnect&amp;#39;)

    const listener = (e) =&amp;gt; {
        h1.textContent = `click:${count++}`;
    }

    connectButton.addEventListener(&amp;#39;click&amp;#39;, () =&amp;gt; {
        if (isConnect === false) {
            isConnect = true;
            h1.addEventListener(&amp;#39;click&amp;#39;, listener);
            p.textContent = `이벤트상태:${isConnect}`
        }
    })

    disconnectButton.addEventListener(&amp;#39;click&amp;#39;, () =&amp;gt; {
        if (isConnect === true) {
            isConnect = false;
            h1.removeEventListener(&amp;#39;click&amp;#39;, listener);

            p.textContent = `이벤트상태:${isConnect}`

        }
    })
})&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;이벤트 모델&lt;/h2&gt;
&lt;p&gt;사전 html기본을 알고 있어야 한다. 이제 지금까지 배운 것을 전부 활용해보자&lt;/p&gt;
&lt;p&gt;이벤트를 연결하는 방법을 이벤트 모델이라고 한다. 이건 두 가지로 나뉜다.&lt;br&gt;표준이벤트 모델 : addEvenetListener&lt;br&gt;고전이벤트 모델 : 문서객체 onxx 시작하는 속성에 이벤트 연결하는 것&lt;br&gt;인라인이벤트 모델 : html요소에 함수를 넣는 것&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const listener = (event) =&amp;gt; {...}
&amp;lt;div onkeyup=&amp;quot;listener(event)&amp;quot; &amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;사실 표준이벤트를 많이 쓰고, 요즘은 인라인이벤트도 조금씩 쓰고 있다.&lt;/p&gt;
&lt;h2&gt;키보드 이벤트&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;이벤트&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;keydown&lt;/td&gt;
&lt;td&gt;키가 눌릴 때 실행. 꾹 누를 때, 입력될 때. 한국어 처리는 못할 때가 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;keypress&lt;/td&gt;
&lt;td&gt;키가 입력되었을 때 실행. 아시아권 문자는 처리 못할 때도 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;keyup&lt;/td&gt;
&lt;td&gt;키보드에서 키가 떨어질 때 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;일반적으로 keyup을 사용한다. 하지만 꾹 눌렀을 때 글씨를 세지 못하는 문제가 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39; () =&amp;gt; {
    const textArea = document.querySelector(&amp;#39;textarea&amp;#39;);
    const h1 = document.querySelector(&amp;#39;h1&amp;#39;);

    textArea.addEventListener(&amp;#39;keyup&amp;#39;, (e) =&amp;gt; {
        const length = textArea.value.length
        h1.textContent = `글자수:${length}`
    })
})&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;키보드 키코드&lt;/h2&gt;
&lt;p&gt;키보드 이벤트가 발생할 때는 이벤트 객체로 어떤 키를 눌렀는지를 알 수 있다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;이벤트 속성 이름&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;code&lt;/td&gt;
&lt;td&gt;입력한 키&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;keyCode&lt;/td&gt;
&lt;td&gt;입력한 키를 나타내는 숫자&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;altKey&lt;/td&gt;
&lt;td&gt;alt키를 눌렀는지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ctrlKey&lt;/td&gt;
&lt;td&gt;ctrl키를 눌렀는지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shiftKey&lt;/td&gt;
&lt;td&gt;shift키를 눌렀는지&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;code 속성은 입력한 키에 대한 문자열이 들어있고 altKey, ctrlKey 등은 boolean값이 들어있다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;script&amp;gt;
document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;gt; {
    const h1 = document.querySelector(&amp;#39;h1&amp;#39;)
    const print = (e) =&amp;gt; {
        let output = &amp;#39;&amp;#39;
        output += `alt:${e.altKey}&amp;lt;br&amp;gt;`
        output += `ctrl:${e.ctrlKey}&amp;lt;br&amp;gt;`
        output += `shift:${e.shiftKey}&amp;lt;br&amp;gt;`
        output += `code:${typeof(e.code) !== &amp;#39;undefined&amp;#39; ? e.code : e.keyCode}&amp;lt;br&amp;gt;`
        h1.innerHTML = output;
    }

    document.addEventListener(&amp;#39;keydown&amp;#39;, print)
    document.addEventListener(&amp;#39;keyup&amp;#39;, print)
})
&amp;lt;/script&amp;gt;
&amp;lt;style&amp;gt;
    h1 { user-select: none;}
&amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;hr&amp;gt;
    &amp;lt;textarea&amp;gt;&amp;lt;/textarea&amp;gt;
    &amp;lt;h1&amp;gt;&amp;lt;/h1&amp;gt;
    &amp;lt;hr&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;별을 이동시키는 게임을 구현할 때는 keydown을 많이 사용한다. 꾹누르는 것을 지원해줘야하기 때문.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;gt; {
    const star = document.querySelector(&amp;#39;h1&amp;#39;)
    star.style.position = &amp;#39;absolute&amp;#39;

    let [x, y] = [0, 0]
    const block = 20
    const print = () =&amp;gt; {
        star.style.left = `${x * block}px`
        star.style.top = `${y * block}px`
    }
    print()

    const [left, up, right, down] = [37,38,39,40]
    document.body.addEventListener(&amp;#39;keydown&amp;#39;, (e) =&amp;gt; {
        switch (e.keyCode)
        {
            case left:
                x -= 1
                break
            case up:
                y -= 1
                break
            case right:
                x += 1
                break
            case down:
                y += 1
                break
        }
        print()
    })
})&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;이벤트 발생객체&lt;/h2&gt;
&lt;p&gt;이벤트 리스너 함수를 외부로 빼낸 경우 변수 접근 문제가 생길 수 있습니다. 이럴 때 어떻게 해결할까용&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;event.currentTarget 속성을 사용합니다.&lt;/li&gt;
&lt;li&gt;this키워드를 사용합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;화살표 함수가 없을 때는 2번째 방법을 많이 사용했지만, 지금은 둘 다 많이 사용합니다. 라이브러리와 프레임워크에 따라 선호하는 방식이 다릅니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const listener = (event) =&amp;gt; {
    const len = event.currentTarget.value.length
    const h1 = document.querySelector(&amp;#39;h1&amp;#39;)
    h1.textContent = `글자수:${len}`
}

document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;gt; {
    const textArea = document.querySelector(&amp;#39;textarea&amp;#39;)
    textArea.addEventListener(&amp;#39;keyup&amp;#39;, listener)
})&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;글자 입력 양식 이벤트&lt;/h2&gt;
&lt;p&gt;사용자로부터 어떠한 입력을 받을 때 사용하는 요소를 form이라고 합니다.&lt;br&gt;input, textarea, button, select 태그 등이 모두 입력양식입니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;gt; {
    const input = document.querySelector(&amp;#39;input&amp;#39;)
    const button = document.querySelector(&amp;#39;button&amp;#39;)
    const p = document.querySelector(&amp;#39;p&amp;#39;)

    button.addEventListener(&amp;#39;click&amp;#39;, () =&amp;gt; {
        const inch = Number(input.value)

        if (isNaN(inch))
        {
            p.textContent = &amp;#39;not a number&amp;#39;
            return
        }
        const cm = inch * 2.54
        p.textContent = cm;
    })
})&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;들여쓰기를 줄이면 코드가 깔끔해집니다. else문은 최대한 안쓰는 게 좋죠.&lt;/p&gt;
&lt;h2&gt;드롭다운&lt;/h2&gt;
&lt;p&gt;select 태그와 option태그를 통해 구현할 수 있습니다. 이건, value도 사용이 가능하긴 한데, 보통 options와 index를 통해 접근하는게 더 안전한 거 같습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;gt; {
    const select = document.querySelector(&amp;#39;select&amp;#39;)
    const p = document.querySelector(&amp;#39;p&amp;#39;)

    select.addEventListener(&amp;#39;change&amp;#39;, (e) =&amp;gt; {
        const value = e.currentTarget.value;
        const idx = e.currentTarget.selectedIndex;

        p.textContent = `choice:${value}`
    })
})&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;여기서 multiple 속성을 부여하면 select박스의 아이템을 여러개 선택할 수 있습니다. 보통 체크박스가 낫습니다.&lt;/p&gt;
&lt;h1&gt;ch8 예외처리&lt;/h1&gt;</description>
      <category>Etc/도서</category>
      <author>och</author>
      <guid isPermaLink="true">https://cheol5.tistory.com/179</guid>
      <comments>https://cheol5.tistory.com/179#entry179comment</comments>
      <pubDate>Sun, 24 Aug 2025 22:19:22 +0900</pubDate>
    </item>
  </channel>
</rss>