<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>기록</title>
    <link>https://hachamo.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 15 Jun 2026 13:08:33 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>하차모</managingEditor>
    <item>
      <title>5강 손익계산서 계정</title>
      <link>https://hachamo.tistory.com/70</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;수익 계정에서 관리하는 계정과목&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;수익의 원천별 분류&amp;gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;영업수익 : 주된 영업활동의 수익(=매출) &amp;rarr; 계속적, 반복적인 판매수익&lt;/li&gt;
&lt;li&gt;영업외수익 : 주된 영업활동 외의 수익 &amp;rarr; 영업수익(매출) 외의 모든 수익&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;영업수익과 영업외수익&amp;gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;영업수익 : 영업활동 중 제품, 상품, 서비스 판매수익 &amp;rarr; 매출&lt;/li&gt;
&lt;li&gt;영업외수익에 속하는 계정과목 : 이자수익, 제춤, 상품 외의 각종 자산의 처분이익, 임대료&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(주) 서울은 전자제품판매업을 영위하고 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1년에 전자제품 100개를 단위당 100,000원에 판매하였음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매출 = 100,000원 * 100개 = 10,000,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1.1 (주)부산에 10,000,000원을 빌려주고, 20X1.12.31에 원금을 회수하기로 하였음. 이자율은 연 5%로 약정하였음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1년의 이자수익 = 10,000,000원 * 5% = 500,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1년에 소유하고 있던 1억원의 토지를 1억 5천만원에 처분하였음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처분이익 = 1억 5천만원 - 1억원 = 50,000,000원 (수익X)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1.7.1 건물 중 일부를 임대하고, 월 500,000원의 임대료를 받았음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1년 임대료 = 월 500,000 * 6개월 3,000,000원&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;비용 계정에서 관리하는 계정과목&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;비용의 원천별 분류&amp;gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;영업비용 : 주된 영업활동의 비용 &amp;rarr; 계속적, 반복적으로 발생&lt;/li&gt;
&lt;li&gt;영업외비용 : 주된 영업활동 외의 비용 &amp;rarr; 영업비용 외의 모든 비용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;영업비용에 속하는 계정과목&amp;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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;매출원가 : 판매한 상품, 제품의 원가&lt;/li&gt;
&lt;li&gt;판매비와 관리비(판관비) : 매출원가 외의 영업비용 (판관비는 계정과목이 아님)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영업비용(1) : 매출원가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(주) 서울은 전자제품판매업을 영위하고 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1년에 전자제품 10개를 단위당 50,000원에 매입하였고, 그 중 7개를 단위당 100,000원에 판매하였음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매출 = 100,000원 * 7개 = 700,000원 (수익)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매출원가 = 50,000원 * 7개 = 350,000원 (비용)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매출총이익 = 700,000 - 350,000 = 350,000원&lt;/p&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;영업비용 중 매출원가를 제외한 비용&amp;gt;&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;급여, 임금, 잡급&lt;/li&gt;
&lt;li&gt;지급수수료&lt;/li&gt;
&lt;li&gt;임차료&lt;/li&gt;
&lt;li&gt;보험료&lt;/li&gt;
&lt;li&gt;소모품비&lt;/li&gt;
&lt;li&gt;감가상각비 등&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(주) 서울은 전자제품판매업을 영위하고 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1년에 전자제품을 판매하는 과정에서 급여 20,000원, 잡급 15,000원, 지급수수료 15,000원, 임차료 30,000원, 보험료 20,000원의 비용이 발생하였음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;판매비와 관리비 = 20,000원 + 15,000원 + 15,000원 + 30,000원 + 20,000원 = 100,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1년에 전자제품 10개를 단위당 50,000원에 매입하였고, 그 중 7개를 단위당 100,000원에 판매하였음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 판매비와 관리비가 총 100,000원 발생하였음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매출 = 100,000원 * 7개 = 700,000원 (영업수익)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매출원가 = 50,000원 * 7개 = 350,000원 (영업비용)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;판매비와 관리비 = 100,000원 (영업비용)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영업이익 = 700,000 - 350,000 - 100,000원 = 250,000원&lt;/p&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;ex)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(주) 부산은 의류판매업을 영위하고 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1.1.1 사무실 운영에 필요한 소모품 10개를 단위당 10,000원에 매입하였는데, 1년 동안 6개를 사용하여 20X1년말 창고에는 소모품 4개만 남아 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1.1.1 : 소모품 = 10,000원 * 10개 = 100,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1.1.1-12.31 (소모품 사용) : 소모품비 = 10,000원 * 6개 = 60,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1.12.31 : 소모품 = 100,000원 - 60,000원 = 40,000원&lt;/p&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 data-ke-size=&quot;size16&quot;&gt;20X1.1.1 사무실에서 사용할 목적으로 복사기(비품)을 3,000,000원에 매입하였음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 비품은 3년(내용연수) 동안 사용할 수 있으며, 3년이 지나면 잔존가치가 &amp;lsquo;300,000원&amp;rsquo;이 됨. (추정)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감가상각은 정액법으로 함. (&amp;rarr; 내용연수만큼 똑같은 금액만큼 사용되어진다고 가정하는 것)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1.1.1 : 비품 = 3,000,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1.1.1-12.31 (비품 사용) : 감가상각비 = (3,000,000 - 300,000)원 / 3년 = 900,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1.12.31 : 비품 = 3,000,000 - 900,000 = 2,100,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X2.12.31 : 비품 = 2,100,000 - 900,000 = 1,200,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X3.12.31 : 비품 = 1,200,000 - 900,000 = 300,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;영업활동 외의 활동에서 발생하는 비용&amp;gt;&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;이자비용&lt;/li&gt;
&lt;li&gt;상품, 제품 외의 각종 자산의 처분손실&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(주) 서울은 전자제품판매업을 영위하고 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1.1.1 신한은행으로부터 사업 자금 10,000,000원을 대출받았으며, 1년 후 상환하기로 하였음. 연 이자율은 5%로 약정하였음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1년 이자비용 = 10,000,000원 * 5% = 500,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1년에 소유하고 있던 1억원의 토지를 9천만원에 처분하였음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처분손실 = 1억원 - 9천만원 = 10,000,000원&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;[참고] 임대료와 임대보증금, 임차료와 임차보증금&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구분 임대의 경우 임차의 경우&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&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;임차보증금(비유동자산)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;임대료 : 부동산임대업이라면 &amp;rarr; 매출, 그 외의 업종이라면 &amp;rarr; 영업외수익&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;임차료 : 영업활동을 위한 임차 &amp;rarr; 영업비용(매출원가 또는 판관비), 영업활동 외의 활동을 위한 임차의 경우 &amp;rarr; 영업외비용&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;계정과목 종합&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷(85).png&quot; data-origin-width=&quot;1079&quot; data-origin-height=&quot;770&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dPuQYW/btsAXidBVYK/uEqSvHptkLwNJafgihPvZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dPuQYW/btsAXidBVYK/uEqSvHptkLwNJafgihPvZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dPuQYW/btsAXidBVYK/uEqSvHptkLwNJafgihPvZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdPuQYW%2FbtsAXidBVYK%2FuEqSvHptkLwNJafgihPvZk%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;1079&quot; height=&quot;770&quot; data-filename=&quot;스크린샷(85).png&quot; data-origin-width=&quot;1079&quot; data-origin-height=&quot;770&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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;권상호 회계입문강의 5강 (&lt;a href=&quot;https://youtu.be/LXcBbkSdNxQ&quot;&gt;https://youtu.be/LXcBbkSdNxQ&lt;/a&gt;) 을 듣고 정리한 내용입니다.&lt;/p&gt;</description>
      <category>금융/회계</category>
      <author>하차모</author>
      <guid isPermaLink="true">https://hachamo.tistory.com/70</guid>
      <comments>https://hachamo.tistory.com/70#entry70comment</comments>
      <pubDate>Mon, 27 Nov 2023 22:10:15 +0900</pubDate>
    </item>
    <item>
      <title>4강 재무상태표 계정</title>
      <link>https://hachamo.tistory.com/69</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;계정(account, A/C)이란?&lt;/h3&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;재무상태표 계정 : 자산 계정, 부채 계정, 자본 계정&lt;/li&gt;
&lt;li&gt;손익계산서 계정 : 수익 계정, 비용 계정&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 이익은 수익에서 비용을 차감하여 산출, 별도로 관리하는 계정이 아님&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;계정과목이란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 계정에 구체적인 이름을 붙인 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex)&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;자산 계정
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;AAA 계정&lt;/li&gt;
&lt;li&gt;BBB 계정&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자산 계정에서 관리하는 계정과목&lt;/h3&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;재산&lt;/li&gt;
&lt;li&gt;채권(받을 권리)&lt;/li&gt;
&lt;li&gt;기타&lt;/li&gt;
&lt;/ul&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;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현금 : 통화, 통화대용증권(ex. 수표), 요구불예금(ex. 보통예금, 당좌예금)&lt;/li&gt;
&lt;li&gt;현금성자산 : 현금 전환이 용이한 금융상품&lt;/li&gt;
&lt;li&gt;&amp;rarr; 현금 및 현금성자산&lt;/li&gt;
&lt;li&gt;토지 : 공장부지, 산지, 농지, 상가부수토지 등&lt;/li&gt;
&lt;li&gt;건물 : 상가, 주택, 공장, 창고, 오피스빌딩 등&lt;/li&gt;
&lt;li&gt;기계장치&lt;/li&gt;
&lt;li&gt;비품 : 사무용 책상, 의자, 전화기, 복사기 등&lt;/li&gt;
&lt;li&gt;소모품&lt;/li&gt;
&lt;li&gt;차량운반구&lt;/li&gt;
&lt;li&gt;상품, 제품 &amp;rarr; 재고자산&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;사업장에 비치하고 사용하는 자산&amp;gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비품 : 1년 이상 장기간 사용, 상대적으로 금액이 큼&lt;/li&gt;
&lt;li&gt;(ex. 사무용 책상, 의자, 복사기, 전화기, 컴퓨터, 프린터)&lt;/li&gt;
&lt;li&gt;소모품 : 1년 이내 단기 사용, 금액이 작음&lt;/li&gt;
&lt;li&gt;(ex. 토너, 필기구 등 각종 사무용품, 화장지 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;판매 목적으로 보유하고 있는 자산&amp;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;/li&gt;
&lt;li&gt;상품 : 타 회사로부터 매입하여 판매 (상기업)&lt;/li&gt;
&lt;li&gt;&amp;rarr; 둘 다 재고자산&lt;/li&gt;
&lt;/ul&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;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주된 영업활동 : 상품, 제품, 서비스의 판매 &amp;rarr; 매출채권&lt;/li&gt;
&lt;li&gt;그 밖의 활동
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;금전을 빌려줌 &amp;rarr; 대여금&lt;/li&gt;
&lt;li&gt;기타(ex. 건물 매각) &amp;rarr; 미수금&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;상품, 서비스 등 매입 전 금전을 선지급(예약, 선지급) &amp;rarr; 선급금&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 의류 도매업체 A는 소매상 B에게 의류를 판매하고, 판매대금 1,000,000원은 1달 후에 받기로 하였음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 매출채권&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 의류 도매업체 A는 소유하고 있던 창고를 C에게 매각하고, 매각대금 1억원은 3달 후에 받기로 하였음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 미수금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 의류 도매업체 A는 다른 업체 D에게 여유자금 1,000만원을 빌려주고, 6달 후에 원금을 회수하기로 하였음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 대여금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 의류 도매업체 A는 상품을 선주문하고 300,000원을 지급하였음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 선급금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;유동자산과 비유동자산에 속하는 계정과목&amp;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;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;li&gt;미수금&lt;/li&gt;
&lt;li&gt;대여금&lt;/li&gt;
&lt;li&gt;선급금&lt;/li&gt;
&lt;li&gt;소모품&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&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;li&gt;장기선급금&lt;/li&gt;
&lt;li&gt;비품&lt;/li&gt;
&lt;li&gt;토지, 건물, 기계장치&lt;/li&gt;
&lt;li&gt;차량운반구&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;부채 계정에서 관리하는 계정과목&lt;/h3&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;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주된 영업활동 : 상품, 원재료, 서비스의 매입 &amp;rarr; 매입채무&lt;/li&gt;
&lt;li&gt;그 밖의 활동
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;금전을 빌림 (ex. 은행 대출) &amp;rarr; 차입금&lt;/li&gt;
&lt;li&gt;기타 (ex. 건물 매입) &amp;rarr; 미지급금&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;상품, 서비스 등 판매 전 금전을 선수령 (상품, 서비스 등 제공할 의무) &amp;rarr; 선수금&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 의류 소매상 B는 도매업체 A로부터 의류를 매입하고, 매입대금 1,000,000원은 1달 후에 지급하기로 하였음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 매입채무&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 의류 도매업체 A는 창고를 C로부터 매입하고, 매입대금 1억원은 3달 후에 지급하기로 하였음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 미지급금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 의류 도매업체 A는 은행으로부터 1,000만원을 빌리고, 6달 후에 원금을 지급하기로 약정하였음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 차입금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 의류 도매업체 A는 소매업체 B로부터 상품 선주문을 받고 200,000원을 수령하였음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 선수금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;유동부채와 비유동부채에 속하는 계정과목&amp;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;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;li&gt;선수금&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&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;li&gt;장기선수금&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자본 계정에서 관리하는 계정과목&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;종자 돈 &amp;rarr; 자본금 (주식회사의 자본금 = 액면금액 * 발행주식 수)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;번 돈 &amp;rarr; 이익잉여금&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기타 자본 계정에 속하는 계정 &amp;rarr; 자본잉여금, 자본조정, 기타포괄손익누계액&amp;hellip;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) (주)서울은 20X1.1.1 설립시 액면금액이 주당 1,000원인 주식 5,000주를 발행하였음(액면발행) (주식회사는 주식을 발행해서 종자돈을 마련함)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 자본금 = 1,000원 * 5,000주 = 5,000,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 20X1.1.1 설립시 액면 주당 1,000원인 주식 5,000주를 주당 1,000원에 발행함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 자본금 = 1,000원 * 5,000주 = 5,000,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rArr; 자본금 5,000,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1년 1년 동안 의류사업으로 수익 2,500,000원, 비용 1,500,000원이 발생함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 이익 = 2,500,000원 - 1,500,000원 = 1,000,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rArr; 자본금 5,000,000원 + 이익잉여금 1,000,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X1년 1년 동안 의류사업으로 수익 3,000,000원, 비용 1,000,000원이 발생함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 이익 = 3,000,000원 - 1,000,000원 = 2,000,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rArr; 자본금 5,000,000원 + 이익잉여금 3,000,000원&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;계정과목 총합&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷(84).png&quot; data-origin-width=&quot;1069&quot; data-origin-height=&quot;694&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lP7Qe/btsAIFGq4hk/HCJJKoh0g1o5sACAqSKXOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lP7Qe/btsAIFGq4hk/HCJJKoh0g1o5sACAqSKXOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lP7Qe/btsAIFGq4hk/HCJJKoh0g1o5sACAqSKXOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlP7Qe%2FbtsAIFGq4hk%2FHCJJKoh0g1o5sACAqSKXOk%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;1069&quot; height=&quot;694&quot; data-filename=&quot;스크린샷(84).png&quot; data-origin-width=&quot;1069&quot; data-origin-height=&quot;694&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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;권상호 회계입문강의 4강 (&lt;a href=&quot;https://youtu.be/_uT-o9OuGJo&quot;&gt;https://youtu.be/_uT-o9OuGJo&lt;/a&gt;) 을 듣고 정리한 내용입니다.&lt;/p&gt;</description>
      <category>금융/회계</category>
      <author>하차모</author>
      <guid isPermaLink="true">https://hachamo.tistory.com/69</guid>
      <comments>https://hachamo.tistory.com/69#entry69comment</comments>
      <pubDate>Wed, 22 Nov 2023 00:16:00 +0900</pubDate>
    </item>
    <item>
      <title>3강 수익, 비용, 이익</title>
      <link>https://hachamo.tistory.com/68</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;수익(revenue)이란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 일정 기간 경제적 효익의 유입&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일정기간? 1년, 6개월(반기), 3개월(분기), 회계기간*&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;회계기간 : 회계적 거래를 종합, 결과를 집계하는 기간&lt;/li&gt;
&lt;li&gt;&amp;rarr; 전전기, 전기, 당기, 차기, 차차기&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;수익과 자산의 관계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일정 기간 수익이 발생하면&amp;hellip;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경제적 효익(현금) 유입 &amp;rarr; 회사의 자본(이익잉여금) 증가 &amp;rarr; 회사의 자산 증가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 20X1.9.30 현재 회사의 자산 = 100만원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10월 한 달간 수익 = 20만원 (비용은 0으로 가정)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 20X1.10.31 현재 회사의 자산 = 120만원&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;수익의 분류&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;영업수익 : 주된 영업활동의 수익(=매출) &amp;rarr; 계속적, 반복적으로 발생&lt;/li&gt;
&lt;li&gt;영업외수익 : 주된 영업활동 외의 수익 &amp;rarr; 영업수익(매출) 외의 모든 수익&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;영업수익과 영업외수익의 구분&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 미용실 운영의 경우&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;li&gt;&amp;rarr; 주된 영업활동으로부터의 수익 (=영업수익, 매출)&lt;/li&gt;
&lt;li&gt;여유 자금으로 주식 투자, 수익&lt;/li&gt;
&lt;li&gt;&amp;rarr; 주된 영업활동 외의 수익 (= 영업외수익)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 식료품 제조업의 경우&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;li&gt;&amp;rarr; 주된 영업활동으로부터의 수익 (=영업수익, 매출)&lt;/li&gt;
&lt;li&gt;건물 일부를 임대하고, 임대료 수령&lt;/li&gt;
&lt;li&gt;&amp;rarr; 주된 영업활동 외의 수익 (= 영업외수익)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 수익을 장부에 기록하는가?&lt;/h3&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;현금주의 : 현금이 유입될 때&lt;/li&gt;
&lt;li&gt;발생주의 : 수익이 발생했다고 인정될 때 (현금과 무관) &amp;rarr; 현행 회계의 기본 원리&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 20X1. 11. 1 상품 10,000원을 외상 판매&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X2. 1. 31 외상대금 10,000원 현금 회수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 판매한 날(20X1. 11. 1) 장부에 기록&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;비용(expense)이란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 일정기간 경제적 효익의 유출&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일정기간? 1년, 6개월(반기), 3개월(분기), 회계기간&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경제적 효익? 가장 대표적인 것은 현금 유출&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;비용과 자산의 관계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일정 기간 비용이 발생하면&amp;hellip;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경제적 효익(현금) 유출 &amp;rarr; 회사의 자본(이익잉여금) 감소 &amp;rarr; 회사의 자산 감소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 20X1.9.30 현재 회사의 자산 = 100만원 (&amp;rarr; 시점)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10월 한 달간 비용 = 10만원 (수익은 0으로 가정) (&amp;rarr; 기간)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 20X1.10.31 현재 회사의 자산 = 90만원&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;비용의 분류&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;영업비용 : 주된 영업활동의 비용 &amp;rarr; 계속적, 반복적으로 발생&lt;/li&gt;
&lt;li&gt;영업외비용 : 주된 영업활동 외의 비용 &amp;rarr; 영업비용 외의 모든 비용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 미용실 운영의 경우&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;li&gt;&amp;rarr; 주된 영업활동에서 발생 (=영업비용)&lt;/li&gt;
&lt;li&gt;은행 대출 이자 비용&lt;/li&gt;
&lt;li&gt;&amp;rarr; 주된 영업활동 외의 비용 (영업외비용)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 비용을 장부에 기록하는가?&lt;/h3&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;현금주의 : 현금이 유출될 때&lt;/li&gt;
&lt;li&gt;발생주의 : 비용이 발생했다고 인정될 때 (현금과 무관) &amp;rarr; 현행 회계의 기본 원리&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 20X1.11.25 종업원 급여 1,000,000원 미지급&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20X2.1.31 급여 1,000,000원 현금 지급&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 급여를 지급하기로 한 날(20X1.11.25) 장부에 기록&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이익(profit)이란?&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이익 = 수익 - 비용 = 순수익(경영성과)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이익의 분류&lt;/h3&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-filename=&quot;스크린샷(81).png&quot; data-origin-width=&quot;1206&quot; data-origin-height=&quot;697&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dXgNF6/btsAzR8yceu/urvr1L9axhutiBzm7AosU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dXgNF6/btsAzR8yceu/urvr1L9axhutiBzm7AosU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dXgNF6/btsAzR8yceu/urvr1L9axhutiBzm7AosU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdXgNF6%2FbtsAzR8yceu%2Furvr1L9axhutiBzm7AosU1%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;1206&quot; height=&quot;697&quot; data-filename=&quot;스크린샷(81).png&quot; data-origin-width=&quot;1206&quot; data-origin-height=&quot;697&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;손익계산서(Income Statement, I/S)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 일정기간 수익과 비용을 집계한 표&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일정기간? 1년, 6개월(반기), 3개월(분기)&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷(82).png&quot; data-origin-width=&quot;912&quot; data-origin-height=&quot;623&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/daEGgy/btsAANefxp2/PgHHZjKk0OpKGHIhhJ1Ut1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/daEGgy/btsAANefxp2/PgHHZjKk0OpKGHIhhJ1Ut1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/daEGgy/btsAANefxp2/PgHHZjKk0OpKGHIhhJ1Ut1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdaEGgy%2FbtsAANefxp2%2FPgHHZjKk0OpKGHIhhJ1Ut1%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;912&quot; height=&quot;623&quot; data-filename=&quot;스크린샷(82).png&quot; data-origin-width=&quot;912&quot; data-origin-height=&quot;623&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이익과 이익잉여금의 관계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.ex)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현금 50,000원으로 친구들과 고스톱 시작&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 자본금 50,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째 게임에서 5,000원을 땄음 (&amp;rarr; 이익 5,000원)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 자본금 50,000원 + 이익잉여금 5,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 게임에서 10,000원을 땄음 (&amp;rarr; 이익 10,000원)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 자본금 50,000원 + 이익잉여금 15,000원&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자산, 부채, 자본과 수익, 비용, 이익의 관계&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷(83).png&quot; data-origin-width=&quot;1256&quot; data-origin-height=&quot;846&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bk7nFu/btsAFF0z6kY/DS20epDG8KdFa7IBnrMki0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bk7nFu/btsAFF0z6kY/DS20epDG8KdFa7IBnrMki0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bk7nFu/btsAFF0z6kY/DS20epDG8KdFa7IBnrMki0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbk7nFu%2FbtsAFF0z6kY%2FDS20epDG8KdFa7IBnrMki0%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;1256&quot; height=&quot;846&quot; data-filename=&quot;스크린샷(83).png&quot; data-origin-width=&quot;1256&quot; data-origin-height=&quot;846&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;rarr; 주식회사의 경우 이익잉여금이 있어야 배당금을 줄 수 있음&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;권상호 회계입문강의 3강 (&lt;a href=&quot;https://youtu.be/vtZsNkga6bs&quot;&gt;https://youtu.be/vtZsNkga6bs&lt;/a&gt;) 을 듣고 정리한 내용입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>금융/회계</category>
      <author>하차모</author>
      <guid isPermaLink="true">https://hachamo.tistory.com/68</guid>
      <comments>https://hachamo.tistory.com/68#entry68comment</comments>
      <pubDate>Mon, 20 Nov 2023 23:56:26 +0900</pubDate>
    </item>
    <item>
      <title>2강 자산, 부채, 자본</title>
      <link>https://hachamo.tistory.com/67</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;자산(asset)이란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 미래 경제적 효익을 주는 것&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;경제적 효익? : 가장 대표적인 경제적 효익은 현금 유입&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자산(asset)의 종류&lt;/h3&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;li&gt;채권 : 일정한 금전을 받을 권리 (매출채권, 미수금, 대여금 등)&lt;/li&gt;
&lt;li&gt;기타&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자산의 분류&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유동자산 : 1년 이내(단기), 가까운 미래에 나에게 경제적 효익을 줄 수 있는 자산&lt;/li&gt;
&lt;li&gt;비유동자산 : 1년 이후(장기), 먼 미래에&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 미수금(아직 받지 못한 돈, 받을 권리가 있는 돈) 100,000원&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;YES &amp;rarr; 유동자산&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NO &amp;rarr; 비유동자산 (장기미수금)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;부채(liability)란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 미래 경제적 희생이 되는 것&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;경제적 희생? : 가장 대표적인 경제적 희생은 현금 유출&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;부채의 종류&lt;/h3&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;li&gt;기타&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;부채의 분류&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유동부채 : 1년 이내(단기)&lt;/li&gt;
&lt;li&gt;비유동부채 : 1년 이후(장기)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 미지급금(아직 지급하지 않은 돈, 줄 의무가 있는 돈) 100,000원&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;YES &amp;rarr; 유동부채&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NO &amp;rarr; 비유동부채 (장기미지급금)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자본(capital)이란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자본 = 자산 - 부채 = 순자산&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자본의 종류&lt;/h3&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;li&gt;이익잉여금 : 사업 개시 후 번 돈을 모아 놓은 것&lt;/li&gt;
&lt;li&gt;기타&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현금 50,000원으로 친구들과 고스톱 시작&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 자본금 50,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째 게임에서 5,000원을 땄음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 자본금 50,000원 + 이익잉여금 5,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 게임에서 10,000원을 땄음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 자본금 50,000원 + 이익잉여금 15,000원&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자산, 부채, 자본의 관계&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자산 = 자본 + 부채&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 자본 : 100,000원, 부채 : 200,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자산? 300,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시(1) : 내 돈 50,000원과 친구로부터 빌린 돈 30,000원으로 80,000원의 만년필을 구입함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 자산(만년필) 80,000원 = 부채 30,000원 + 자본 50,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나의 자산(만년필) 80,000원의 자본 원천은 부채 30,000원과 내 돈(자본) 50,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시(2) : 내 소유의 구형 자동차를 팔아서 마련한 1,000만원과 할부 1,000만원 조건으로 2,000만원의 신형 자동차를 매입하였음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 자산(신형 자동차) 2,000만원 = 부채 1,000만원 + 자본 1,000만원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나의 자산(자동차) 2,000만원의 자본 원천은 부채 1,000만원과 내 돈(자본) 1,000만원&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자산, 부채, 자본의 관계 정리&lt;/h3&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;rarr; 자본 증가 &amp;rarr; 자산 증가&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;재무상태표(Balance Sheet, B/S)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: a statement of financial position&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-filename=&quot;스크린샷(79).png&quot; data-origin-width=&quot;1162&quot; data-origin-height=&quot;740&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wBKe0/btsAjPa6el8/Rkc6h6iHgFnyVvcCTXJ8YK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wBKe0/btsAjPa6el8/Rkc6h6iHgFnyVvcCTXJ8YK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wBKe0/btsAjPa6el8/Rkc6h6iHgFnyVvcCTXJ8YK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwBKe0%2FbtsAjPa6el8%2FRkc6h6iHgFnyVvcCTXJ8YK%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;1162&quot; height=&quot;740&quot; data-filename=&quot;스크린샷(79).png&quot; data-origin-width=&quot;1162&quot; data-origin-height=&quot;740&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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;권상호 회계입문강의 2강 (&lt;a href=&quot;https://youtu.be/4JsdxfMN3P4&quot;&gt;https://youtu.be/4JsdxfMN3P4&lt;/a&gt;) 을 듣고 정리한 내용입니다.&lt;/p&gt;</description>
      <category>금융/회계</category>
      <author>하차모</author>
      <guid isPermaLink="true">https://hachamo.tistory.com/67</guid>
      <comments>https://hachamo.tistory.com/67#entry67comment</comments>
      <pubDate>Mon, 13 Nov 2023 23:42:20 +0900</pubDate>
    </item>
    <item>
      <title>1강 회계의 개념</title>
      <link>https://hachamo.tistory.com/66</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;기업의 경영활동&lt;/h3&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;영업활동 : 1. 매입한 자산 사용 2. 재료, 상품 매입 3. 종업원 고용, 임금 4. 기타 제조, 판매 및 관리를 위한 활동&lt;/li&gt;
&lt;li&gt;투자활동 : 영업에 사용할 건물, 기계, 비품 등 매입(매각), 재산 증식 목적의 투자&lt;/li&gt;
&lt;li&gt;재무활동 : 사업자금조달(상환)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 경영활동의 예&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나의 현금 70,000원, 은행 대출 30,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 100,000원 출자하여 커피전문점 설립, 개업&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 사업자금 조달(상환) &amp;rarr; 재무활동&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;건물 50,000원 매입&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커피 기계, 테이블, 의자 등 비품 매입 20,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 영업에 사용할 건물, 기계, 비품 등 매입 (매각) &amp;rarr; 투자활동&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커피 재료 매입 20,000원, 종업원 급여 10,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커피 판매 50,000원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 매입한 건물 등 사용, 제품 판매 준비, 판매 및 관리 활동 등 &amp;rarr; 영업활동&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기업의 경영활동과 거래&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;회사가 경영활동을 수행하면 반드시 거래가 발생&amp;rdquo;&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;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;/ol&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;일반적 거래 + 3. 금액으로 표시 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순한 주문 행위는 회계적 거래 X&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;회계(會計, accounting)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음의 전 과정을 회계라고 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경영활동 &amp;rarr; 회계적 거래 &amp;rarr; 장부 기입(부기) (장부기입 방법 : 분개) &amp;rarr; 수정, 결산 &amp;rarr; 결산보고서 (회계정보, 재무제표) &amp;rarr; 결산보고서 이용&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;누가 회계정보를 이용하는가?&lt;/h3&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;/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;예비 주주 : A사 주식에 투자할까? 말까?&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;[회사 내부]&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;h3 data-ke-size=&quot;size23&quot;&gt;회계의 목적은 무엇인가?&lt;/h3&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;h3 data-ke-size=&quot;size23&quot;&gt;회계의 분류&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회계의 분류 : 회계정보 이용자에 따른 분류&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주주, 채권자 &amp;rarr; 재무회계 &amp;rarr; 회계기준이 아주 중요함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경영자 &amp;rarr; 관리회계 &amp;rarr; 특별한 기준 없음&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;우리나라의 회계기준&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상장기업&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국채택국제회계기준(K-IFRS)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비상장기업&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반기업회계기준 (직전년도 기준 자산규모 120억 이상)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중소기업회계기준 (직전년도 기준 자산규모 70억원 미만)&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;한국거래소에서 운영하고 있는 대표적인 증권시장 :&amp;nbsp;유가증권시장,&amp;nbsp;코스닥시장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일정한 요건을 갖춘 증권만이 이 시장에서 거래될 수 있음 &amp;rarr; 상장증권&lt;/p&gt;
&lt;p data-ke-size=&quot;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;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;권상호 회계입문강의 1강 (&lt;a href=&quot;https://www.youtube.com/watch?v=VZaAhSSlfdc&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=VZaAhSSlfdc&lt;/a&gt;)을 듣고 정리한 내용입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>금융/회계</category>
      <author>하차모</author>
      <guid isPermaLink="true">https://hachamo.tistory.com/66</guid>
      <comments>https://hachamo.tistory.com/66#entry66comment</comments>
      <pubDate>Mon, 23 Oct 2023 22:26:14 +0900</pubDate>
    </item>
    <item>
      <title>19. 공지사항 게시판 (임시저장 기능)</title>
      <link>https://hachamo.tistory.com/61</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;게시글 임시저장&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게시판 테이블에는 글 상태값을 나타내는 boardStatus 컬럼이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1은 정상 등록, 2는 임시 저장, 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;처음에 임시저장 기능은 boardStatus 값만 다르게 해서 글 등록 기능 활용하면 그렇게 어렵지 않겠다고 생각했는데&amp;hellip;&amp;hellip;. 생각보다 할 게 너무 많다. 하다 보니까 글 등록, 임시저장, 수정, 삭제 쿼리를 다 갈아 엎고 있었음.. 사실 간단하게 하라면 그렇게 할 수도 있지만 진짜 서비스처럼 구현하고 싶어서..! (그러기엔 부족한 점이 많지만 ;;)&lt;/p&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 data-ke-size=&quot;size16&quot;&gt;그때 새로운 글이 insert 되지 않고 기존 임시저장글이 update 되었으면 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 네이버 블로그나 티스토리에서 임시저장을 하면 버튼을 누를 때마다 새로운 임시저장글이 생기는 게 아니고 이전에 임시저장한 글이 업데이트된다. (실제로 어떻게 구현했는지는 모르지만..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;임시저장 버튼을 누를 때마다 새로운 임시저장 글이 계속 Insert되면 구현하기에는 쉽겠지만 데이터 저장 문제도 있고, 사용자 입장에서도 불편할 것이라고 생각했다.&lt;/p&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;글을 처음 임시저장 버튼을 누르면 임시저장한 글의 boardNum을 value값으로 가지고 있는 hidden 속성의 input 태그를 html에 추가했다.(&amp;lt;input type=&quot;hidden&quot; name=&quot;boardNum&quot; value=&quot;~글 번호~&quot;&amp;gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;임시저장 버튼을 눌러 컨트롤러로 넘어갔을 때, 같은 메소드로 넘어가지만 boardNum값이 없으면 처음 임시저장, boardNum값이 있으면 해당 임시저장 글 update가 되도록 구현했다.&lt;/p&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-filename=&quot;스크린샷(51).png&quot; data-origin-width=&quot;1290&quot; data-origin-height=&quot;687&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccj0aH/btsjButTTWb/XKdPXZQR4qtpLxb4pmkJ11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccj0aH/btsjButTTWb/XKdPXZQR4qtpLxb4pmkJ11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccj0aH/btsjButTTWb/XKdPXZQR4qtpLxb4pmkJ11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fccj0aH%2FbtsjButTTWb%2FXKdPXZQR4qtpLxb4pmkJ11%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;1290&quot; height=&quot;687&quot; data-filename=&quot;스크린샷(51).png&quot; data-origin-width=&quot;1290&quot; data-origin-height=&quot;687&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;NoticeController.java&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;//글쓰기 페이지 이동
@GetMapping(&quot;/regNotice&quot;)
public String regForm(Model model) {
	model.addAttribute(&quot;boardMenuCode&quot;, &quot;BOARD_MENU_001&quot;);
	
	// 로그인 처리후 수정해야됨~~~~~~~~~~~~~~~~~~~~!!!!!!!!!!!!!!
	model.addAttribute(&quot;tempBoardCnt&quot;, noticeService.getTempBoardCntByEmpno(20230517));
	
	return &quot;content/notice/notice_form&quot;;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게시판 목록에서 글쓰기 버튼을 누르고 글 등록 폼 페이지로 올 때, 지금 로그인하고 있는 유저의 사번(pk)로 그 유저가 임시저장한 글의 개수를 가져온다.&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;notice_form.html&lt;/p&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;&amp;lt;div class=&quot;row px-2&quot;&amp;gt;
	&amp;lt;div class=&quot;col d-grid gap-2 d-md-flex justify-content-md-end&quot; id=&quot;btnDiv&quot;&amp;gt;
		&amp;lt;div id=&quot;alertDiv&quot;&amp;gt;&amp;lt;/div&amp;gt;
		&amp;lt;div class=&quot;btn-group&quot; role=&quot;group&quot;&amp;gt;
		  &amp;lt;button type=&quot;button&quot; class=&quot;btn myBtn&quot; onclick=&quot;tempRegNotice();&quot;&amp;gt;임시저장&amp;lt;/button&amp;gt;
		  &amp;lt;input type=&quot;button&quot; class=&quot;btn myBtn numberBtn&quot; th:onclick=&quot;tempBoardList()&quot;
		  			data-bs-toggle=&quot;modal&quot; data-bs-target=&quot;#tempRegModal&quot; id=&quot;tempModalBtn&quot; th:value=&quot;${tempBoardCnt}&quot;&amp;gt;
		&amp;lt;/div&amp;gt;
		&amp;lt;button class=&quot;btn&quot; type=&quot;button&quot; onclick=&quot;regNotice();&quot;&amp;gt;등록&amp;lt;/button&amp;gt;
	&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;

&amp;lt;div class=&quot;row&quot;&amp;gt;
	&amp;lt;div class=&quot;col&quot; id=&quot;hiddenDiv&quot;&amp;gt;&amp;lt;/div&amp;gt;
	&amp;lt;input type=&quot;hidden&quot; name=&quot;boardMenuVO.boardMenuCode&quot; th:value=&quot;${boardMenuCode}&quot;&amp;gt;
&amp;lt;/div&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;notice_form.js&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;//정상 글 등록
function regNotice() {
	if(!noticeFormCheck()) {
		return false;
	}
	else {
		//상태값 설정
		const hiddenDiv = document.querySelector('#hiddenDiv');
		
		const statusStr = `&amp;lt;input type=&quot;hidden&quot; name=&quot;boardStatus&quot; value=&quot;${1}&quot;&amp;gt;`;
		hiddenDiv.insertAdjacentHTML('beforeend', statusStr);
		
		document.querySelector('#noticeForm').submit();
	}
}

//임시 저장 글 등록
function tempRegNotice() {
	if(!noticeFormCheck()) {
		return false;
	}
	else {
		//상태값 설정
		const hiddenDiv = document.querySelector('#hiddenDiv');
		
		const hasHidden = hiddenDiv.hasChildNodes();
		
		//hiddenDiv에 자식 노드가 없으면(첫 임시저장일 때)
		if(!hasHidden) {
			const statusStr = `&amp;lt;input type=&quot;hidden&quot; name=&quot;boardStatus&quot; value=&quot;${2}&quot;&amp;gt;`;
			hiddenDiv.insertAdjacentHTML('afterbegin', statusStr);
			
			//임시저장함 개수 증가
			const tempModalBtn = document.querySelector('#tempModalBtn');
			tempModalBtn.value = Number(tempModalBtn.value)+ 1;
		}
		
		
		//폼 태그
		const formData = new FormData(document.querySelector('#noticeForm'));
		
		//ajax start
		$.ajax({
			url: '/notice/tempRegNotice', //요청경로
			type: 'post',
			async: true,
			data: formData,
		    processData: false,
		    contentType: false,
			success: function(result) {
				const tempBoard = result;
				
				
				//알림 메시지 추가
				const alertDiv = document.querySelector('#alertDiv');
				alertDiv.replaceChildren();
				
				const tempAlertStr = '&amp;lt;div class=&quot;alert alert-danger mb-0 py-1 fs-6&quot; role=&quot;alert&quot; id=&quot;tempAlert&quot;&amp;gt;임시저장이 완료되었습니다.&amp;lt;/div&amp;gt;';
				alertDiv.insertAdjacentHTML('afterbegin', tempAlertStr);
				
				$(&quot;#tempAlert&quot;).delay(4000).fadeOut(1000);
				
				
				//글 번호 추가
				if(!hasHidden) {
					const boardNumStr = `&amp;lt;input type=&quot;hidden&quot; name=&quot;boardNum&quot; value=&quot;${tempBoard.boardNum}&quot;&amp;gt;`;
					hiddenDiv.insertAdjacentHTML('afterbegin', boardNumStr);
				}
				
				//첨부파일 번호 + onchange 추가 + name값 삭제
				const fileInputs = document.querySelectorAll('#fileInput');
				
				fileInputs.forEach(function(fileInput, index){
					//이미 임시 저장된 파일은 controller로 넘어가지 않도록 name 속성 없애준다.
					//다시 임시 저장했을 때 불러오지 않도록 id 속성도 삭제해줌
					fileInput.removeAttribute('name');
					fileInput.removeAttribute('id');
					
					//data-file-num 속성 추가 (html에서는 fileNum으로 자동 인식)
					fileInput.dataset.fileNum = tempBoard.boardFileList[index].fileNum;
					
					//파일 태그 삭제 버튼 onclick에 deleteFileNum 추가
					const deleteBtn = fileInput.nextElementSibling;
					deleteBtn.setAttribute('onClick', `tempDeleteFileInputDiv(this, &quot;${fileInput.dataset.fileNum}&quot;)`);
					
					//사용자가 기존 파일 태그에서 파일 변경할 시
					fileInput.addEventListener('change',function() {
						//다시 name, id 속성 추가
						fileInput.name = 'files';
						fileInput.id = 'fileInput'
						
						//기존 임시저장 파일 삭제 위해서 deleteFileNum 추가
						const hiddenDiv = document.querySelector('#hiddenDiv');
					
						const deleteFileNumStr = `&amp;lt;input type=&quot;hidden&quot; name=&quot;deleteFileNum&quot; value=&quot;${tempBoard.boardFileList[index].fileNum}&quot;&amp;gt;`;
						hiddenDiv.insertAdjacentHTML('beforeend', deleteFileNumStr);
						
						//data-file-num 속성 삭제
						fileInput.removeAttribute('data-file-num');
						
						//파일 태그 삭제 버튼 onclick에 deleteFileNum 추가
						deleteBtn.setAttribute('onClick', `deleteFileInputDiv(this)`);
					}, { once: true });
				});
				
				if(hasHidden)  { //그 글에서 계속 임시저장했을 때 삭제한 파일 fileNum은 지우기
					const deleteFileNums = hiddenDiv.querySelectorAll('input[name=&quot;deleteFileNum&quot;]');
					if(deleteFileNums.length != 0) {
						for(const deleteFileNum of deleteFileNums) {
							deleteFileNum.remove();
						}
					}
				}
				
			},
			error: function() {
				alert('실패');
			}
		});
		//ajax end
	}
}

//임시저장 파일 태그 삭제
function tempDeleteFileInputDiv(deleteBtn, fileNum) {
	const hiddenDiv = document.querySelector('#hiddenDiv');
					
	const deleteFileNumStr = `&amp;lt;input type=&quot;hidden&quot; name=&quot;deleteFileNum&quot; value=&quot;${fileNum}&quot;&amp;gt;`;
	hiddenDiv.insertAdjacentHTML('beforeend', deleteFileNumStr);
	
	const fileInputDiv = deleteBtn.parentElement;
	fileInputDiv.remove();
};&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;p data-ke-size=&quot;size16&quot;&gt;1.&amp;nbsp;정상 글 등록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 일반 글 등록이다. 기능이 변한 것은 없고, 유효성 검사를 통과하면 boardStatus 1 값을 가진 input hidden 태그를 hiddenDiv에 삽입한 뒤에 form 태그를 submit 시켜 준다.&lt;/p&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;자바스크립트 코드가 이렇게 길어진 것은 첨부파일 처리가 좀 까다로워서&amp;hellip;.&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;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;처음 임시저장 했을 때
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;boardStatus 2 값을 가진 input hidden 태그를 hiddenDiv에 삽입&lt;/li&gt;
&lt;li&gt;임시저장함 버튼의 임시저장 글 개수 증가&lt;/li&gt;
&lt;li&gt;AJAX로 폼 태그 데이터 전송(FormData 객체로 전송) - processData, contentType : false 로 해야 파일 정보까지 넘길 수 있다. &amp;rarr; 통신 성공 시 컨트롤러에서 저장한 글 정보 담고있는 boardVO 반환&lt;/li&gt;
&lt;li&gt;알림 메시지 띄우기 - jQuery로 4초 딜레이시켰다가, 1초 점점 사라지도록 함.&lt;/li&gt;
&lt;li&gt;받아온 글의 boardNum 값을 가진 input hidden 태그 hiddenDiv에 insert&lt;/li&gt;
&lt;li&gt;임시저장한 첨부파일 처리(하단에 추가 설명)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;임시저장 후 추가 작성 및 수정하고 다시 임시저장 버튼 눌렀을 때
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;boardStatus 추가 X&lt;/li&gt;
&lt;li&gt;AJAX로 FormData 전송&lt;/li&gt;
&lt;li&gt;처음 임시저장했을 때 추가했던 boardNum값도 같이 가져 감&lt;/li&gt;
&lt;li&gt;컨트롤러에서 폼 데이터 받았을 때 boardNum이 없으면 처음 임시저장(Insert), 있으면 이후 임시저장(Update)으로 판단&lt;/li&gt;
&lt;/ol&gt;
&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;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;처음 임시저장 시 파일을 첨부한 경우
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파일 유지&lt;/li&gt;
&lt;li&gt;파일 변경(input 태그 클릭해서 다른 파일 첨부)&lt;/li&gt;
&lt;li&gt;파일 삭제(삭제 버튼 클릭해서)&lt;/li&gt;
&lt;li&gt;새로 등록&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자는 이 네 가지의 경우 중 하나를 수행할 것이다. (새로 등록은 기존 첨부파일 추가와 같아서 따로 추가할 기능 없음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 자바스크립트 코드를 보자. (const fileInputs..~ 부터)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;&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;지금 가져온 이 파일들은 (변경하지 않는다면) 다시 임시저장을 눌렀을 때 컨트롤러로 넘어가지 않아야 한다. 따라서 name 속성을 삭제해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또, 이 파일들은 다시 임시저장을 눌렀을 때 이 이후의 작업을 수행하지 않도록 (자바스크립트에서 id값으로 가져오지 않도록) id 속성을 삭제해준다.&lt;/p&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;input 태그에 &amp;lsquo;fileNum&amp;rsquo; 이라는 이름의 데이터 속성을 추가한다. 데이터 속성은 HTML에서 &amp;lsquo;data-&amp;rsquo;로 시작하는데 특정한 데이터를 DOM 요소에 저장하기 위해 쓰인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(개발자가 특정 데이터를 저장하기 위해 임의로 만든 속성이라고 생각하면 됨)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트에서 fileNum으로 추가하면 html에서는 자동으로 &amp;lsquo;data-file-num&amp;rsquo;이라는 이름의 속성으로 들어간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;임시저장한 파일을 삭제했을 때, 그 파일의 fileNum을 deleteFileNum으로 가진 input hidden 태그를 추가해줘야 update할 때 삭제되기 때문에 해당 기능을 하는 onclick 함수를 추가해준다.&lt;/p&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;임시 저장했던 파일 태그 자체를 다시 클릭해서 다른 파일을 첨부하는 경우가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 경우를 위해 addEventListener로 파일이 바뀌었을 때('change') 함수를 추가해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨트롤러로 넘어가게 하기 위해서 name 값을 추가한다. 또, 1번과 2번이 수행되려면 id가 있어야 하기 때문에 그 값도 추가해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존의 임시저장 파일은 삭제되게 하기 위해서 기존 파일의 fileNum을 deleteFileNum값으로 가진 input hidden 태그를 추가해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가했던 fileNum 데이터 속성을 삭제한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 태그 삭제 버튼의 onclick 함수를 변경한다. (deleteFileInputDiv 함수는 단순히 file input 태그를 담고 있는 div를 삭제해주는 기능만 한다. deleteFileNum X)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이 함수는 파일을 변경할 때 딱 한 번만 실행되도록 addEventListener() 메소드의 세번째 파라미터로 {once: true}를 전달한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;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;마지막으로 삭제한 deleteFileNum 태그는 삭제해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;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;NoticeController.java&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;//글 임시 저장
@ResponseBody
@PostMapping(&quot;/tempRegNotice&quot;)
public BoardVO tempRegNotice(BoardVO boardVO, String[] deleteFileNum, MultipartFile[] files) {
	
	//가져온 정보에서 글 번호가 없을 때
	if (boardVO.getBoardNum() == null) { //새로운 임시 글 등록
		//글 등록 쿼리
		regBoard(boardVO, files);
	}
	else { //같은 임시글 저장
		boardVO.setBoardDate(&quot;SYSDATE&quot;);
		updateBoard(boardVO, deleteFileNum, files);
	}
	
	return boardVO; //매개변수로 객체(참조변수)를 전달하면 주소값을 보낸거니까 다시 받아오지 않아도 됨.
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;임시저장 버튼을 누르고 AJAX로 '/notice/tempRegNotice&amp;rsquo; 요청경로로 넘어오면 먼저 boardNum 값이 있는지 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;있으면 새로운 글 insert, 없으면 기존 임시저장글 update하고 완료한 글 정보가 담긴 boardVO를 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;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;NoticeController.java&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;//글 신규 등록
@PostMapping(&quot;/regNotice&quot;)
public String regNotice(BoardVO boardVO, String[] deleteFileNum, MultipartFile[] files) {

	if(boardVO.getBoardNum() == null) { //신규 등록
		regBoard(boardVO, files);
	}
	else { // 임시저장하고 등록
		//상태값 변경
		boardVO.setBoardStatus(1);
		boardVO.setBoardDate(&quot;SYSDATE&quot;);
		
		updateBoard(boardVO, deleteFileNum, files);			
	}
	
	return &quot;redirect:/notice/list&quot;;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넘어온 boardVO에 boardNum 값이 있으면 boardStatus를 1로 변경하고 update해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷(51).png&quot; data-origin-width=&quot;1290&quot; data-origin-height=&quot;687&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k3rQ3/btsjnbh1aFh/44Rwba2EvlD4ePudr7kyHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k3rQ3/btsjnbh1aFh/44Rwba2EvlD4ePudr7kyHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k3rQ3/btsjnbh1aFh/44Rwba2EvlD4ePudr7kyHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk3rQ3%2Fbtsjnbh1aFh%2F44Rwba2EvlD4ePudr7kyHK%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;1290&quot; height=&quot;687&quot; data-filename=&quot;스크린샷(51).png&quot; data-origin-width=&quot;1290&quot; data-origin-height=&quot;687&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷(52).png&quot; data-origin-width=&quot;457&quot; data-origin-height=&quot;209&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/egHbrn/btsjlX5Endf/jpqCkUKTicr2KCE58kARv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/egHbrn/btsjlX5Endf/jpqCkUKTicr2KCE58kARv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/egHbrn/btsjlX5Endf/jpqCkUKTicr2KCE58kARv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FegHbrn%2FbtsjlX5Endf%2FjpqCkUKTicr2KCE58kARv1%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;457&quot; height=&quot;209&quot; data-filename=&quot;스크린샷(52).png&quot; data-origin-width=&quot;457&quot; data-origin-height=&quot;209&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hiddenDiv에 boardNum이 추가된 것을 볼 수 있다.&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;스크린샷(53).png&quot; data-origin-width=&quot;1275&quot; data-origin-height=&quot;704&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDn2tF/btsjnbh1h0H/lfWlnmEKvkdGyuzQCW49E0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDn2tF/btsjnbh1h0H/lfWlnmEKvkdGyuzQCW49E0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDn2tF/btsjnbh1h0H/lfWlnmEKvkdGyuzQCW49E0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDn2tF%2Fbtsjnbh1h0H%2FlfWlnmEKvkdGyuzQCW49E0%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;1275&quot; height=&quot;704&quot; data-filename=&quot;스크린샷(53).png&quot; data-origin-width=&quot;1275&quot; data-origin-height=&quot;704&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷(54).png&quot; data-origin-width=&quot;438&quot; data-origin-height=&quot;135&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rc0ed/btsjkLYTegN/z9qVjAigxWfchX0xytuxqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rc0ed/btsjkLYTegN/z9qVjAigxWfchX0xytuxqk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rc0ed/btsjkLYTegN/z9qVjAigxWfchX0xytuxqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Frc0ed%2FbtsjkLYTegN%2Fz9qVjAigxWfchX0xytuxqk%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;438&quot; height=&quot;135&quot; data-filename=&quot;스크린샷(54).png&quot; data-origin-width=&quot;438&quot; data-origin-height=&quot;135&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;update 쿼리가 실행되는 것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프로젝트</category>
      <author>하차모</author>
      <guid isPermaLink="true">https://hachamo.tistory.com/61</guid>
      <comments>https://hachamo.tistory.com/61#entry61comment</comments>
      <pubDate>Sun, 11 Jun 2023 21:48:27 +0900</pubDate>
    </item>
    <item>
      <title>18. 공지사항 게시판 (페이징 처리)</title>
      <link>https://hachamo.tistory.com/60</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;페이징 처리&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yh8T8/btsh3B24DLU/AzVEsrG5rrmA7HAcXJj1q1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yh8T8/btsh3B24DLU/AzVEsrG5rrmA7HAcXJj1q1/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1312&quot; data-origin-height=&quot;847&quot; data-filename=&quot;스크린샷(48).png&quot; style=&quot;width: 48.8552%; margin-right: 10px;&quot; data-widthpercent=&quot;49.43&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yh8T8/btsh3B24DLU/AzVEsrG5rrmA7HAcXJj1q1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyh8T8%2Fbtsh3B24DLU%2FAzVEsrG5rrmA7HAcXJj1q1%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;1312&quot; height=&quot;847&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nrIot/btsh4ZCojO7/htRUD42DAxgZjHvnr5V4N0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nrIot/btsh4ZCojO7/htRUD42DAxgZjHvnr5V4N0/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1328&quot; data-origin-height=&quot;838&quot; data-filename=&quot;스크린샷(49).png&quot; style=&quot;width: 49.9821%;&quot; data-widthpercent=&quot;50.57&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nrIot/btsh4ZCojO7/htRUD42DAxgZjHvnr5V4N0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnrIot%2Fbtsh4ZCojO7%2FhtRUD42DAxgZjHvnr5V4N0%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;1328&quot; height=&quot;838&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게시글 목록 하단 중앙에 페이징 nav를 추가하고 목록 상단 좌측에 전체 데이터 건수를 추가했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;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;PageVO.java&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class PageVO {
	private int nowPage; // 현재 선택된 페이지 번호
	private int totalDataCnt; // 전체 데이터 수
	private int beginPage; // 화면에 보이는 첫번째 페이지 번호
	private int endPage; // 화면에 보이는 마지막 페이지 번호
	private int displayCnt; // 한 페이지에 보여지는 게시글 수
	private int displayPageCnt; // 한 번에 보여지는 페이지 수
	private boolean prev; // '이전' 버튼의 유무
	private boolean next; // '다음' 버튼의 유무
	private int offsetCnt; // 건너뛸 개수
	
	//기본 생성자 선언
	public PageVO() {
		this(5, 3); // 한 페이지에 보여줄 데이터 개수는 5,
			  // 한 번에 보여지는 페이지 수는 3
		nowPage = 1; // 생성과 동시에 현재 페이지는 1
	}
	
	//데이터 개수 &amp;amp; 페이지 수 지정 생성자
	public PageVO(int displayCnt, int displayPageCnt) {
		nowPage = 1;
		this.displayCnt = displayCnt; // 한 페이지에 보여줄 데이터 개수
		this.displayPageCnt = displayPageCnt; // 한 번에 보여지는 페이지 수
	}
	
		
	// 이 메서드가 실행되면 page 처리를 위한 모든 변수 값을 세팅
	public void setPageInfo() {
		// 마지막에 보이는 페이지 번호
		// 한 화면에 보여지는 페이지 수 * (정수)올림(현재 페이지 / (실수)한 화면에 보여지는 페이지 수)
		// 올림 : Math.ceil(실수); 반올림 : Math.round(실수); -&amp;gt; 실수 값 반환
		endPage = displayPageCnt * (int)Math.ceil(nowPage / (double)displayPageCnt);
		
		// 처음에 보이는 페이지 번호
		beginPage = endPage - displayPageCnt + 1;
		
		// 전체 페이지 수
		// (정수)올림(전체 데이터 수 / (실수)한 페이지에 보여지는 데이터 수) 
		int totalPageCnt = (int)Math.ceil(totalDataCnt / (double)displayCnt);
		
		// next 버튼 유무
		// 마지막 페이지 번호를 전체 페이지 수로 맞추기
		if (endPage &amp;lt; totalPageCnt) {
			next = true;
		}
		else {
			next = false;
			endPage = totalPageCnt;
		}
		
		// 데이터가 0개인 경우
		if(totalPageCnt == 0) {
			endPage = 1;
		}
		
		// prev 버튼 유무
		prev = beginPage == 1 ? false : true;
		
		//건너뛸 개수
		offsetCnt = (nowPage - 1) * displayCnt;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이징 처리에 필요한 모든 데이터가 담겨있는 PageVO를 생성한다. 객체 생성 시 현재 페이지, 한 번에 보여줄 데이터 개수를 5로, 한 번에 보여지는 페이지 수를 3으로 지정하는 생성자를 만든다. (공지사항 말고 다른 페이지에도 페이징 처리를 해야 했고, 그 페이지의 기본 세팅이 5, 3이었기 때문에 기본 생성자는 5, 3으로 해줬다.) 데이터 개수 &amp;amp; 페이지 수를 지정할 수 있는 생성자를 추가로 만들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;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;setPageInfo() 메소드가 실행되면 페이징 처리를 위한 모든 변수 값을 세팅하도록 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;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;BoardVO.java&lt;/p&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;public class BoardVO extends PageVO {
	public BoardVO() {
		super(10, 10);
	}

	...(생략)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BoardVO가 PageVO를 상속받도록 해주고, super()로 조상 클래스의 생성자를 호출한다. 매개변수로 int가 두 개 들어가는 생성자가 호출되며, 게시판에서 한 페이지에 보여지는 글 개수는 10개, 페이지 개수는 10이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;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;board-mapper.xml&lt;/p&gt;
&lt;pre class=&quot;sql&quot; data-ke-language=&quot;sql&quot;&gt;&lt;code&gt;&amp;lt;!-- 글 개수 조회 --&amp;gt;
&amp;lt;select id=&quot;getBoardCnt&quot; resultType=&quot;int&quot;&amp;gt;
	SELECT COUNT(BOARD_NUM)
	FROM BOARD, EMP
	WHERE BOARD_MENU_CODE = 'BOARD_MENU_001'
	AND BOARD_STATUS = 1
	AND BOARD_WRITER = EMPNO
	&amp;lt;if test='searchBoardVO != null and !searchBoardVO.searchKeyword.equals(&quot;&quot;)'&amp;gt;
	AND UPPER(${searchBoardVO.searchSelect}) LIKE '%'||UPPER(#{searchBoardVO.searchKeyword})||'%'
	&amp;lt;/if&amp;gt;
&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 글 개수를 구하기 위한 쿼리를 작성한다. 검색을 했을 때도 그 건수에 맞게 페이징 처리가 되어야 하기 때문에 where절을 글 목록 조회 쿼리와 같게 작성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;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;NoticeController.java&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;//게시판 목록
@GetMapping(&quot;/list&quot;)
public String noticeList(Model model, BoardVO boardVO) {
	//전체 데이터 수
	boardVO.setTotalDataCnt(noticeService.getBoardCnt(boardVO));
	
	//페이지 정보 세팅
	boardVO.setPageInfo();
	
	//전체 글 목록 조회
	model.addAttribute(&quot;noticeList&quot;, noticeService.getNoticeList(boardVO));
	
	//중요글 목록 조회
	model.addAttribute(&quot;noticeImportantList&quot;, noticeService.getNoticeImportantList());
	
	return &quot;content/notice/notice_list&quot;;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 쿼리로 구한 전체 데이터 수로 PageVO의 totalDataCnt 변수를 세팅해주고, setPageInfo() 메소드를 실행해 페이지 정보를 세팅한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;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;board-mapper.xml&lt;/p&gt;
&lt;pre class=&quot;sql&quot; data-ke-language=&quot;sql&quot;&gt;&lt;code&gt;&amp;lt;!-- 공지사항 글 목록 조회 --&amp;gt;
&amp;lt;select id=&quot;getNoticeList&quot; resultMap=&quot;board&quot;&amp;gt;
	SELECT BOARD_NUM
	    , BOARD_TITLE
	    , BOARD_WRITER
	    , TO_CHAR(BOARD_DATE, 'YYYY-MM-DD') BOARD_DATE
	    , BOARD_VIEW
	    , ENAME
	    , (SELECT COUNT(FILE_NUM) 
			FROM BOARD_FILE
			WHERE BOARD_NUM = BOARD.BOARD_NUM) FILE_CNT
		, (SELECT COUNT(REPLY_NUM)
              FROM BOARD_REPLY
              WHERE BOARD_NUM = BOARD.BOARD_NUM) REPLY_CNT
	FROM BOARD, EMP
	WHERE BOARD_MENU_CODE = 'BOARD_MENU_001'
	AND BOARD_STATUS = 1
	AND BOARD_WRITER = EMPNO
	&amp;lt;if test='searchBoardVO != null and !searchBoardVO.searchKeyword.equals(&quot;&quot;)'&amp;gt;
	AND UPPER(${searchBoardVO.searchSelect}) LIKE '%'||UPPER(#{searchBoardVO.searchKeyword})||'%'
	&amp;lt;/if&amp;gt;
	ORDER BY BOARD_NUM DESC
	OFFSET #{offsetCnt} ROWS FETCH FIRST #{displayCnt} ROWS ONLY
&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글 목록 조회 쿼리에 OFFSET FETCH 절을 추가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OFFSET offset { ROW | ROWS } &lt;br /&gt;FETCH { FIRST | NEXT } [ { rowcount | percent } ] { ROW | ROWS } { ONLY | WITH TIES }&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OFFSET : 건너뛸 행의 수를 지정(시작 행을 정함)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FETCH : 반환할 ROW 수 지정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;rowcount : 해당 수 만큼의 행을 반환&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;percent : 해당 비율만큼의 행을 반환&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ONLY : 지정한 행수만큼 리턴&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WITH TIES : 마지막 행과 값이 같은 행이 있으면 같이 반환(ORDER BY 절 지정)&lt;/p&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 class=&quot;pgsql&quot;&gt;&lt;code&gt;OFFSET #{offsetCnt} ROWS FETCH FIRST #{displayCnt} ROWS ONLY
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;offsetCnt 값만큼 건너뛰고 displayCnt 값만큼의 행만을 반환한다.는 의미임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+) OFFSET FETCH 성능이 좋지 않아 대용량의 테이블은 불가능하다고 함.. 대용량 테이블일 때는 rownum 사용해야 함&lt;/p&gt;
&lt;p data-ke-size=&quot;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;notice_list.html&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(전체 건수)&lt;/p&gt;
&lt;pre class=&quot;dust&quot;&gt;&lt;code&gt;&amp;lt;div class=&quot;text-secondary fs-6 align-self-end&quot;&amp;gt;전체 &amp;lt;span class=&quot;text-dark&quot;&amp;gt;[[${boardVO.totalDataCnt}]]&amp;lt;/span&amp;gt;건&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;totalDataCnt 변수로 조회한 전체 건수를 보여준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(게시글 목록 table의 tbody)&lt;/p&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;&amp;lt;tbody&amp;gt;
	&amp;lt;tr th:if=&quot;${#lists.size(noticeImportantList) != 0}&quot; th:each=&quot;important, state : ${noticeImportantList}&quot;  class=&quot;table-light&quot;&amp;gt;
		&amp;lt;td&amp;gt;
			&amp;lt;span class=&quot;badge text-bg-success&quot;&amp;gt;중요&amp;lt;/span&amp;gt;
		&amp;lt;/td&amp;gt;
		&amp;lt;td class=&quot;text-start&quot;&amp;gt;
			&amp;lt;a th:href=&quot;@{/notice/detail(boardNum=${important.boardNum})}&quot; style=&quot;color: black;&quot;&amp;gt;
			[[${important.boardTitle}]]
			&amp;lt;/a&amp;gt;
			
			&amp;lt;th:block th:if=&quot;${important.replyCnt != 0}&quot;&amp;gt;
				&amp;lt;span class=&quot;fs-6 text-secondary&quot; th:text=&quot;'[' + ${important.replyCnt} + ']'&quot;&amp;gt;&amp;lt;/span&amp;gt;
			&amp;lt;/th:block&amp;gt;
		&amp;lt;/td&amp;gt;
		&amp;lt;td&amp;gt;
			&amp;lt;th:block th:if=&quot;${important.fileCnt != 0}&quot;&amp;gt;
				&amp;lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;20&quot; height=&quot;20&quot; fill=&quot;currentColor&quot; class=&quot;bi bi-paperclip&quot; viewBox=&quot;0 0 16 16&quot;&amp;gt;
				  &amp;lt;path d=&quot;M4.5 3a2.5 2.5 0 0 1 5 0v9a1.5 1.5 0 0 1-3 0V5a.5.5 0 0 1 1 0v7a.5.5 0 0 0 1 0V3a1.5 1.5 0 1 0-3 0v9a2.5 2.5 0 0 0 5 0V5a.5.5 0 0 1 1 0v7a3.5 3.5 0 1 1-7 0V3z&quot;/&amp;gt;
				&amp;lt;/svg&amp;gt;
			&amp;lt;/th:block&amp;gt;
		&amp;lt;/td&amp;gt;
		&amp;lt;td&amp;gt;[[${important.ename}]]&amp;lt;/td&amp;gt;
		&amp;lt;td&amp;gt;[[${important.boardDate}]]&amp;lt;/td&amp;gt;
		&amp;lt;td&amp;gt;[[${important.boardView}]]&amp;lt;/td&amp;gt;
	&amp;lt;/tr&amp;gt;
	&amp;lt;th:block th:if=&quot;${#lists.size(noticeList) == 0}&quot;&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;td colspan=&quot;5&quot;&amp;gt;등록된 게시글이 없습니다.&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;						
	&amp;lt;/th:block&amp;gt;
	&amp;lt;th:block th:unless=&quot;${#lists.size(noticeList) == 0}&quot;&amp;gt;
		&amp;lt;tr th:each=&quot;notice, state : ${noticeList}&quot;&amp;gt;
			&amp;lt;td&amp;gt;[[${boardVO.totalDataCnt - ((boardVO.nowPage - 1) * boardVO.displayCnt + state.index)}]]&amp;lt;/td&amp;gt;
			&amp;lt;td class=&quot;text-start&quot;&amp;gt;
				&amp;lt;a th:href=&quot;@{/notice/detail(boardNum=${notice.boardNum})}&quot; style=&quot;color: black;&quot;&amp;gt;
				[[${notice.boardTitle}]]
				&amp;lt;/a&amp;gt;
				&amp;lt;th:block th:if=&quot;${notice.replyCnt != 0}&quot;&amp;gt;
					&amp;lt;span class=&quot;fs-6 text-secondary&quot; th:text=&quot;'[' + ${notice.replyCnt} + ']'&quot;&amp;gt;&amp;lt;/span&amp;gt;
				&amp;lt;/th:block&amp;gt;
			&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;
				&amp;lt;th:block th:if=&quot;${notice.fileCnt != 0}&quot;&amp;gt;
					&amp;lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;20&quot; height=&quot;20&quot; fill=&quot;currentColor&quot; class=&quot;bi bi-paperclip&quot; viewBox=&quot;0 0 16 16&quot;&amp;gt;
					  &amp;lt;path d=&quot;M4.5 3a2.5 2.5 0 0 1 5 0v9a1.5 1.5 0 0 1-3 0V5a.5.5 0 0 1 1 0v7a.5.5 0 0 0 1 0V3a1.5 1.5 0 1 0-3 0v9a2.5 2.5 0 0 0 5 0V5a.5.5 0 0 1 1 0v7a3.5 3.5 0 1 1-7 0V3z&quot;/&amp;gt;
					&amp;lt;/svg&amp;gt;
				&amp;lt;/th:block&amp;gt;
			&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;[[${notice.ename}]]&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;[[${notice.boardDate}]]&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;[[${notice.boardView}]]&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
	&amp;lt;/th:block&amp;gt;
&amp;lt;/tbody&amp;gt;&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;&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;ex) 현재 전체 글 개수 = 43, 현재 페이지 = 1, 한 페이지에 보여지는 글 개수 = 10&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;43 - ((1-1) * 10 + index) = 43 - 0, 43 - 1, 43 - 2 &amp;hellip;..&lt;/p&gt;
&lt;p data-ke-size=&quot;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;(페이징 nav)&lt;/p&gt;
&lt;nav aria-label=&quot;Page navigation example&quot;&gt;&lt;/nav&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;&amp;lt;nav aria-label=&quot;Page navigation example&quot;&amp;gt;
  &amp;lt;ul class=&quot;pagination justify-content-center&quot;&amp;gt;
    &amp;lt;li class=&quot;page-item&quot; th:classappend=&quot;${boardVO.prev} ? '' :  'disabled'&quot;&amp;gt;
      &amp;lt;button class=&quot;page-link&quot; th:onclick=&quot;movePage([[${boardVO.beginPage-1}]])&quot; aria-label=&quot;Previous&quot;&amp;gt;
        &amp;lt;span aria-hidden=&quot;true&quot;&amp;gt;
        	&amp;lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;16&quot; height=&quot;16&quot; fill=&quot;currentColor&quot; class=&quot;bi bi-chevron-left&quot; viewBox=&quot;0 0 16 16&quot;&amp;gt;
			  &amp;lt;path fill-rule=&quot;evenodd&quot; d=&quot;M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z&quot;/&amp;gt;
			&amp;lt;/svg&amp;gt;
        &amp;lt;/span&amp;gt;
      &amp;lt;/button&amp;gt;
    &amp;lt;/li&amp;gt;
    &amp;lt;th:block th:each=&quot;pageNum : ${#numbers.sequence(boardVO.beginPage, boardVO.endPage)}&quot;&amp;gt;
	    &amp;lt;li class=&quot;page-item&quot; th:classappend=&quot;${boardVO.nowPage == pageNum} ? 'active' : ''&quot;&amp;gt;
	    	&amp;lt;button class=&quot;page-link&quot; th:onclick=&quot;movePage([[${pageNum}]])&quot;&amp;gt;[[${pageNum}]]&amp;lt;/button&amp;gt;
	    &amp;lt;/li&amp;gt;
    &amp;lt;/th:block&amp;gt;
    &amp;lt;li class=&quot;page-item&quot; th:classappend=&quot;${boardVO.next} ? '' :  'disabled'&quot;&amp;gt;
      &amp;lt;button class=&quot;page-link&quot; th:onclick=&quot;movePage([[${boardVO.endPage+1}]])&quot; aria-label=&quot;Next&quot;&amp;gt;
        &amp;lt;span aria-hidden=&quot;true&quot;&amp;gt;
			&amp;lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;16&quot; height=&quot;16&quot; fill=&quot;currentColor&quot; class=&quot;bi bi-chevron-right&quot; viewBox=&quot;0 0 16 16&quot;&amp;gt;
			  &amp;lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z&quot;/&amp;gt;
			&amp;lt;/svg&amp;gt;
		&amp;lt;/span&amp;gt;
      &amp;lt;/button&amp;gt;
    &amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/nav&amp;gt;&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;페이지가 10개 이상이고, 화면에 보이는 마지막 페이지 번호가 전체 페이지 개수보다 작으면 next는 true&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지가 10개 이상이고, 화면에 보이는 첫 번째 페이지 번호가 1이 아닐 때는 prev가 true 값이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;next와 prev가 false로 넘어오면 th:classappend로 버튼에 disabled 속성을 추가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;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;notice_list.js&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;//페이지 이동 + 검색
function movePage(pageNum) {
	const noticeForm = document.querySelector('#noticeForm');
	document.querySelector('#nowPage').value = pageNum;	
	noticeForm.submit();
}&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;notice_list.html&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(검색 form 태그)&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;&amp;lt;form action=&quot;/notice/list&quot; method=&quot;get&quot; id=&quot;noticeForm&quot;&amp;gt;
	&amp;lt;div class=&quot;input-group&quot; style=&quot;width: 20rem;&quot;&amp;gt;
		&amp;lt;select class=&quot;form-select&quot; name=&quot;searchBoardVO.searchSelect&quot;&amp;gt;
		  &amp;lt;option value=&quot;BOARD_TITLE&quot; 
		  		th:selected=&quot;${boardVO.searchBoardVO == null or (boardVO.searchBoardVO != null and boardVO.searchBoardVO.searchSelect == 'BOARD_TITLE')}&quot;&amp;gt;제목&amp;lt;/option&amp;gt;
		  &amp;lt;option value=&quot;ENAME&quot;
		  		th:selected=&quot;${boardVO.searchBoardVO != null and boardVO.searchBoardVO.searchSelect == 'ENAME'}&quot;&amp;gt;작성자&amp;lt;/option&amp;gt;
		&amp;lt;/select&amp;gt;
		&amp;lt;input type=&quot;text&quot; class=&quot;form-control w-25&quot; name=&quot;searchBoardVO.searchKeyword&quot;
				th:value=&quot;${boardVO.searchBoardVO == null ? '' : boardVO.searchBoardVO.searchKeyword}&quot;&amp;gt;
		&amp;lt;input type=&quot;submit&quot; class=&quot;btn&quot; value=&quot;검색&quot;&amp;gt;
	&amp;lt;/div&amp;gt;
	&amp;lt;input type=&quot;hidden&quot; id=&quot;nowPage&quot; name=&quot;nowPage&quot; 
					th:value=&quot;${boardVO.nowPage}&quot;&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지 버튼을 누르면 movePage() 함수가 실행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;movePage() 함수가 실행되면 id값이 nowPage인 input 태그를 찾아 value 값을 함수의 매개변수로 지정하고 form태그를 submit 한다. (함수의 매개변수에는 이동하고자 하는 페이지 넘버가 담긴다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 페이지가 넘어갈 때 검색 form 태그를 submit 하는 이유는 검색 시에도 페이징 처리가 되어야 하기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프로젝트</category>
      <author>하차모</author>
      <guid isPermaLink="true">https://hachamo.tistory.com/60</guid>
      <comments>https://hachamo.tistory.com/60#entry60comment</comments>
      <pubDate>Tue, 30 May 2023 22:39:13 +0900</pubDate>
    </item>
    <item>
      <title>17. 공지사항 게시판 (검색)</title>
      <link>https://hachamo.tistory.com/59</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;게시글 키워드 검색&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷(40).png&quot; data-origin-width=&quot;1317&quot; data-origin-height=&quot;846&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/s2r0W/btsh17hpvsm/lDCk5qkzy4i0uz9Bp5QkaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/s2r0W/btsh17hpvsm/lDCk5qkzy4i0uz9Bp5QkaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/s2r0W/btsh17hpvsm/lDCk5qkzy4i0uz9Bp5QkaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fs2r0W%2Fbtsh17hpvsm%2FlDCk5qkzy4i0uz9Bp5QkaK%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;1317&quot; height=&quot;846&quot; data-filename=&quot;스크린샷(40).png&quot; data-origin-width=&quot;1317&quot; data-origin-height=&quot;846&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;기능을 추가할 때마다 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;p data-ke-size=&quot;size16&quot;&gt;notice_list.html&lt;/p&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;&amp;lt;form action=&quot;/notice/list&quot; method=&quot;get&quot; id=&quot;noticeForm&quot;&amp;gt;
	&amp;lt;div class=&quot;input-group&quot; style=&quot;width: 20rem;&quot;&amp;gt;
		&amp;lt;select class=&quot;form-select&quot; name=&quot;searchBoardVO.searchSelect&quot;&amp;gt;
		  &amp;lt;option value=&quot;BOARD_TITLE&quot; 
		  		th:selected=&quot;${boardVO.searchBoardVO == null or (boardVO.searchBoardVO != null and boardVO.searchBoardVO.searchSelect == 'BOARD_TITLE')}&quot;&amp;gt;제목&amp;lt;/option&amp;gt;
		  &amp;lt;option value=&quot;ENAME&quot;
		  		th:selected=&quot;${boardVO.searchBoardVO != null and boardVO.searchBoardVO.searchSelect == 'ENAME'}&quot;&amp;gt;작성자&amp;lt;/option&amp;gt;
		&amp;lt;/select&amp;gt;
		&amp;lt;input type=&quot;text&quot; class=&quot;form-control w-25&quot; name=&quot;searchBoardVO.searchKeyword&quot;
				th:value=&quot;${boardVO.searchBoardVO == null ? '' : boardVO.searchBoardVO.searchKeyword}&quot;&amp;gt;
		&amp;lt;input type=&quot;submit&quot; class=&quot;btn&quot; value=&quot;검색&quot;&amp;gt;
	&amp;lt;/div&amp;gt;
&amp;lt;/form&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색 기능이기 때문에 form 데이터를 get 방식으로 처리했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GET 방식은 클라이언트에서 서버로 데이터를 전송할 때 URL에다 &amp;lsquo;?변수 이름=값&amp;rsquo; 형태로 데이터를 넣어 전송한다. (Query String 형식)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;POST 방식은 HTTP 패킷의 body 부분에 그 값을 넣어서 전송한다. URL로는 데이터가 노출되지 않기 때문에 보안에 더 우수하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GET 방식은 검색이나 조회 등 데이터를 읽을 때,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;POST 방식은 게시, 수정 등 데이터를 생성할 때 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;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;스크린샷(43).png&quot; data-origin-width=&quot;1333&quot; data-origin-height=&quot;596&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjS7rp/btsh3kG5wDJ/Aj23sxqYEoav1vTISrqCgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjS7rp/btsh3kG5wDJ/Aj23sxqYEoav1vTISrqCgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjS7rp/btsh3kG5wDJ/Aj23sxqYEoav1vTISrqCgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjS7rp%2Fbtsh3kG5wDJ%2FAj23sxqYEoav1vTISrqCgk%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;1333&quot; height=&quot;596&quot; data-filename=&quot;스크린샷(43).png&quot; data-origin-width=&quot;1333&quot; data-origin-height=&quot;596&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네이버 검색 form 태그를 확인해보면 get 방식인 것을 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;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;lsquo;검색유형&amp;rsquo;과 &amp;lsquo;검색 키워드&amp;rsquo;이다. (검색 유형에는 제목, 작성자가 있다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 select 태그에서 고른 option의 value값이 바로 쿼리로 들어가도록 테이블의 컬럼 이름으로 넣었다.(제목=&amp;rdquo;BOARD_TITLE&amp;rdquo;, 작성자=&amp;rdquo;ENAME&amp;rdquo;)&lt;/p&gt;
&lt;p data-ke-size=&quot;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;SearchBoardVO.java&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class SearchBoardVO {
	private String searchSelect;
	private String searchKeyword;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BoardVO.java&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class BoardVO {
	
	...(생략)
	
	private SearchBoardVO searchBoardVO;
	
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SearchBoardVO를 만들고 BoardVO의 변수로 추가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;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;NoticeController.java&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;//게시판 목록
@GetMapping(&quot;/list&quot;)
public String noticeList(Model model, BoardVO boardVO) {

    //전체 글 목록 조회
    model.addAttribute(&quot;noticeList&quot;, noticeService.getNoticeList(boardVO));

    //중요글 목록 조회
    model.addAttribute(&quot;noticeImportantList&quot;, noticeService.getNoticeImportantList());

    return &quot;content/notice/notice_list&quot;;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;form태그 submit 해서 넘어온 값이 boardVO에 담겨지고, 전체 글 목록을 조회하는 쿼리에 파라메터로 넘어간다.&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;스크린샷(47).png&quot; data-origin-width=&quot;711&quot; data-origin-height=&quot;152&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqlPk8/btsh2tR5CnQ/WVzmqqAQhdvPPwgWG8oDkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqlPk8/btsh2tR5CnQ/WVzmqqAQhdvPPwgWG8oDkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqlPk8/btsh2tR5CnQ/WVzmqqAQhdvPPwgWG8oDkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqlPk8%2Fbtsh2tR5CnQ%2FWVzmqqAQhdvPPwgWG8oDkk%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;711&quot; height=&quot;152&quot; data-filename=&quot;스크린샷(47).png&quot; data-origin-width=&quot;711&quot; data-origin-height=&quot;152&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;board-mapper.xml&lt;/p&gt;
&lt;pre class=&quot;sql&quot; data-ke-language=&quot;sql&quot;&gt;&lt;code&gt;&amp;lt;!-- 공지사항 글 목록 조회 --&amp;gt;
&amp;lt;select id=&quot;getNoticeList&quot; resultMap=&quot;board&quot;&amp;gt;
	SELECT BOARD_NUM
	    , BOARD_TITLE
	    , BOARD_WRITER
	    , TO_CHAR(BOARD_DATE, 'YYYY-MM-DD') BOARD_DATE
	    , BOARD_VIEW
	    , ENAME
	    , (SELECT COUNT(FILE_NUM) 
			FROM BOARD_FILE
			WHERE BOARD_NUM = BOARD.BOARD_NUM) FILE_CNT
		, (SELECT COUNT(REPLY_NUM)
              FROM BOARD_REPLY
              WHERE BOARD_NUM = BOARD.BOARD_NUM) REPLY_CNT
	FROM BOARD, EMP
	WHERE BOARD_MENU_CODE = 'BOARD_MENU_001'
	AND BOARD_STATUS = 1
	AND BOARD_WRITER = EMPNO
	&amp;lt;if test='searchBoardVO != null and !searchBoardVO.searchKeyword.equals(&quot;&quot;)'&amp;gt;
	AND UPPER(${searchBoardVO.searchSelect}) LIKE '%'||UPPER(#{searchBoardVO.searchKeyword})||'%'
	&amp;lt;/if&amp;gt;
	ORDER BY BOARD_NUM DESC
&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;if&amp;gt;문을 사용해 searchBoardVO가 Null 값이 아닐 때(사용자가 검색 버튼을 눌러 form 태그가 submit 되었을 때) WHERE 절이 실행되도록 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#{}는 파라메터가 String 형태로 들어와 &amp;lsquo;파라메터&amp;rsquo; 형태가 되고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;${}는 파라메터가 &amp;lsquo;&amp;rsquo; 없이 바로 출력된다. (테이블이나 컬럼명을 파라메타로 전달할 때 사용된다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컬럼명을 담고 있는 searchSelect는 ${}를, 검색 키워드를 담고 있는 searchKeyword는 #{}를 사용했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;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;해당 쿼리로 조회된 리스트가 noticeList라는 이름으로 html에 넘어간다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷(46).png&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;584&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mKDw8/btsh3l6174n/srZRNI50FKwR6eHM7uMwkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mKDw8/btsh3l6174n/srZRNI50FKwR6eHM7uMwkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mKDw8/btsh3l6174n/srZRNI50FKwR6eHM7uMwkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmKDw8%2Fbtsh3l6174n%2FsrZRNI50FKwR6eHM7uMwkK%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;1295&quot; height=&quot;584&quot; data-filename=&quot;스크린샷(46).png&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;584&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;</description>
      <category>프로젝트</category>
      <author>하차모</author>
      <guid isPermaLink="true">https://hachamo.tistory.com/59</guid>
      <comments>https://hachamo.tistory.com/59#entry59comment</comments>
      <pubDate>Tue, 30 May 2023 22:32:32 +0900</pubDate>
    </item>
    <item>
      <title>16. 공지사항 게시판 (댓글 삭제, 수정)</title>
      <link>https://hachamo.tistory.com/58</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;댓글 삭제&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷(37).png&quot; data-origin-width=&quot;1386&quot; data-origin-height=&quot;644&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHOQ94/btshqTKnNCs/skb6jf99ZdGHctKoDSqlx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHOQ94/btshqTKnNCs/skb6jf99ZdGHctKoDSqlx1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHOQ94/btshqTKnNCs/skb6jf99ZdGHctKoDSqlx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHOQ94%2FbtshqTKnNCs%2Fskb6jf99ZdGHctKoDSqlx1%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;1386&quot; height=&quot;644&quot; data-filename=&quot;스크린샷(37).png&quot; data-origin-width=&quot;1386&quot; data-origin-height=&quot;644&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;삭제 버튼을 누르면 onclick 속성으로 deleteReply() 함수가 실행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;notice_detail.js&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;//댓글 삭제
function deleteReply(replyNum, deleteBtn) {
	const deleteReplyTag = deleteBtn.closest('tr');
	const replyTable = document.querySelector('#replyTable');
	const replyCntSpan = document.querySelector('#replyCntSpan');
	
	if(confirm('댓글을 삭제하시겠습니까?')) {
		//ajax start
		$.ajax({
			url: '/reply/delete', //요청경로
			type: 'post',
			async: true,
			contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
			data: {'replyNum' : replyNum}, //필요한 데이터
			success: function(result) {
				deleteReplyTag.remove();
				
				const replyTrs = replyTable.querySelectorAll('tr');
				
				//댓글이 없으면
				if(replyTrs.length == 1) {
					let str = '';
					
					str += `&amp;lt;tr class=&quot;border-top&quot; id=&quot;noReplyTr&quot;&amp;gt;                                             `;
					str += `	&amp;lt;td class=&quot;text-secondary text-center align-middle&quot; colspan=&quot;2&quot; height=&quot;120px&quot;&amp;gt;`;
					str += `		등록된 댓글이 없습니다.                                                    		`;
					str += `	&amp;lt;/td&amp;gt;                                                                          `;
					str += `&amp;lt;/tr&amp;gt;                                                                              `;
					
					replyTable.insertAdjacentHTML('afterbegin', str);
				}
				
				replyCntSpan.textContent = Number(replyCntSpan.textContent) - 1;
			},
			error: function() {
				alert('실패');
			}
		});
		//ajax end
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ajax를 이용해 Controller로 댓글 번호 pk를 넘겨준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 방식이기 때문에 페이지 리로딩 없이 처리가 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨트롤러에서 삭제를 성공했을 때, 삭제한 댓글이 담긴 tr 태그를 삭제해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;댓글 테이블에서 tr태그를 모두 select 해 왔을 때, tr태그가 하나인 경우(= 댓글 등록 tr만 남았을 경우, 등록된 댓글이 하나도 없을 경우) 등록된 댓글이 없다는 내용을 담고 있는 tr 태그를 삽입해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;댓글 수를 나타내는 span 태그도 가져와서 -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;처음 사진에서 마지막 댓글 삭제 후, 페이지 리로드 없이도 댓글이 사라지고 댓글 개수도 2개로 줄어든 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷(39).png&quot; data-origin-width=&quot;1392&quot; data-origin-height=&quot;608&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYmFjr/btshpYyWslH/3XjixuIYy0oPbph8FlcYdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYmFjr/btshpYyWslH/3XjixuIYy0oPbph8FlcYdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYmFjr/btshpYyWslH/3XjixuIYy0oPbph8FlcYdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYmFjr%2FbtshpYyWslH%2F3XjixuIYy0oPbph8FlcYdK%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;1392&quot; height=&quot;608&quot; data-filename=&quot;스크린샷(39).png&quot; data-origin-width=&quot;1392&quot; data-origin-height=&quot;608&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;댓글 수정&lt;/h2&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;먼저 수정 버튼을 눌렀을 때, updateReplyForm()함수가 실행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;댓글 내용이 있던 부분에 기존 내용이 담겨있는 textarea로 변경해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lsquo;수정&amp;rsquo; 이라고 쓰여있던 버튼을 &amp;lsquo;등록&amp;rsquo;으로 바꾸고, onclick 함수도 updateReply()로 바꾼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 innerHTML로 기존 내용을 가져와야 &amp;lt;br&amp;gt;태그까지 가져올 수 있고, 그 &amp;lt;br&amp;gt;태그는 정규식을 이용해 엔터값으로 변경하여 textarea에 담아준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷(38).png&quot; data-origin-width=&quot;1347&quot; data-origin-height=&quot;669&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bokAlk/btshr5p3x18/KJgKh81nF6Pw0TckabvdGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bokAlk/btshr5p3x18/KJgKh81nF6Pw0TckabvdGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bokAlk/btshr5p3x18/KJgKh81nF6Pw0TckabvdGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbokAlk%2Fbtshr5p3x18%2FKJgKh81nF6Pw0TckabvdGk%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;1347&quot; height=&quot;669&quot; data-filename=&quot;스크린샷(38).png&quot; data-origin-width=&quot;1347&quot; data-origin-height=&quot;669&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;notice_detail.js&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;//댓글 수정 폼
function updateReplyForm(replyNum, updateBtn) {
	const replyContentDiv = updateBtn.parentElement.previousElementSibling;
	const replyContent = replyContentDiv.innerHTML;
	
	const replyContentBr = replyContent.replaceAll(&quot;&amp;lt;br&amp;gt;&quot;, &quot;\\r\\n&quot;);
	
	const str = `&amp;lt;textarea class=&quot;form-control my-1&quot; style=&quot;resize: none&quot;&amp;gt;${replyContentBr}&amp;lt;/textarea&amp;gt;`;
	
	replyContentDiv.replaceChildren();
	replyContentDiv.insertAdjacentHTML('afterbegin', str);
	
	updateBtn.value = '등록';
	updateBtn.setAttribute(&quot;onClick&quot;, `updateReply(&quot;${replyNum}&quot;, this)`);
}&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;댓글 내용 수정 후 등록 버튼을 눌렀을 때, updateReply() 함수가 실행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내용이 입력되지 않았을 때, 간단한 유효성 검사를 해주고, 정규식을 이용해 엔터값이 있는 경우 &amp;lt;br&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;notice_detail.js&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;//댓글 수정
function updateReply(replyNum, formBtn) {
	const replyContentDiv = formBtn.parentElement.previousElementSibling;
	const replyContent = replyContentDiv.querySelector('textarea').value;
	const replyDateDiv = replyContentDiv.previousElementSibling.lastElementChild;
	
	if(replyContent == '' || replyContent == null) {
		alert('댓글을 입력해주세요.');
		return false;
	};
	
	const replyContentBr = replyContent.replace(/(?:\\r\\n|\\r|\\n)/g, '&amp;lt;br&amp;gt;');
	
	//ajax start
	$.ajax({
		url: '/reply/update', //요청경로
		type: 'post',
		async: true,
		contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
		data: {'replyNum' : replyNum, 'replyContent' : replyContentBr}, //필요한 데이터
		success: function(result) {
			const reply = result;
			
			replyDateDiv.replaceChildren();
			replyDateDiv.textContent = reply.replyDate;
			
			replyContentDiv.replaceChildren();
			replyContentDiv.innerHTML = reply.replyContent;
			
			formBtn.value = '수정';
			formBtn.setAttribute(&quot;onClick&quot;, `updateReplyForm(&quot;${replyNum}&quot;, this)`);
		},
		error: function() {
			alert('실패');
		}
	});
	//ajax end
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엔터값 처리를 해준 댓글 내용과 댓글 번호 pk값을 컨트롤러로 보내주면, 컨트롤러에서는 update쿼리로 수정하고 수정된 댓글을 조회한 값을 반환해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정된 댓글 정보를 기존 댓글 칸에 넣어준다. 이때 innerHTML로 넣어 줘야 &amp;lt;br&amp;gt;태그도 인식이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lsquo;등록&amp;rsquo;이라고 적혀있던 버튼을 &amp;lsquo;수정&amp;rsquo;으로 바꿔주고 onclick함수도 updateReplyForm()으로 바꿔준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;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;ReplyController.java&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;//댓글 수정
	@ResponseBody
	@PostMapping(&quot;/update&quot;)
	public ReplyVO updateReply(ReplyVO replyVO) {
		replyService.updateReply(replyVO);
		
		return replyService.getReplyByReplyNum(replyVO.getReplyNum());
	}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;게시글 상세 조회 시 댓글 목록 조회&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;board-mapper.xml&lt;/p&gt;
&lt;pre class=&quot;sql&quot; data-ke-language=&quot;sql&quot;&gt;&lt;code&gt;&amp;lt;!-- (상세 조회) + 댓글 리스트 조회 --&amp;gt;
&amp;lt;select id=&quot;getReplyList&quot; resultMap=&quot;replyMapper.reply&quot;&amp;gt;
    SELECT REPLY_NUM
        , REPLY_WRITER
        , ENAME
        , REPLY_CONTENT
        , TO_CHAR(REPLY_DATE, 'YYYY-MM-DD HH24:MI') REPLY_DATE
    FROM BOARD_REPLY, EMP
    WHERE BOARD_NUM = #{boardNum}
    AND REPLY_WRITER = EMPNO
    ORDER BY REPLY_NUM
&amp;lt;/select&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;lsquo;조회수 증가 &amp;amp; 첨부파일 조회 + 댓글 조회 + 글 상세 조회&amp;rsquo;를 트랜잭션 처리했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NoticeServiceImpl.java&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;//공지글 상세 조회
@Override
@Transactional(rollbackFor = Exception.class)
public BoardVO getNoticeDetail(BoardVO boardVO) {
    //조회수 증가
    sqlSession.update(&quot;boardMapper.updateBoardView&quot;, boardVO);

    //첨부파일 조회
    List&amp;lt;BoardFileVO&amp;gt; selectedFileList = sqlSession.selectList(&quot;boardMapper.getBoardFile&quot;, boardVO);

    //댓글 조회
    List&amp;lt;ReplyVO&amp;gt; replyList = sqlSession.selectList(&quot;boardMapper.getReplyList&quot;, boardVO);

    //상세 조회하는 글
    BoardVO selectedBoard = sqlSession.selectOne(&quot;boardMapper.getNoticeDetail&quot;, boardVO);

    //첨부파일 변수에 담아줌
    selectedBoard.setBoardFileList(selectedFileList);

    //댓글 변수에 담아줌
    selectedBoard.setReplyList(replyList);

    //글 상세 조회 정보 반환
    return selectedBoard;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;글 목록 조회 시 댓글 개수&lt;/h2&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;스크린샷(40).png&quot; data-origin-width=&quot;1317&quot; data-origin-height=&quot;846&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sQ0aP/btshrR6rOiS/HSQj4AbIgHKZrnQizWvoZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sQ0aP/btshrR6rOiS/HSQj4AbIgHKZrnQizWvoZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sQ0aP/btshrR6rOiS/HSQj4AbIgHKZrnQizWvoZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsQ0aP%2FbtshrR6rOiS%2FHSQj4AbIgHKZrnQizWvoZ0%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;1317&quot; height=&quot;846&quot; data-filename=&quot;스크린샷(40).png&quot; data-origin-width=&quot;1317&quot; data-origin-height=&quot;846&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;/p&gt;</description>
      <category>프로젝트</category>
      <author>하차모</author>
      <guid isPermaLink="true">https://hachamo.tistory.com/58</guid>
      <comments>https://hachamo.tistory.com/58#entry58comment</comments>
      <pubDate>Fri, 26 May 2023 00:40:44 +0900</pubDate>
    </item>
    <item>
      <title>15. 공지사항 게시판 (댓글 등록)</title>
      <link>https://hachamo.tistory.com/57</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;pre class=&quot;sql&quot; data-ke-language=&quot;sql&quot;&gt;&lt;code&gt;ALTER TABLE BOARD_REPLY ADD REPLY_WRITER NUMBER CONSTRAINT REPLY_EMP_FK REFERENCES EMP(EMPNO) NOT NULL;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;댓글 등록&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷(37).png&quot; data-origin-width=&quot;1386&quot; data-origin-height=&quot;644&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cXaFLk/btsht02QC8Q/BRZrpeifeeZDnj02tYx3xk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cXaFLk/btsht02QC8Q/BRZrpeifeeZDnj02tYx3xk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cXaFLk/btsht02QC8Q/BRZrpeifeeZDnj02tYx3xk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcXaFLk%2Fbtsht02QC8Q%2FBRZrpeifeeZDnj02tYx3xk%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;1386&quot; height=&quot;644&quot; data-filename=&quot;스크린샷(37).png&quot; data-origin-width=&quot;1386&quot; data-origin-height=&quot;644&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;제일 하단에 댓글 입력 칸이 있고 시간순으로 위에서 아래로 댓글이 등록되도록 했음&lt;/p&gt;
&lt;p data-ke-size=&quot;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;등록 버튼을 클릭하면 regReply() 함수가 실행됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;notice_detail.html&lt;/p&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;&amp;lt;tr class=&quot;border-top&quot; id=&quot;regReplyTr&quot;&amp;gt;
	&amp;lt;td colspan=&quot;2&quot;&amp;gt;
		&amp;lt;div class=&quot;input-group&quot;&amp;gt;
			&amp;lt;textarea class=&quot;form-control&quot; rows=&quot;5px&quot; style=&quot;resize: none&quot; id=&quot;replyTextarea&quot;&amp;gt;&amp;lt;/textarea&amp;gt;
			&amp;lt;input type=&quot;button&quot; class=&quot;btn&quot; th:onclick=&quot;regReply([[${notice.boardNum}]]);&quot; value=&quot;등록&quot;&amp;gt;
		&amp;lt;/div&amp;gt;
	&amp;lt;/td&amp;gt;
&amp;lt;/tr&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;regReply() 함수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;댓글 기능은 전체적으로 Ajax로 구현했는데, 페이지 리로딩 없이 비동기식으로 처리할 수 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;notice_detail.js&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;//댓글 등록
function regReply(boardNum) {
	const replyTextarea = document.querySelector('#replyTextarea');
	const replyContent = replyTextarea.value;
	const regReplyTr = document.querySelector('#regReplyTr');
	const noReplyTr = document.querySelector('#noReplyTr');
	const replyCntSpan = document.querySelector('#replyCntSpan');
	
	if(replyContent == '' || replyContent == null) {
		alert('댓글을 입력해주세요.');
		return false;
	};
	
	const replyContentBr = replyContent.replace(/(?:\\r\\n|\\r|\\n)/g, '&amp;lt;br&amp;gt;');
	
	//ajax start
	$.ajax({
		url: '/reply/regReply', //요청경로
		type: 'post',
		async: true,
		contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
		data: {'replyContent' : replyContentBr, 'boardNum' : boardNum}, //필요한 데이터
		success: function(result) {
			const reply = result;
			
			if(noReplyTr != null) {
				noReplyTr.remove();
			}
			
			let str = '';
			
			str += `&amp;lt;tr class=&quot;border-top&quot;&amp;gt;                                                         `;
			str += `	&amp;lt;td class=&quot;text-center&quot;&amp;gt;                                                    `;
			str += `		&amp;lt;img src=&quot;/img/content/board/testProfile.png&quot; width=&quot;100%&quot; class=&quot;mx-0&quot;&amp;gt;`;
			str += `	&amp;lt;/td&amp;gt;                                                                       `;
			str += `	&amp;lt;td&amp;gt;                                                                        `;
			str += `		&amp;lt;div class=&quot;d-flex justify-content-between&quot;&amp;gt;                            `;
			str += `			&amp;lt;div class=&quot;fw-semibold mb-1&quot;&amp;gt;${reply.ename}&amp;lt;/div&amp;gt;                    `;
			str += `			&amp;lt;div class=&quot;text-secondary fs-6&quot;&amp;gt;${reply.replyDate}&amp;lt;/div&amp;gt;           `;
			str += `		&amp;lt;/div&amp;gt;                                                                  `;
			str += `		&amp;lt;div&amp;gt;${reply.replyContent}&amp;lt;/div&amp;gt;                                              `;
			str += `		&amp;lt;div class=&quot;d-grid gap-1 d-md-flex justify-content-md-end&quot;&amp;gt;             `;
			str += `			&amp;lt;input type=&quot;button&quot; class=&quot;btn&quot; onclick=&quot;updateReplyForm('${reply.replyNum}', this)&quot; value=&quot;수정&quot;&amp;gt;                      `;
			str += `			&amp;lt;input type=&quot;button&quot; class=&quot;btn&quot; onclick=&quot;deleteReply('${reply.replyNum}', this)&quot; value=&quot;삭제&quot;&amp;gt;                      `;
			str += `		&amp;lt;/div&amp;gt;                                                                  `;
			str += `	&amp;lt;/td&amp;gt;                                                                       `;
			str += `&amp;lt;/tr&amp;gt;                                                                           `;
			
			
			regReplyTr.insertAdjacentHTML('beforebegin', str);
			
			replyTextarea.value = '';
			
			replyCntSpan.textContent = Number(replyCntSpan.textContent) + 1;
		},
		error: function() {
			alert('실패');
		}
	});
	//ajax end
	
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;textarea value 값이 비어 있을 때 간단한 유효성 검사와 정규식을 사용해 엔터값이 넘어 왔을 때 &amp;lt;br&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;댓글 등록은 리소스 생성이기 때문에 POST 방식을 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;댓글 내용 값(replyContent)과 댓글을 등록하는 글의 번호(boardNum)를 넘겨준다.&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;스크린샷(41).png&quot; data-origin-width=&quot;1342&quot; data-origin-height=&quot;353&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9WJue/btshr6Cur7b/at56J8UWY1upBw8cunOya1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9WJue/btshr6Cur7b/at56J8UWY1upBw8cunOya1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9WJue/btshr6Cur7b/at56J8UWY1upBw8cunOya1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9WJue%2Fbtshr6Cur7b%2Fat56J8UWY1upBw8cunOya1%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;1342&quot; height=&quot;353&quot; data-filename=&quot;스크린샷(41).png&quot; data-origin-width=&quot;1342&quot; data-origin-height=&quot;353&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;noReplyTr은 위 사진처럼 댓글이 없을 때 보이는 tr태그이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 등록하는 댓글이 해당 글의 첫 댓글이라면 (=noReplyTr이 존재한다면) 그 tr을 삭제함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨트롤러의 리턴 값이 새로 등록한 댓글을 ReplyVO이기 때문에 받아온 값으로 바로 댓글 테이블에 등록한 댓글 정보를 추가함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;댓글 테이블 상단에 현재 글의 댓글 수가 몇개인지가 나타나 있는데 , 해당 span태그도 가져와서 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;++) 아직 로그인 처리를 안 해서 댓글을 쓴 사람의 이미지, 이름 들고오는 작업도 해야 함&lt;/p&gt;
&lt;p data-ke-size=&quot;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;ReplyController.java&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;//댓글 등록
@ResponseBody
@PostMapping(&quot;/regReply&quot;)
public ReplyVO regReplyAjax(ReplyVO replyVO) {
    //다음으로 들어갈 댓글 번호 조회
    String nextReplyNum = replyService.getNextReplyNum();
    //댓글 번호 세팅
    replyVO.setReplyNum(nextReplyNum);

    //댓글 등록
    replyService.regReply(replyVO);

    return replyService.getReplyByReplyNum(nextReplyNum);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;등록한 댓글을 바로 조회해서 반환해 주기 위해서(Ajax에서 받은 반환값으로 화면에 바로 댓글을 띄워줘야 하기 때문) 댓글 번호 조회를 따로 만듦&lt;/p&gt;
&lt;p data-ke-size=&quot;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;댓글 테이블 html&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;notice_detail.html&lt;/p&gt;
&lt;pre class=&quot;dust&quot;&gt;&lt;code&gt;&amp;lt;div class=&quot;row&quot;&amp;gt;
	&amp;lt;div class=&quot;col-12 mb-1&quot;&amp;gt;
		&amp;lt;span id=&quot;replyCntSpan&quot;&amp;gt;[[${notice.replyCnt}]]&amp;lt;/span&amp;gt;개의 댓글
	&amp;lt;/div&amp;gt;
	&amp;lt;div class=&quot;col-12&quot;&amp;gt;
		&amp;lt;table class=&quot;table table-borderless border-top border-bottom&quot; id=&quot;replyTable&quot;&amp;gt;
			&amp;lt;colgroup&amp;gt;
				&amp;lt;col width=&quot;5%&quot;&amp;gt;
				&amp;lt;col width=&quot;*&quot;&amp;gt;
			&amp;lt;/colgroup&amp;gt;

			&amp;lt;th:block th:if=&quot;${#lists.size(notice.replyList) == 0}&quot;&amp;gt;
				&amp;lt;tr class=&quot;border-top&quot; id=&quot;noReplyTr&quot;&amp;gt;
					&amp;lt;td class=&quot;text-secondary text-center align-middle&quot; colspan=&quot;2&quot; height=&quot;120px&quot;&amp;gt;
						등록된 댓글이 없습니다.
					&amp;lt;/td&amp;gt;
				&amp;lt;/tr&amp;gt;
			&amp;lt;/th:block&amp;gt;
			&amp;lt;th:block th:if=&quot;${#lists.size(notice.replyList) != 0}&quot;
						th:each=&quot;reply : ${notice.replyList}&quot;&amp;gt;
				&amp;lt;tr class=&quot;border-top&quot;&amp;gt;
					&amp;lt;td class=&quot;text-center&quot;&amp;gt;
						&amp;lt;img src=&quot;/img/content/board/testProfile.png&quot; width=&quot;100%&quot; class=&quot;mx-0&quot;&amp;gt;
					&amp;lt;/td&amp;gt;
					&amp;lt;td&amp;gt;
						&amp;lt;div class=&quot;d-flex justify-content-between&quot;&amp;gt;
							&amp;lt;div class=&quot;fw-semibold mb-1&quot;&amp;gt;[[${reply.ename}]]&amp;lt;/div&amp;gt;
							&amp;lt;div class=&quot;text-secondary fs-6&quot;&amp;gt;[[${reply.replyDate}]]&amp;lt;/div&amp;gt;
						&amp;lt;/div&amp;gt;
						&amp;lt;div th:utext=&quot;${reply.replyContent}&quot;&amp;gt;&amp;lt;/div&amp;gt;
						&amp;lt;div class=&quot;d-grid gap-1 d-md-flex justify-content-md-end&quot;&amp;gt;
							&amp;lt;input type=&quot;button&quot; class=&quot;btn&quot; th:onclick=&quot;updateReplyForm([[${reply.replyNum}]], this)&quot; value=&quot;수정&quot;&amp;gt;
							&amp;lt;input type=&quot;button&quot; class=&quot;btn&quot; th:onclick=&quot;deleteReply([[${reply.replyNum}]], this)&quot; value=&quot;삭제&quot;&amp;gt;
						&amp;lt;/div&amp;gt;
					&amp;lt;/td&amp;gt;
				&amp;lt;/tr&amp;gt;
			&amp;lt;/th:block&amp;gt;

			&amp;lt;tr class=&quot;border-top&quot; id=&quot;regReplyTr&quot;&amp;gt;
				&amp;lt;td colspan=&quot;2&quot;&amp;gt;
					&amp;lt;div class=&quot;input-group&quot;&amp;gt;
						&amp;lt;textarea class=&quot;form-control&quot; rows=&quot;5px&quot; style=&quot;resize: none&quot; id=&quot;replyTextarea&quot;&amp;gt;&amp;lt;/textarea&amp;gt;
						&amp;lt;input type=&quot;button&quot; class=&quot;btn&quot; th:onclick=&quot;regReply([[${notice.boardNum}]]);&quot; value=&quot;등록&quot;&amp;gt;
					&amp;lt;/div&amp;gt;
				&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
		&amp;lt;/table&amp;gt;
	&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>프로젝트</category>
      <author>하차모</author>
      <guid isPermaLink="true">https://hachamo.tistory.com/57</guid>
      <comments>https://hachamo.tistory.com/57#entry57comment</comments>
      <pubDate>Fri, 26 May 2023 00:36:12 +0900</pubDate>
    </item>
  </channel>
</rss>