<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>junbeomm-park.log</title>
        <link>https://velog.io/</link>
        <description>DB 엔지니어👍</description>
        <lastBuildDate>Mon, 17 Oct 2022 06:30:07 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>junbeomm-park.log</title>
            <url>https://images.velog.io/images/junbeomm-park/profile/778c44f6-e43b-481a-bcfe-2b7234d68e31/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. junbeomm-park.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/junbeomm-park" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[리눅스 (CentOS 7) 디스크 용량 증설하기]]></title>
            <link>https://velog.io/@junbeomm-park/%EB%A6%AC%EB%88%85%EC%8A%A4-CentOS-7-%EB%94%94%EC%8A%A4%ED%81%AC-%EC%9A%A9%EB%9F%89-%EC%A6%9D%EC%84%A4%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@junbeomm-park/%EB%A6%AC%EB%88%85%EC%8A%A4-CentOS-7-%EB%94%94%EC%8A%A4%ED%81%AC-%EC%9A%A9%EB%9F%89-%EC%A6%9D%EC%84%A4%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 17 Oct 2022 06:30:07 GMT</pubDate>
            <description><![CDATA[<h2 id="os-환경">OS 환경</h2>
<p>Server : VMware 16
OS : Linux CentOS 7</p>
<br>
<br>
<br>

<h2 id="volume-">Volume ?</h2>
<p>Physical Volume (물리적 볼륨) : /dev/sda1, /dev/sda2 등의 파티션
Volume Group (볼륨 그룹) : Physical Volume(물리적 볼륨)을 합쳐서 1개의 그룹으로 만드는 것
Logical Volume (논리적 볼륨) : Volume Group(볼륨 그룹)을 논리적으로 나눈 것</p>
<br>
<br>
<br>

<h2 id="확장-순서">확장 순서</h2>
<p>VMware Disk 용량 증설 -&gt; 물리 파티션 용량 추가 -&gt; 볼륨 그룹 용량 증설 -&gt; 논리 파티션 증설</p>
<br>
<br>
<br>

<h2 id="작업">작업</h2>
<p>root 폴더의 용량이 부족해 해당 폴더를 증설</p>
<h3 id="1-용량확인">1. 용량확인</h3>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/58941e4c-69b6-4cde-a81a-668c709327d1/image.PNG" alt=""></p>
<p><code>df -h .</code> 명령어를 활용해 디스크 사용량을 확인 할 수 있으며,
총 26GB 중 24GB를 사용 하고 있어 디스크 용량을 늘릴 필요가 있음</p>
<br>
<br>

<hr>
<h3 id="2-vmware-용량-증설-기존-30gb에서-200gb로-변경">2. VMware 용량 증설. 기존 30GB에서 200GB로 변경</h3>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/10454f4d-98c8-4b2c-b6fa-0633393fdd2d/image.png" alt=""></p>
<p>Edit virtural machine settings 클릭 후</p>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/45151ebe-4f94-4b25-86be-a364cf5c2d5a/image.png" alt="">
Expand 클릭</p>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/5f54a5d7-399d-4b95-90bc-c9b43872d896/image.PNG" alt=""></p>
<p>원하는 size 입력후 Expand 클릭</p>
<br>
<br>

<hr>
<h3 id="3-파티션-구성-확인">3. 파티션 구성 확인</h3>
<pre><code>[root@target ~]# lsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0  200G  0 disk 
├─sda1            8:1    0    1G  0 part /boot
└─sda2            8:2    0   25G  0 part 
  ├─centos-root 253:0    0   26G  0 lvm  /
  └─centos-swap 253:1    0    3G  0 lvm  [SWAP]
sr0              11:0    1  4.4G  0 rom  /run/media/admin/CentOS 7 x86_64</code></pre><ul>
<li><code>lsblk</code> 명령어로 전체 구성을 확인 할 수 있다. 총 200GB 중, 사용 중(할당)일 용량은 26GB로써 200GB로 정상적으로 추가 된 것을 확인</li>
</ul>
<br>
<br>

<hr>
<h3 id="4-growpart-설치">4. growpart 설치</h3>
<p><code>yum install cloud-utils-growpart</code></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/413c8749-8b0e-414a-b092-ad93f183eac5/image.PNG" alt=""></p>
<br>
<br>

<hr>
<h3 id="5-물리-볼륨물리-파티션-용량-추가">5. 물리 볼륨(물리 파티션) 용량 추가</h3>
<p><code>growpart /dev/sda 2</code></p>
<p>growpart 명령어를 통해 물리 파티션에 용량을 추가. root가 포함되어 있는 sda2 물리 파티션에 추가한다</p>
<pre><code>[root@target ~]# lsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0  200G  0 disk 
├─sda1            8:1    0    1G  0 part /boot
└─sda2            8:2    0  199G  0 part 
  ├─centos-root 253:0    0   26G  0 lvm  /
  └─centos-swap 253:1    0    3G  0 lvm  [SWAP]
sr0              11:0    1  4.4G  0 rom  /run/media/admin/CentOS 7 x86_64</code></pre><p>sda2 영역이 증설된 모습을 확인 할 수 있다. (25GB -&gt; 199GB)</p>
<br>
<br>


<hr>
<h3 id="6-볼륨-그룹-확인">6. 볼륨 그룹 확인</h3>
<p><code>pvresize /dev/sda2</code> = /dev/sda2 영역에 추가 되어있는 모든 용량을 파티션에 할당
<code>vgdisplay</code> = Volume Group 구성 확인</p>
<pre><code>[root@source ~]# pvresize /dev/sda2
  Physical volume &quot;/dev/sda2&quot; changed
  1 physical volume(s) resized or updated / 0 physical volume(s) not resized</code></pre><br>
물리 파티션에 추가한 173GB를 파티션에 할당


<p><br><br></p>
<pre><code>[root@source ~]# vgdisplay
  --- Volume group ---
  VG Name               centos
  System ID             
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  5
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                2
  Open LV               2
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               &lt;199.00 GiB
  PE Size               4.00 MiB
  Total PE              50943
  Alloc PE / Size       50943 / &lt;199.00 GiB
  Free  PE / Size       0 / 0   
  VG UUID               hBI25A-0Xjv-G3i7-hCng-5dp7-q7xg-PmgGQs
</code></pre><p><br><br></p>
<hr>
<h3 id="7-논리-볼륨논리-파티션-용량-확장">7. 논리 볼륨(논리 파티션) 용량 확장</h3>
<p><code>lvextend -r -l +100%FREE /dev/mapper/centos-root</code>
=+100%FREE &gt; 볼륨 그룹 내, 남아있는 모든 용량(100%)을 대상 경로에 전부 할당</p>
<pre><code>[root@source ~]# lvextend -r -l +100%FREE /dev/mapper/centos-root</code></pre><br>
<br>

<hr>
<h3 id="8-증설-확인">8. 증설 확인</h3>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/efcb615d-a69f-4489-91cf-e7a14413abd1/image.PNG" alt=""></p>
<p>정상적으로 증설이 잘 마무리된 모습</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Oracle Archive log Mode 설정 방법 with Linux]]></title>
            <link>https://velog.io/@junbeomm-park/Oracle-Archive-log-Mode-%EC%84%A4%EC%A0%95-%EB%B0%A9%EB%B2%95-with-Linux</link>
            <guid>https://velog.io/@junbeomm-park/Oracle-Archive-log-Mode-%EC%84%A4%EC%A0%95-%EB%B0%A9%EB%B2%95-with-Linux</guid>
            <pubDate>Thu, 22 Sep 2022 05:54:45 GMT</pubDate>
            <description><![CDATA[<h2 id="아카이브-모드-">아카이브 모드 ?</h2>
<p>Oracle DB에 접속을해 DML 및 DDL 등의 명령어로 작업을 수행하면, 모든 작업의 기록은 redo log 파일에 저장이된다.</p>
<p>작업의 양이 많아지면 redo log파일에 기록하는 내용도 굉장히 많아지게 된다. 그렇게 되면 데이터를 기록하기 위해서 redo log파일을 늘려야 하는 일이 발생 하기도 한다.</p>
<p>하지만 Oracle redo log 파일은 계속 증가하는 것이 아니라 몇개의 log 파일을 만들어 놓고 번갈아 가면서 기록하는 구조로 되어 있다.</p>
<p>이렇게 작업을 하게 되면 새로운 작업의 내용이 예전의 작업내용을 덮어 쓰므로 이전 작업의 내용을 잃게 된다는 단점이 있다 . </p>
<p>이러한 단점을 해결 하기 위한 방법이 redo log 파일의 내용을 다른 디렉터리에 자동으로 복사해서 저장하도록 운영하는 방법이다. 이렇게 운영하는 방법을 아카이브 로그 모드(Archive Log Mode) 이다.</p>
<p>Oracle 에서 Default로 No Archive Log Mode 이며, Archive Log Mode로 운영하기 위해서는 아래와 같이 설정을 진행 해야 한다.</p>
<br>
<br>
<br>

<hr>
<h2 id="테스트-환경">테스트 환경</h2>
<p>Server : VMware
OS : CentOS 7
DB : Oracle 19c ASM Single </p>
<p><br><br><br></p>
<h2 id="guide">Guide</h2>
<h4 id="1-현재-아카이브-모드-확인">1. 현재 아카이브 모드 확인</h4>
<pre><code class="language-java">SQL&gt; archive log list
Database log mode           No Archive Mode
Automatic archival           Disabled
Archive destination           USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence     76
Current log sequence           78
</code></pre>
<br>
<br>

<h4 id="2-아카이브-모드-변경">2. 아카이브 모드 변경</h4>
<pre><code class="language-java">SQL&gt; alter system set log_archive_dest=&#39;/u01/app/oracle/fast_recovery_area/ORCL/archivelog&#39; scope=spfile ;
Database altered.

SQL&gt; alter system set log_archive_format=&#39;%d_%t_%s_%r.dbf&#39; scope=spfile sid=&#39;*&#39;;
Database altered.</code></pre>
<ul>
<li>log_archive_dest 의 경로는 아카이브 로그를 저장 할 디렉터리의 경로를 지정 해주면 된다.</li>
</ul>
<br>
<br>

<pre><code class="language-sql">SQL&gt; shutdown immediate

Database closed.
Database dismounted.
ORACLE instance shut down.



SQL&gt; startup mount

ORACLE instance started.




SQL&gt; archive log list;

Database log mode           No Archive Mode
Automatic archival           Disabled
Archive destination           USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence     76
Current log sequence           78



SQL&gt; alter database archivelog;

Database altered.



SQL&gt; alter database open;

Database altered.



SQL&gt; archive log list;

Database log mode           Archive Mode
Automatic archival           Disabled
Archive destination           USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence     76
Current log sequence           78
</code></pre>
<br>
<br>

]]></description>
        </item>
        <item>
            <title><![CDATA[[Oracle] Oracle의 Table / Row Chaining / Row Migration]]></title>
            <link>https://velog.io/@junbeomm-park/Oracle-Oracle%EC%9D%98-Table-Row-Chaining-Row-Migration</link>
            <guid>https://velog.io/@junbeomm-park/Oracle-Oracle%EC%9D%98-Table-Row-Chaining-Row-Migration</guid>
            <pubDate>Thu, 25 Aug 2022 01:59:59 GMT</pubDate>
            <description><![CDATA[<h2 id="table-">Table ?</h2>
<p>테이블이란 , Row(행)과 Column(열)로 구성된 표 형식의 오브젝트로 데이터를 보관하는 역할을 함.
DB 내에 생성할 수 있는 테이블의 수는 제한이 없으며, 물리적인 제약이 없는 한 얼마든지 생성 할 수 있음.</p>
<br>
<br>
<br>

<h2 id="row-저장-방식-이란-">Row 저장 방식 이란 ?</h2>
<p>테이블의 Row는 테이블이 저장되는 테이블 스페이스를 구성하는 데이터 파일의 블록에 저장된다. 로우를 입력하는 처리(insert 문)를 수행하면, 블록의 데이터 저장 영역 중 밑단 부분 부터 데이터를 저장한다. 
일반적으로 여러 Row를 하나의 블록에 저장한다. 오라클은 로우 데이터를 데이터 저장영역이 가득찰 때까지 집어 넣지는 않는다. </p>
<br>
<br>
<br>

<h2 id="row-migration">Row Migration</h2>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/44691cf1-1516-478d-81c3-dbbd141316aa/image.png" alt=""></p>
<p>PCTFREE를 설정해블록에 빈 공간을 마련해두는 이유는 Update 문 수행 등으로 인해 데이터가 변경되 로우의 크기가 커질 수 있기 때문이다.
이때 데이터가 블록의빈 공간에 들어갈 수 없을정도로 커지면, &#39;Row Migration&#39;이 발생한다. Row Migration이 발생하면, 변경으로 인해 증가한 데이터 뿐만 아니라 전체 Row의 데이터가 다른 블록으로 복사 된다. 해당 Row의 위치를 갖고있는 인덱스 등의 모든 오브젝트를 변경해야하는 일이 생기므로 원래의 블록에 새로 복사된 위치의 Pointer를 남긴다.</p>
<br>
Row Migration이 발생한 Row의 데이터를 읽어오기 위해서는 'Row의 포인터가 저장되있는 블록'과 'Row의 데이터가 저장되있는 블록'을 둘 다읽어와야 한다.
 따라서 'Row Migration'이 발생하지 않은 블록'을 읽어올때 보다 성능이 저하 된다. 해결방안은, PCTFREE를 좀 더 크게 설정하고 Row Migration의 발생을 억제하는 것이다.


 <br>
 <br>
 <br>


<h2 id="row-chaining">Row Chaining</h2>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/3bfb9115-87af-4e1c-b21a-c6ff76239ed8/image.png" alt=""></p>
<p> Row Chaining이란, 입력할 Row의 데이터 크기가 블록의 데이터 저장 공간보다 클 때발생하는 현상이다. 데이터 크기가 블록의 데이터 저장공간 보다 클 때 한 Row를 여러개의 조각으로 분리하고 각 조각을 다른 블록에 저장한다.</p>
<h4 id="참고">참고</h4>
<p> <a href="https://devfunny.tistory.com/297">https://devfunny.tistory.com/297</a>
 <a href="https://blog.naver.com/itperson/220879812591">https://blog.naver.com/itperson/220879812591</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Linux에 Oracle19c 설치 방법 with VMware, CentOS]]></title>
            <link>https://velog.io/@junbeomm-park/Linux%EC%97%90-Oracle19c-%EC%84%A4%EC%B9%98-%EB%B0%A9%EB%B2%95-with-VMware-CentOS</link>
            <guid>https://velog.io/@junbeomm-park/Linux%EC%97%90-Oracle19c-%EC%84%A4%EC%B9%98-%EB%B0%A9%EB%B2%95-with-VMware-CentOS</guid>
            <pubDate>Tue, 23 Aug 2022 08:15:51 GMT</pubDate>
            <description><![CDATA[<h2 id="설치-환경">&lt; 설치 환경 &gt;</h2>
<ul>
<li>Server : VMware Workstation 16</li>
<li>OS : CenOS 7</li>
<li>Version : Oracle 19c</li>
</ul>
<h2 id="사전-준비-사항">&lt; 사전 준비 사항 &gt;</h2>
<ul>
<li><span style="color:skyblue">/etc/hosts</span> 파일 설정</li>
</ul>
<br>
기본

<pre><code class="language-sql">127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6</code></pre>
<br>

<p><code>vi /etc/hosts</code>  명령어 입력 후 <strong><span style="color:indianred">실제 서버의 IP주소와 hostsname을 반드시 등록!!</span></strong></p>
<pre><code class="language-sql">127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.142.144 source source.localdomain
</code></pre>
<p><br><br><br><br></p>
<ul>
<li>컴파일러를 비롯한 필수 시스템 SW 설치
(하나씩 설치하기 귀찮으니 yum update 명령어를 통해 전체 업데이트 함)</li>
</ul>
<pre><code class="language-sql">$ yum update</code></pre>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/17d2b8c9-ef27-49a5-8669-5dbf3a2c8710/image.PNG" alt="">
위 사진 처럼 나온다면 y 입력후 enter 누르고 설치 진행</p>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/ccb9edf7-1c05-487b-8ec0-3fc9500e6f18/image.PNG" alt=""></p>
<p>약 5분 정도 기다리면 완료</p>
<p><br><br><br><br></p>
<ul>
<li>커널파라미터 수정(<span style="color:skyblue">/etc/sysctl.conf</span>)</li>
</ul>
<pre><code>[root@localhost ~]# vi /etc/sysctl.conf
</code></pre><p>root 계정에서 vi /etc/sysctl.conf 명령어를 사용해 아래내용 추가</p>
<br>
<br>
<br>

<pre><code>fs.aio-max-nr = 1048576
fs.file-max = 6815744
kernel.shmall = 2097152
kernel.shmmax = 4294967295
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
net.ipv4.ip_local_port_range = 9000 65500
net.core.rmem_default = 262144
net.core.rmem_max = 4194304
net.core.wmem_default = 262144
net.core.wmem_max = 1048576

kernel.shmall = 8388608
kernel.shmmax = 34359738368

kernel.core_pattern = %e.%p.core</code></pre><br>
<br>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/43d63c49-f457-4336-bfed-f00b6869efad/image.PNG" alt=""></p>
<p>위 사진 처럼 등록 후 :wq! 로 저장</p>
<br>
<br>

<p>변경내용 적용 
<strong><span style="color:indianred">/etc/sysctl.conf에 내용이 변경되었으면 꼭   적용 시켜줘야함 !!!</span></strong></p>
<pre><code>[root@localhost ~]# sysctl -p
</code></pre><p><img src="https://velog.velcdn.com/images/junbeomm-park/post/527bc88d-1b8c-41f9-b6fe-73f19eb4fb4e/image.PNG" alt=""></p>
<br>
<br>
<br>
<br>

<ul>
<li>swap 공간 확보</li>
</ul>
<p>모든 운영체제는 디스크에 swap 공간을 사용하도록 되어있다.
리눅스의 경우 운영체제 설정 시 swap 영역으로 사용하기 위한 스왑파티션을 만든다.
-&gt; 이공간이 최소 <span style="color:indianred">2G byte</span> 이상 되어야함</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/96532d8c-be64-409a-ad8d-cbcaa6c0b9bd/image.PNG" alt=""></p>
<p>공간이 충분하므로 PASS</p>
<br>
<br>
<br>
<br>

<hr>
<br>
<br>

<h2 id="oracle-다운로드-및-설치">Oracle 다운로드 및 설치</h2>
<p><a href="https://www.oracle.com/database/technologies/oracle-database-software-downloads.html">https://www.oracle.com/database/technologies/oracle-database-software-downloads.html</a></p>
<p>위 링크에서 19c 리눅스 버전으로 다운로드</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/557a8536-2494-49ef-9bd0-c9d371261266/image.png" alt=""></p>
<p>설치할때 로그인은 필수 이므로 회원가입이 안되었다면 회원가입후 진행</p>
<br>
<br>
<br>

<h3 id="1-리눅스-환경설정">1. 리눅스 환경설정</h3>
<p>1-1) 종속성 패키지 설치
<br></p>
<p>계정 : root</p>
<pre><code>yum -y install compat-libcap1
yum -y install compat-libstdc++-33
yum -y install libstdc++-devel
yum -y install gcc 
yum -y install gcc-c++
yum -y install ksh
yum -y install libaio-devel</code></pre><p>※ 오라클 설치에 반드시 필요한 패키지이므로 <span style="color:skyblue">오라클 설치전에 미리 설치</span>함.</p>
<br>
<br>
<br>
1-2) 오라클 관리 그룹/계정 생성

<pre><code>[root@localhost /]# groupadd -g 1200 dba
[root@localhost /]# useradd -g dba -u 1200 ora19c
[root@localhost /]# passwd ora19c
//GID 1200 dba 그룹생성, UID 1200 ora19c 계정 생성, ora19c 패스워드 설정

[root@localhost /]# mkdir -p /app/ora19c
[root@localhost /]# chown -R ora19c.dba /app
[root@localhost /]# chmod -R 755 /app
// /app/ora19c 디렉토리 생성 및 소유자 : ora19c, 소유그룹 : dba, 권한 drxr-xr-x 설정</code></pre><ul>
<li>WinSCP로 다운로드 받은 zip 파일 전송하기</li>
</ul>
<br>
<br>
<br>
1-3) 리눅스 설정

<ul>
<li><span style="color:skyblue">/etc/security/limits.conf</span> 수정</li>
</ul>
<pre><code>[root@localhost ~]# vi /etc/security/limits.conf </code></pre><pre><code>...//아래 내용 추가

#oracle setup
ora19c soft nproc 2047
ora19c hard nproc 16384
ora19c soft nofile 1024
ora19c hard nofile 65536
ora19c soft stack 10240
ora19c hard stack 20480</code></pre><br>
<br>
<br>

<ul>
<li>selinex 사용 정지<pre><code>[root@localhost ~]# vi /etc/sysconfig/selinux </code></pre></li>
</ul>
<pre><code>...//변경
SELINEX=disabled
...</code></pre><br>
<br>
<br>

<ul>
<li>방화벽 정지</li>
</ul>
<pre><code>[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# systemctl disable firewalld
</code></pre><br>
<br>
<br>

<p>1-4) 오라클 계정 생성</p>
<p>생성해주었던 <span style="color:skyblue">ora19c</span> 계정으로 로그인해 <span style="color:skyblue">~/.bash_profile</span> 에 내용 추가</p>
<pre><code>[ora19c@localhost ~]$ vi ~/.bash_profile
</code></pre><pre><code>#oracle setup
export ORACLE_HOSTNAME=source
export TMP=/tmp
export TMPDIR=$TMP export ORACLE_OWNER=ora19c
export ORACLE_BASE=/app
export ORACLE_HOME=/app
export PATH=$PATH:$ORACLE_HOME/bin:$ORACLE_HOME:/usr/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib:/lib:/usr/lib
export ORACLE_SID=source
export NLS_LANG=AMERICAN_AMERICA.KO16MSWIN949
export ORACLE_TERM=xterm
export TNS_ADMIN=$ORACLE_HOME/network/admin
export CLASSPATH=$ORACLE_HOME/JRE:$ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib
export EDITOR=vi
 if [ $USER = &quot;ora19c&quot; ]; then
   if [ $SHELL = &quot;/bin/ksh&quot; ]; then
        ulimit -p 16384
        ulimit -n 65536
   else
        ulimit -u 16384 -n 65536
   fi
 fi</code></pre><br>
<br>
<br>
<br>

<h3 id="2-설치과정">2. 설치과정</h3>
<p>1) 다운로드 받은 oracle19c를 WinSCP 프로그램을 활용해 VMware 서버로 옮기기</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/7978000b-18c9-4490-9bec-ac2b7a96c6e1/image.PNG" alt=""></p>
<p>호스트 이름에 IP를 입력하고 리눅스 OS 계정과 비밀번호를 입력후 로그인 </p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/c94d0259-6e23-415d-8b8b-7d2fbfe1a98a/image.PNG" alt=""></p>
<p>/app 경로로 다운로드 받은 zip 파일을 옮겨줌</p>
<br>
<br>
<br>

<p>2) unzip을 사용해 다운로드 받은 파일을 풀어줌</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/4e3b105d-5bc0-4b32-9025-97819185f0a9/image.PNG" alt=""></p>
<br>
<br>
<br>

<p>3) xhost 등록</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/3f89a47e-95f1-48d0-9283-ace486d6b7c9/image.PNG" alt="">
root 계정에서 <code>xhost +</code> 명령어 입력 </p>
<br>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/c6782809-321c-462a-a3fd-7dd73a51969e/image.PNG" alt=""></p>
<p>다시 ora19c 계정으로 와서 <code>export DISPLAY=:0</code> 입력 후 설치한 경로로 이동후 <code>./runInstaller</code> 입력</p>
<br>
<br>
<br>

<p>4) install</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/b3fadb6f-e2b2-45cd-9763-0c33c53bf610/image.PNG" alt=""></p>
<p>다음 클릭</p>
<p><br><br></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/b0e7ead8-6528-4450-b444-3cba08347ea3/image.PNG" alt=""></p>
<p>다음 클릭</p>
<p><br><br></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/ef269da8-a61b-462d-b633-77759081be2c/image.PNG" alt=""></p>
<p>전역 데이터베이스 이름(OracleSID) 설정 후 비밀번호 입력</p>
<p><br><br></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/68fb6e9e-aeb6-4ada-8479-ab884bb18117/image.PNG" alt="">
예 클릭</p>
<p><br><br></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/4e8f56c8-f770-46f2-abbf-327c9d17ba59/image.PNG" alt=""></p>
<p>자동으로 구성 스크립트 실행 체크 후 root 계정 비밀번호 입력</p>
<p><br><br></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/e77d2b9e-fb94-41b5-b3dc-f344756a9885/image.PNG" alt=""></p>
<p>모두 무시 체크 후 다음</p>
<p><br><br></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/7ecd826a-4c00-483b-95bf-b7c7bcfaad71/image.PNG" alt=""></p>
<p>설치 클릭</p>
<p><br><br></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/306447e8-de4f-4f2c-bdcb-9c9709220d62/image.PNG" alt=""></p>
<p>예 클릭</p>
<p><br><br><br><br></p>
<h3 id="3-오라클-실행">3. 오라클 실행</h3>
<ul>
<li><span style="color:skyblue">sqlplus / as sysdba</span> 실행</li>
</ul>
<pre><code>[ora19c@localhost dbs]$ sqlplus / as sysdba
</code></pre><p><img src="https://velog.velcdn.com/images/junbeomm-park/post/37a779b9-bef1-42c0-b64b-5458dfd3ba69/image.PNG" alt=""></p>
<p><code>select status from v$instance</code> 입력후 status 값이 위 사진처럼 OPEN 상태면 설치완료</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[KOSTA] Spring 기반 Cloud 서비스 개발자 양성 과정 76 일차 - Spring, RESTful]]></title>
            <link>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-76-%EC%9D%BC%EC%B0%A8-Spring-RESTful</link>
            <guid>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-76-%EC%9D%BC%EC%B0%A8-Spring-RESTful</guid>
            <pubDate>Tue, 24 May 2022 06:43:28 GMT</pubDate>
            <description><![CDATA[<h1 id="📖-학습-내용">📖 학습 내용</h1>
<ol>
<li>REST</li>
<li>@RestController</li>
<li>@PathVariable</li>
<li>@RequestBody</li>
<li>댓글 처리</li>
</ol>
<h2 id="span-stylecolorlightcoral1-restspan"><span style="color:LightCoral">1. REST</span></h2>
<p>Representational state transfer의 약자로서 하나의 URI는 하나의 고유한 리소스(Resource)를 대표하도록 설계 되는 개념에 전송방식을 결합한 것</p>
<ul>
<li>URI &gt; URL 개념으로 URI는 현실, 구체적이며 URL은 상대적으로 상징적 의미를 지님</li>
<li>HTTP Method (GET,POST,PUT,PATCH, DELETE 등)으로 나타냄</li>
</ul>
<br>

<h2 id="span-stylecolorlightcoral2-restcontrollerspan"><span style="color:LightCoral">2. @RestController</span></h2>
<p><span style="color:orange"><strong>문자열 반환</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/f2882a7d-07f0-4720-82ab-9c660f35604c/image.PNG" alt=""></p>
<ul>
<li>produces 속성은 해당 메소드가 생산하는 MIME 타입을 의미</li>
<li>문자열로 직접 지정 혹은 메소드 내의 MediaType을 이용할 수 있음</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/cbf5f3a3-f35e-40ac-b379-6a1eb539da2e/image.PNG" alt=""></p>
<ul>
<li>ContextType이 produces 속성값에 의해 나타낸 것을 볼 수 있음</li>
</ul>
<br>

<p><span style="color:orange"><strong>객체 반환</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/6b269af8-d1ff-48d3-83e3-55873c97e8a6/image.PNG" alt=""></p>
<ul>
<li>객체를 반환하는 작업은 JSON이나 XML을 이용</li>
<li>@AllArgsConstructor는 모든 속성을 사용하는 생성자를 만드는 어노테이션</li>
<li>@NoArgsConstructor는 비어 있는 생성자(기본생성자) 를 만드는 어노테이션</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/d83c6450-cf1f-44bd-84b2-77aae700ecca/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/bb6b411a-21ef-4319-878f-807cc3ee6546/image.PNG" alt=""></p>
<ul>
<li>SampleVO 객체를 JSON 형식으로 반환 </li>
</ul>
<br>

<p><span style="color:orange"><strong>컬렉션 타입</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/80cd8ed2-0452-4c41-acc3-8fbd54977984/image.PNG" alt=""></p>
<ul>
<li>컬렉션 타입으로 객체를 반환</li>
<li>1 ~ 10 까지 반복하여 출력</li>
<li>기본 출력은 XML 형식, .json을 출력하면  JSON 형식으로 출력</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/5c657080-3c9e-4dbb-858b-1b7c30cd56ca/image.PNG" alt=""></p>
<ul>
<li>/sample/getList 로 기본 출력</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/e5ffb671-cff2-437d-8174-24fa5ff9729b/image.PNG" alt=""></p>
<ul>
<li>/sample/getList.json 으로 JSON 형식으로 출력</li>
</ul>
<br>

<p><span style="color:orange"><strong>ResponseEntity</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/19446cc1-f713-4a5c-b3ad-fc33732e007b/image.PNG" alt=""></p>
<ul>
<li>데이터와 함께 HTTP 헤더의 상태 메시지도 같이 전달</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/35ff1311-eeca-477b-b23c-7e89e1151a67/image.PNG" alt=""></p>
<ul>
<li>주소창에 param으로 준 값을 입력</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/338709e9-a9a9-4d23-b198-8bac5eed7095/image.PNG" alt=""></p>
<ul>
<li>if문의 조건에 따라 height 값이 150 이하로 입력 하면 상태코드는 502</li>
</ul>
<br>

<h2 id="span-stylecolorlightcoral3-pathvariablespan"><span style="color:LightCoral">3. @PathVariable</span></h2>
<p>REST 방식에서 자주 사용 됨
URL 경로의 일부를 파라미터로 사용할 때 이용</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/27f93d20-7b5e-4a15-ab99-2b9dc9571869/image.PNG" alt=""></p>
<ul>
<li>@PathVariable 어노테이션을 파라미터 안에 넣는다.</li>
<li>return시 배열을 생성</li>
<li>어노테이션 변수명은 GetMapping 에서 {}에 선언한 변수명과 일치 해야 한다.</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/b230ad0f-63d3-42b3-a1d2-c09d5d333f3e/image.PNG" alt=""></p>
<ul>
<li>URL에 cat, pid 값을 작성</li>
</ul>
<br>

<h2 id="span-stylecolorlightcoral4-requestbodyspan"><span style="color:LightCoral">4. @RequestBody</span></h2>
<p>JSON 데이터를 원하는 타입의 객체로 변환해야 할 때 사용
요청 내용을 이용하여 해당 파라미터 타입으로 변환을 요구</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/c8b79550-920f-4c17-95e1-b7c93cce5ff1/image.PNG" alt=""></p>
<ul>
<li>요청(request)한 내용을 처리해야 하기 때문에 @PostMapping 선언</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/02196270-641d-454f-83b4-f5ad541d6486/image.PNG" alt=""></p>
<ul>
<li>postman 프로그램으로 테스트</li>
<li>ticket 객체에 값을 넣지 않아 빈객체가 나오지만 에러는 발생하지 않음</li>
</ul>
<br>

<h2 id="span-stylecolorlightcoral5-댓글-처리span"><span style="color:LightCoral">5. 댓글 처리</span></h2>
<p>RESTful 방식, Ajax를 이용해 댓글 처리</p>
<p><span style="color:orange"><strong>영속 영역</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/1dbe6cb5-fab0-40d8-be4f-3eb93c086c1b/image.PNG" alt=""></p>
<ul>
<li>sqldeveloper 로 댓글 처리를 위한 tbl_reply 테이블 생성</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/314c86e1-2383-4d58-87d9-d6e992635d30/image.PNG" alt=""></p>
<ul>
<li>도메인 객체(ReplyVO) 생성</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/6001bafd-0bea-47c2-9586-f48048c38f19/image.PNG" alt=""></p>
<ul>
<li>Mapper 인터페이스 생성</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/1823c6a4-c792-40f3-b6e3-f3fa4e3140e7/image.PNG" alt=""></p>
<ul>
<li>쿼리문 작성을 위한 XML 생성 후 namespace 설정(Mapping)</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/290a10b6-43f3-4aaf-873f-9121471b0840/image.PNG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/c73b318a-e15f-4fa6-a58b-d574bc8552b4/image.PNG" alt=""></p>
<ul>
<li>JUnit Test를 통해 ReplyMapper 객체가 정상 적으로 Mapping 되었는지 확인</li>
</ul>
<br>

<p><span style="color:orange"><strong>Create Test</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/c45e5ef3-4a4c-4179-a02b-bf8e2b72cd37/image.PNG" alt=""></p>
<ul>
<li>ReplyMapper 인터페이스에 insert 메소드 등록</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/8dce56df-0df4-4ee8-a1d6-1f20762abadb/image.PNG" alt=""></p>
<ul>
<li>XML에 insert 쿼리문 작성</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/1afa9983-0284-4418-b2f5-ec343a9726e0/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/ba64cc01-dd49-429c-b7d7-d76f411ef7c2/image.PNG" alt=""></p>
<ul>
<li>Test를 통해 insert문이 제대로 작동 하는지 확인</li>
</ul>
<br>

<p><span style="color:orange"><strong>Read Test</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/89219fdb-0cc0-4431-9194-ec5146a6286b/image.PNG" alt=""></p>
<ul>
<li>ReplyMapper 인터페이스에 read 메소드 등록</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/d791f0f8-c405-421c-b6cf-504b52bb15a7/image.PNG" alt=""></p>
<ul>
<li>XML에 Read하기 위한 select 문 작성</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/d4c256e4-c05e-454f-8a37-8cf93e67b023/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/51670dfb-64e1-406c-81b5-64447e07a5e4/image.PNG" alt=""></p>
<ul>
<li>Test를 통해 select 문이 정상적으로 작동하는지 확인</li>
</ul>
<br>

<p><span style="color:orange"><strong>Update Test</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/290377b9-c70d-49ea-bc25-5eafac34ad33/image.PNG" alt=""></p>
<ul>
<li>ReplayMapper 인터페이스에 update 메소드 등록</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/53592a1e-0691-4b3c-b5cb-ed2987943c27/image.PNG" alt=""></p>
<ul>
<li>update를 위한 쿼리문 작성</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/c6f4132f-72d2-4f72-9b07-f596d94f954f/image.PNG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/26cfbb7d-4152-4838-82b1-8e66a66220de/image.PNG" alt=""></p>
<ul>
<li>Test를 통해 update문이 정상적으로 작동하는지 확인</li>
</ul>
<br>

<p><span style="color:orange"><strong>Delete Test</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/d747283c-214e-46a4-b641-960f2c6b248c/image.PNG" alt=""></p>
<ul>
<li>ReplyMapper 인터페이스에 delete 메소드 등록</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/da793c8e-f18e-442b-bbee-003e08371eb5/image.PNG" alt=""></p>
<ul>
<li>delete를 위한 쿼리문 작성</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/b1e52a62-ef4e-4624-a1eb-6dc25820d3b0/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/5e278c59-ac8d-481a-a5b6-91cc52fea9f6/image.PNG" alt=""></p>
<ul>
<li>Test를 통해 delete문이 정상적으로 작동하는지 확인</li>
</ul>
<br>

<p><span style="color:orange"><strong>Service</strong></span></p>
<p>Service의 로직은 위 방식과 동일하기 때문에 메소드별 설명은 생략</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/53e28635-d070-433e-9978-a7129c358fff/image.PNG" alt=""></p>
<ul>
<li>ReplyService 인터페이스에 각 메소드 등록</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/f2dfc043-d0f6-404a-9ea2-fa600e6dc276/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/c5dec0ba-b075-40b0-9bb1-201c6e80457c/image.PNG" alt=""></p>
<ul>
<li>ReplyServiceImpl은 ReplyService를 상속받아 각 메소드를 오버라이딩 한후 mapper 메소드를 return</li>
</ul>
<br>

<p><span style="color:orange"><strong>Controller - insert</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/e47a59fb-6b4c-4f2a-88ae-8efb80ed74fe/image.PNG" alt=""></p>
<ul>
<li>@RequestMapping을 사용해 /replies/로 상위 경로 설정</li>
<li>REST 방식으로 구현 하기 위해 @RestController 어노테이션 선언</li>
<li>insert시 consumes 와 produces를 이용하여 JSON 방식의 데이터만 처리 및 문자열만 반환</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/6b6175ab-62ab-45b5-be0e-bdd681eb03ad/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/768cac6f-ba71-4e17-af2a-74db61844a90/image.PNG" alt=""></p>
<ul>
<li>postman 프로그램을 활용해 post 요청 후 정상적으로 작동 되는 것을 DB에서 확인</li>
</ul>
<br>

<p><span style="color:orange"><strong>Controller - read</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/a36ea07a-9776-43e9-8ac2-6c263d5be931/image.PNG" alt=""></p>
<ul>
<li>@PathVariable을 사용해 bno, page를 URL로 표시</li>
<li>Criteria 객체를 생성하여 페이지 번호를 @PathVariable에서 입력</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/c8cee9fc-5218-4b6c-b61a-80e4922a4317/image.PNG" alt=""></p>
<ul>
<li>URL에 입력한 값이 출력</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/1987228b-44c8-4e88-8c6e-ad6ca625f1fb/image.PNG" alt=""></p>
<ul>
<li>rno를 @PathVariable로 입력하여 댓글 조회</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/c4ce30bb-f9b7-4a8a-81c5-d76c0186760b/image.PNG" alt=""></p>
<ul>
<li>댓글 번호에 따른 조회 결과</li>
</ul>
<br>

<p><span style="color:orange"><strong>Controller - update</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/18e1f6c9-069d-413c-bc5e-493e7a094a2c/image.PNG" alt=""></p>
<ul>
<li><p>수정할 값을 받기 때문에 request 객체를 이용하여 작성</p>
</li>
<li><p>Method는 PUT과 PATCH를 이용하여 수정
PUT : 해당 자원의 전체를 변경
PATCH : 일부를 변경</p>
</li>
<li><p>RequestBody를 이용하여 들어온 요청에 대하여 JSON 방식으로 받음</p>
</li>
<li><p>VO에 rno를 담고 수정 되면 success, 실패시 error</p>
</li>
</ul>
<br>


<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/84bbed28-3251-47ed-82b3-d276535caf35/image.PNG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/768b0c70-5320-41fc-ae95-26e1581ed48c/image.PNG" alt=""></p>
<ul>
<li>PATCH 방식으로 요청 하면 값이 수정된 것을 확인 할 수 있다.</li>
</ul>
<br>

<p><span style="color:orange"><strong>Controller - delete</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/457e9c33-7acf-438c-9c73-280791382d65/image.PNG" alt=""></p>
<ul>
<li>@DeleteMapping 으로 선언하여 DELETE 방식으로 요청오면 해당 rno는 삭제 되고 성공 하면 success 실패시 error를 리턴 한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[KOSTA] Spring 기반 Cloud 서비스 개발자 양성 과정 75일차 - Spring, Oracle DB Hint, Paging, Search]]></title>
            <link>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-75%EC%9D%BC%EC%B0%A8-Spring-Oracle-DB-Hint-Paging-Search</link>
            <guid>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-75%EC%9D%BC%EC%B0%A8-Spring-Oracle-DB-Hint-Paging-Search</guid>
            <pubDate>Mon, 23 May 2022 00:31:43 GMT</pubDate>
            <description><![CDATA[<h1 id="📖-학습내용">📖 학습내용</h1>
<ol>
<li>Oracle DB Hint</li>
<li>Paging</li>
<li>검색기능</li>
</ol>
<h2 id="span-stylecolorlightcoral1-oracle-db-hintspan"><span style="color:LightCoral">1. Oracle DB Hint</span></h2>
<p>Select 문을 실행할 때 힌트(hint)를 사용하여 개발자가 실행 조건을 걸어주는 것</p>
<ul>
<li>힌트 구문에서 에러가 발생하여도 SQL 실행에 지장을 주지 않는다.</li>
<li>Order By 절의 FullScan하는 단점을 극복할 수 있다.</li>
<li>INDEX_ASC or DESC (테이블명 PK)를 사용하여 정렬을 생략</li>
<li>FULL(테이블명)으로 FullScanning 가능</li>
</ul>
<br>

<p><span style="color:orange"><strong>Order By</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/5b29ea62-23ab-42c8-96c7-8ad38a7f94c0/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/1a6eb41e-03b1-4cdf-90f3-baf075e611de/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/4e74a4d2-f911-4720-9180-81f81eb46fcd/image.PNG" alt=""></p>
<ul>
<li>order by 정렬은 데이터가 많은 경우 엄청난 성능의 저하를 가져오기 때문에 데이터가 적거나, 정렬을 빠르게 하는 방법이 있지 않으면 지양한다.</li>
<li>계획 설명에서 보이듯 테이블을 FULL로 scan 한 것을 볼 수 있다.</li>
</ul>
<br>

<p><span style="color:orange"><strong>Hint(INDEXT 사용)</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/bade9a22-c7ec-40ed-9e25-24fea3e7635f/image.PNG" alt=""></p>
<p><strong><code>/*+ INDEX_DESC(테이블명 제약조건명) */</code></strong></p>
<ul>
<li>힌트를 적용하려면 <code>/*+  */</code> 와 같은 키워드 안에 작성하여 적용해야 한다.</li>
<li>order by를 사용했을 때와 다르게 sort를 하지 않았고 제약조건을 사용하여 Range Scan을 했다.</li>
<li>힌트에서 자동으로 정렬을 해줘 order by 절로 정렬 하지않아도 정렬이 되어 있다.</li>
</ul>
<br>

<p><span style="color:orange"><strong>ROWNUM</strong></span></p>
<p>SQL이 실행된 결과에 넘버링을 해주는 역할
모든 SELECT문에 사용 가능</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/aaf2926e-de5a-483e-badf-02e21547f4ad/image.PNG" alt=""></p>
<ul>
<li>ROWNUM을 선언하여 나오는 결과의 순서를 매긴다.</li>
<li>테이블에 존재하는 것이 아니라 가져온 데이터를 이용하여 순서를 매긴다.</li>
<li>위 예제는 Full Scan을 하면서 정렬이 되지 않았을 때 ROWNUM을 매기고 차후에 정렬이 되기 때문에 뒤죽박죽 상태란 것을 알 수 있다.</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/e2c82e31-2974-4cd2-8cd1-0e41d5949360/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/462c3d93-0dd3-4853-8dbd-5280b09b5e18/image.PNG" alt=""></p>
<ul>
<li>Hint에 INDEX를 사용하여 기본 정렬 상태에서 ROWNUM을 적용한다면 순서에 맞게 매겨진다.</li>
<li>실행 계획에도 Full Scan이 아닌 Range Scan임을 확인 할 수 있다.</li>
</ul>
<br>

<p><span style="color:orange"><strong>인라인 뷰(in-line view)</strong></span></p>
<p>페이징 처리하기 위해 인라인뷰로 처리해야만 문제가 발생하지 않는다.</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/9bc143c8-3594-48c0-b03e-3554c64a32fd/image.PNG" alt=""></p>
<ul>
<li>위와 같이 ROWNUM이 높은 순서대로 출력 된다.</li>
<li>이 때 2페이지부분을 구하기 위해 다시 쿼리문을 작성한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/5904f313-4bec-4404-b995-a14a904fdafb/image.PNG" alt=""></p>
<ul>
<li>에러는 나오지 않지만 아무런 결과가 나오지 않는다.</li>
<li>그 이유는 ROWNUM은 새로운 데이터를 가져오는 순간 1로 시작되어 어떠한 조건이 1보다 큰 경우를 만족을 못하면 결과가 없게 된다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/84f77f57-83a6-4d6d-bc02-04b5f991ad41/image.PNG" alt=""></p>
<ul>
<li>위와 같이 FROM절에 인라인뷰를 이용하여 SELECT 문에는 ROWNUM의 총 갯수를 정해주고 정한 RN의 조건을 설정해 조건에 해당되는 데이터가 출력하게 쿼리문을 작성한다.</li>
</ul>
<br>

<h2 id="span-stylecolorlightcoral2-pagingspan"><span style="color:LightCoral">2. Paging</span></h2>
<p>게시판의 기본 구조인 페이징 처리를 Mybatis 와 Spring을 활용해 구현</p>
<p><span style="color:orange"><strong>Mapper Test</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/e9a25d36-0cff-4a70-97e9-4d414bbcb415/image.PNG" alt=""></p>
<ul>
<li>페이징 처리를 위해 페이지 번호, 한 페이지의 글 갯수를 나타내 줘야 하기 때문에 객체를 생성</li>
<li>생성자를 생성해 각각의 파라미터 값을 선언</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/66ee2aeb-7dcc-4ae2-8669-513af081da16/image.PNG" alt=""></p>
<ul>
<li>해당 도메인 객체를 가지는 BoardMapper 인터페이스에 메소드 등록</li>
<li>VO객체를 사용하기 위해 List로 담아 선언</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/2a43284e-c7d4-484d-96dd-57a03e985bbb/image.PNG" alt=""></p>
<ul>
<li>인라인 뷰를 적용한 쿼리문 작성</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/50a9fe4f-f6d7-40b0-8b4c-8334e31d03f3/image.PNG" alt=""></p>
<ul>
<li>3페이지에 해당 되는 10개의 글을 출력하는 Test</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/f35ac9ce-980f-4b4a-ae2a-7eebeec12854/image.PNG" alt=""></p>
<ul>
<li>10개 글 출력</li>
</ul>
<br>

<p><span style="color:orange"><strong>Service Test</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/e7246d17-05f0-4edb-93d9-ef8618939f40/image.PNG" alt=""></p>
<ul>
<li>기존 getList() 메소드를 페이징 처리를 위해 Criterita 객체를 파라미터에 선언</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/381e6e8e-d479-460e-b4fa-a590aec8893a/image.PNG" alt=""></p>
<ul>
<li>ServiceImpl 에서 또한 기존 getList() 메소드를 페이징 처리를 위해 Criteria 객체를 파라미터에 선언후 BoardMapper에 선언한 getListWithPaging 메소드 호출</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/d0859023-2f72-4de4-870a-51be1afe5be5/image.PNG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/6b478d67-a83c-4173-9ce9-4f81f1830f81/image.PNG" alt=""></p>
<ul>
<li>Serivce Test 또한 출력이 잘되는 것을 확인 할 수 있다.</li>
</ul>
<br>

<p><span style="color:orange"><strong>Controller Test</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/09ecd9f4-74e9-4d4b-a0fd-ea8e9dd9ff65/image.PNG" alt=""></p>
<ul>
<li>Service Test 까지 했으면, Web View와 직접적인 관련이 있는 Controller Test까지 진행한다.</li>
<li>페이징 처리 된 list를 호출 하기 위해 Criteria 파라미터를 선언하고 model 객체로 메소드를 담는다.</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/ccb6cba6-e85e-48d0-a8dc-c3547e343b40/image.PNG" alt=""></p>
<ul>
<li>get 방식으로 /board/list 까지 가져간다</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/8cbf8103-a5a8-4344-9e56-ac58d40f0b89/image.PNG" alt=""></p>
<ul>
<li>Controller 또한 에러 없이 Test가 됬다.</li>
</ul>
<br>

<p><span style="color:orange"><strong>페이징 처리</strong></span></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/06d6995b-abdf-4de7-82f9-9ada939bc3bc/image.PNG" alt=""></p>
<ul>
<li>페이징 처리를 위해 PageDTO 도메인 객체를 생성 한다.</li>
<li>PageDTO에 기존에 만들었던 객체인 Criteria를 선언하여 페이지 관련된 값을 넘겨 받고, total을 선언하여 총 데이터 수를 입력한다.</li>
<li>파라미터 값을 넣어 연산이 가능한 로직을 작성한다.</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/7f28d7f0-f87b-4704-b828-320950497fd9/image.PNG" alt=""></p>
<ul>
<li>list에 Criteria 객체를 생성하고 Model객체를 생성하여 데이터를 담는다</li>
<li>PageDTO를 선언하여 파라미터 값에 값을 선언후 pageMaker에 담는다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/0031c2a0-f9c9-4d43-8c32-006df8b96885/image.PNG" alt=""></p>
<ul>
<li>Model 객체로 pageMaker에 보낸 데이터를 el태그를 통해 페이지 뷰에 작성</li>
<li>이전, 현재, 다음 페이지의 el태그 선언</li>
</ul>
<br>

<p><strong>결과화면</strong>
<img src="https://velog.velcdn.com/images/junbeomm-park/post/6c104495-f537-4ce6-9496-eb170406c6d9/image.PNG" alt=""></p>
<br>

<h2 id="span-stylecolorlightcoral3-검색기능span"><span style="color:LightCoral">3. 검색기능</span></h2>
<p>Select문을 활용해 검색기능과 화면처리</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/380d5a37-ae24-43f9-9886-5bce35a657b3/image.PNG" alt=""></p>
<ul>
<li>페이징 처리에 검색 조건이 들어가면서 Criteria 객체에 type, keyword 변수가 추가 되고 삼항연산자를 사용하여 null이면 배열을 만들고 아니면 split을 이용해 각 타입을 분리한다.</li>
</ul>
<br>




<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/523af35d-d9a2-4ea5-bfcf-3442aea84680/image.PNG" alt=""></p>
<ul>
<li>위와 같이 작성하고 prefixOverrides를 사용해 맨 앞에온 OR은 지우고 괄호와 AND를 prefix와 suffix로 나타낸다.</li>
<li>Criteria 객체에서 생성한 TypeArr의 type을 foreach를 통해 반복</li>
<li>choose when 구문으로 조건별 LIKE를 선언해 키워드 입력 시 OR을 이용하여 구문을 생성</li>
</ul>
<br>


<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/a22768f7-92e5-4683-bcc9-f7347dbe345d/image.PNG" alt=""></p>
<ul>
<li>뷰 페이지에서 select option 태그를 사용해 pageMaker의 cri 객체의 type이 각 검색할 내용들이라면 selected 하고 아니면 공백을 둔다</li>
<li>keyword를 입력하는 input 태그를 추가한다.</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/23f86069-f55a-4bf4-b614-7eda2a696794/image.PNG" alt=""></p>
<ul>
<li>검색 이후 페이지를 이동해도 동일한 검색 list가 출력되어야 하기 때문에 hidden으로 type과 keyword 선언</li>
</ul>
<br>

<p><strong>결과화면</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/2cb2c2c9-c045-4090-be0f-291e4f4fc80f/image.PNG" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[KOSTA] Spring 기반 Cloud 서비스 개발자 양성 과정 74 일차 - MVC CRUD Test]]></title>
            <link>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-74-%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-74-%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Thu, 19 May 2022 16:12:40 GMT</pubDate>
            <description><![CDATA[<h1 id="📖-학습내용">📖 학습내용</h1>
<ol>
<li>MVC CRUD Mapper Test</li>
<li>MVC CRUD Service Test</li>
<li>MVC CRUD Controller Test</li>
</ol>
<br>

<h2 id="1-mvc-crud-mapper-test">1. MVC CRUD Mapper Test</h2>
<p>Create, Read, Update, Delete를 Mapping이 되었는지 확인하기 위해 각 Mapper를 JUnit으로 Test</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/9c123ef9-af65-4ffd-9ab8-fecce6355d2c/image.PNG" alt=""></p>
<ul>
<li>연동테스트를 위해 DB에 테이블 생성 및 더미 데이터 추가</li>
<li>데이터를 추가한 후 commit을 꼭 해야한다.</li>
</ul>
<br>

<p><strong>영속 계층 구현</strong></p>
<ol>
<li>테이블 컬럼 구조 반영 VO 클래스 생성</li>
<li>Mybatis의 Mapper 인터페이서 작성 및 XML</li>
<li>작성한 인터페이스 테스트</li>
</ol>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/89445b59-c1e1-477f-b170-599e7e7cf8aa/image.PNG" alt=""></p>
<ul>
<li>DB에서 생성한 객체를 담을 수 있도록 도메인 객체를 위와 같이 생성<br>

</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/373fc57c-2a71-4cae-968a-e78af5ef45ca/image.PNG" alt=""></p>
<ul>
<li>Mybatis와 연동하기 위해 mapper 패키지를 scan 하기위해 위와 같이 작성<br>

</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/e236ae19-e909-4e41-8174-ad5f469e1390/image.PNG" alt=""></p>
<ul>
<li>SQL과 Mapping할 메소드들을 인터페이스로 선언</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/c84ba876-61dc-41bf-8f7c-0b2248490720/image.PNG" alt=""></p>
<ul>
<li>인터페이스에서 선언한 메소드와 같은 id로 선언하고 쿼리문 작성</li>
<li><code>&lt;![CDATA[...]]&gt;</code> 는 쿼리문의 부등호를 사용하기 위해 사용</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/ff63e3cd-bf69-4ad4-9040-3fa14bc3216e/image.PNG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/500fc689-8f1f-48d0-a4f9-3b397786cdbd/image.PNG" alt=""></p>
<ul>
<li>JUnit으로 Mapping이 잘되었는지 Test</li>
</ul>
<br>

<p><strong>Create Test</strong></p>
<ul>
<li>자동으로 PK가 결정시 처리 방법 </li>
</ul>
<ol>
<li>insert만 처리되고 PK를 알 필요가 없는 경우</li>
<li>insert문이 실행되고 생성된 PK를 알아야 하는 경우</li>
</ol>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/ff269513-4ada-4e45-81ea-9ae0b4a0cee6/image.PNG" alt=""></p>
<ul>
<li>1번 방법인 기본 insert문과 2번 방법인 SelectKey 방법을 사용</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/fcc84f29-fd82-45c6-b7fc-d32ced1b94c7/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/7d15708e-7f05-41ea-a490-8574ec23d1b3/image.PNG" alt=""></p>
<ul>
<li>1번 방법은 insert시 PK인 bno가 null 값으로 출력 되지만</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/4bae4307-04d1-4188-a80e-ef7156e3166c/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/55ed43e4-2d09-4ac3-b5dc-23b51ce9455a/image.PNG" alt=""></p>
<ul>
<li>2번 SelectKey 방법은 insert시 PK인 bno가 정상적으로 출력이 된다.</li>
</ul>
<br>

<p><strong>Read Test</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/83d417f1-9cee-4f0c-a67e-cf48850383c4/image.PNG" alt=""></p>
<ul>
<li>Select문을 사용하므로 resultType 선언</li>
<li>bno에 해당하는 내용을 읽을 것이기 때문에 where절에 bno 선언</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/b1f771ad-f3a2-4d75-a48f-827f1c882a0e/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/2ecf01c5-4dd0-483a-8b1d-0ed01726ca2b/image.PNG" alt=""></p>
<ul>
<li>VO 객체를 생성하여 bno가 5인 객체를 담고 log로 출력</li>
</ul>
<br>

<p><strong>Delete Test</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/f980e2c7-2016-4899-a409-b2757526987c/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/a5ab3021-3d0b-4204-9339-4f4ce1953499/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/43f7ca0f-22a7-429d-9c04-7fbb821274f8/image.PNG" alt=""></p>
<p><strong>Update Test</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/640f3668-8206-4bb3-9373-dc6f3cc4db42/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/aa8b18c1-31ea-4574-bd2e-a458112eb23b/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/e0d41465-074d-4a4a-8cfd-713abc17cdd6/image.PNG" alt=""></p>
<ul>
<li>VO 객체를 생성</li>
<li>생성한 객체에 set메소드를 통하여 수정할 변수들을 선언</li>
<li>선언한 bno에 대한 객체가 수정</li>
</ul>
<br>

<hr>
<h2 id="2-mvc-crud-service-test">2. MVC CRUD Service Test</h2>
<p>Create, Read, Update, Delete를 비즈니스 로직을 위해 각 Service를 Test</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/4f214f6e-d189-4ce6-83e0-1780e1c3fe9b/image.PNG" alt=""></p>
<ul>
<li>비즈니스 계층을 위해 패키지를 생성</li>
<li>BoardServiceImple은 느슨한 결합을 하기 위해 메소드를 구현하는 역할</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/34358c01-4217-4ca7-9c33-ed3a752b4396/image.PNG" alt=""></p>
<ul>
<li>service 패키지를 스캔하기 위해 xml에 등록</li>
</ul>
<br>

<p><strong>Create Test</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/61215685-9c18-4848-9952-c5bda4b51d62/image.PNG" alt=""></p>
<ul>
<li>BoardService 인터페이스를 생성해 메소드 등록</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/aa95a0f5-05e7-4d4c-b897-f1d0200c58a6/image.PNG" alt=""></p>
<ul>
<li>@AllArgsConstructor 어노테이션은 단일 파라미터일 경우 자동으로 의존성 주입을 하는 어노테이션이다. 때문에 따로 Setter를 선언할 필요가 없다</li>
<li>DB연동 체크를 위해 BoardMapper 객체를 생성</li>
<li>Service 인터페이스에 메소드를 등록 했으므로 Override를 통해 구현</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/55bfeea1-db1e-480a-ad70-19e267daeaa2/image.PNG" alt=""></p>
<ul>
<li>Service를 Test 해야하기 때문에 객체를 생성후 @Autowired를 선언하여 의존성 주입</li>
<li>VO 객체 생성 후 작성할 내용을 set메소드를 사용해 작성한다.</li>
<li>service객체에서 생성한 메소드 선언</li>
</ul>
<br>

<p><strong>Read Test</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/e5a03ed7-f688-4d83-9baa-3e80cbfce11b/image.PNG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/f46a4ccd-e0a5-4935-ad88-8613fca5a796/image.PNG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/a61d99ac-8105-4bce-881a-b8c4106d796e/image.PNG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/33c8c21f-1ac9-4472-8549-4b956b30dd16/image.PNG" alt=""></p>
<br>

<p><strong>Update Test</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/c6a0c828-399e-48b4-b9b4-1c022eb307d8/image.PNG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/ed3b0e3f-1c03-4a96-9cf6-59526fda9ed9/image.PNG" alt=""></p>
<ul>
<li>객체에서 1을 조회한다. 조회하는 이유는 bno가 1인 객체를 수정하기 위함이다.</li>
<li>조회한 값이 null 이면 return 하고 값이 있다면 set을 사용해 제목 수정한후 modify 메소드 호출</li>
</ul>
<br>

<p><strong>Delete Test</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/b79c9815-c689-49df-ae07-49e492e745f7/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/9f4a4ab5-4a1a-49be-b7ea-158aeb90875b/image.PNG" alt=""></p>
<br>

<h2 id="3-mvc-crud-controller-test">3. MVC CRUD Controller Test</h2>
<p>Create, Read, Update, Delete를 웹으로 구현하기 위해 Controller를 Test</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/c28ee583-27bc-458d-b843-1d8a0f19585d/image.PNG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/3e5f8310-44ee-4dd5-9ff1-0fbbb066559e/image.PNG" alt=""></p>
<ul>
<li>@Controller 어노테이션을 통해 객체로 등록될 수 있도록 한다.</li>
<li>RequestMapping으로 상위 경로를 설정</li>
<li>@AllArgsConstructor로 파라미터 하나인 객체를 의존성 주입</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/f1e0c9af-49b7-4c2c-85fc-a210b4811955/image.PNG" alt=""></p>
<ul>
<li>@WebApplicationConfiguration을 사용해 WebApplicationContext를 이용 할 수 있도록 설정</li>
<li>@RunWith 는 JUnit을 사용할 수 있게 한다.</li>
<li>@ContextConfiguration으로 설정 파일을 로드</li>
<li>MockMvc는 WAS를 구동하지 않고 테스트를 할 수 있게 해준다.</li>
<li>@Before 는테스트 메소드 실행 전 실행하게 해준다.</li>
</ul>
<br>

<p><strong>Create Test</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/eb0c9540-5ea2-4041-9490-f7d34808aea5/image.PNG" alt=""></p>
<ul>
<li>@GetMapping은 register.jsp로 이동하기 위함이다. </li>
<li>데이터 타입이 void 이면 url자체를 리턴한다.</li>
<li>@PostMapping은 Post 방식을 처리하기 위함이다.</li>
<li>command 방식으로 VO 객체를 가져온다.</li>
<li>Redirect를 위해 RedirectAttributes를 선언</li>
<li>Service에서 로직 처리한 메소드를 호출</li>
<li>addFlashAttribute로 bno를 result에 담아 list로 redirect</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/6f63a344-ca44-48ca-92b1-7b969ac7d1fe/image.PNG" alt=""></p>
<ul>
<li>mockMvc 객체 내에 내장되어 있는 함수를 사용해 post 방식으로 register 경로로 데이터를 전달</li>
<li>.param을 사용하여 전달할 파라미터값을 선언</li>
</ul>
<br>

<p><strong>Read Test</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/c7ffdc50-be2f-4289-94d4-d46349073507/image.PNG" alt=""></p>
<ul>
<li>Model 객체를 생성하여 데이터를 가지고 전달</li>
<li>getList() 메소드를 list에 담는다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/f86e2e88-5673-4727-9646-a4b0f0f82f2a/image.PNG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/157408ab-89e0-4e21-bc97-a47cfee51815/image.PNG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/4db8fe82-0ee4-45be-9555-379b9744218e/image.PNG" alt=""></p>
<br>

<p><strong>Update Test</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/12a81105-585b-4bcd-a695-c98bcd166c42/image.PNG" alt=""></p>
<ul>
<li>VO 객체를 생성하고 list로 이동하기 위해 redirect 객체 선언</li>
<li>만약 수정을 한다면 success를 result에 담아 list로 redirect</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/350742cf-cf1f-4064-b5cf-2b2c2b6e35dc/image.PNG" alt=""></p>
<ul>
<li>Post방식으로 modify로 이동</li>
<li>.param으로 수정될 내용을 담는다.</li>
</ul>
<br>

<p><strong>Delete Test</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/299632b2-73d5-4861-bec1-d761b75eed4a/image.PNG" alt=""></p>
<ul>
<li>bno 값을 RequestParam으로 파라미터 값을 넣어준다.</li>
<li>RequestParam은 HttpServletRequest와 같은 역할을 한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/e7f7c80a-9ae4-4b76-b17a-bd2e5ef36cce/image.PNG" alt=""></p>
<ul>
<li>Post 방식으로 14인 bno를 가지고 간다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[KOSTA] Spring 기반 Cloud 서비스 개발자 양성 과정 73일차 - JUnit, DB, Mybatis, log4j, MVC]]></title>
            <link>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-73%EC%9D%BC%EC%B0%A8-JUnit-DB-Mybatis-log4j-MVC</link>
            <guid>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-73%EC%9D%BC%EC%B0%A8-JUnit-DB-Mybatis-log4j-MVC</guid>
            <pubDate>Thu, 19 May 2022 02:08:05 GMT</pubDate>
            <description><![CDATA[<h1 id="📖-학습-내용">📖 학습 내용</h1>
<ol>
<li>JUnit</li>
<li>Orcale Database 연동</li>
<li>Mybatis 연동</li>
<li>log4j</li>
<li>MVC Controller</li>
</ol>
<h2 id="1-junit">1. JUnit</h2>
<p>단위 테스트 도구로서 테스트를 쉽게 할 수 있게 만들어주는 라이브러리</p>
<ul>
<li>어노테이션으로 간결하게 지원</li>
</ul>
<br>

<p><strong>예제</strong>
<img src="https://velog.velcdn.com/images/junbeomm-park/post/a1f95e44-15ed-4474-8c7b-c978f36dae82/image.PNG" alt=""></p>
<p>pom.xml에 위와 같이 라이브러리 등록</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/a51303a9-93c0-4270-a22c-3b1afd958d29/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/3e3794d8-e066-4a2b-a4ba-6f9a7cfabe7c/image.PNG" alt=""></p>
<ul>
<li>chef 클래스는 @Component를 사용해 빈 등록</li>
<li>@Data : Lombok을 사용해 자동으로 set/get 메소드 생성</li>
<li>Restaurant 클래스에서 chef 객체를 선언하고 @Data를 통해 @Setter를 사용해 의존성 주입</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/a54187ed-105f-44ba-b246-1006f99ad847/image.PNG" alt=""></p>
<ul>
<li>src/test/java 패키지에서 test 클래스를 생성</li>
<li><strong><code>JUnit Test Case</code></strong> 클래스를 선언하여 생성</li>
<li><strong><code>@RunWith</code></strong>는 현재 테스트 코드가 스프링을 실행하는 역할을 할 것이라는 것을 뜻함</li>
<li><strong><code>@ContextConfiguration</code></strong>은 지정된 클래스나 문자열을 이용해 객체를 스프링에 등록</li>
<li><strong><code>@Log4j</code></strong>는 log를 기록하는 Logger를 변수로 생성</li>
<li>restaurant 객체를 생성하여 의존성 주입</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/1b9a9704-87af-474a-aa9f-3755a6d8b67d/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/d6e1f9fb-e3ae-4dec-9894-77f955bbd83a/image.PNG" alt=""></p>
<ul>
<li>Restaurant에서 new 연산자를 통해 객체를 생성하지 않았음에도 객체가 생성됨</li>
<li><blockquote>
<p><code>@Component</code>를 통해 빈 객체에 등록했기 때문</p>
</blockquote>
</li>
</ul>
<br>

<hr>
<h2 id="2-orcale-database-연동">2. Orcale Database 연동</h2>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/fcb38234-28b0-4a0d-8ac7-16cb1bb12b11/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/d3fc0e1a-d874-461c-927b-d458e86e3091/image.PNG" alt=""></p>
<ul>
<li>Connection Pool을 위해 Hikari 라이브러리를 사용하기 위해 위와 pom.xml 과 servlet-xml에 위와 같이 셋팅</li>
</ul>
<br>

<hr>
<h2 id="3-mybatis-연동">3. Mybatis 연동</h2>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/d12ed870-14fe-40fa-8091-3b001efb0bd0/image.PNG" alt=""></p>
<ul>
<li>pom.xml 에 라이브러리 추가</li>
<li>spring-jdbc / spring-tx : 스프링에서 DB처리와 트랜잭션 처리를 위함</li>
<li>mybatis / mybatis-spring : 스프링과 연동</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/e204ab7d-71f4-4c5f-8482-72caf11fb820/image.PNG" alt=""></p>
<ul>
<li>SqlSessionFactory 등록</li>
<li>mybatis 셋팅은 SQL을 별도로 설정을 분리하고 자동으로 처리될 수 있도록 Mapper 선언</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/4e6ec963-d107-44b5-9595-f832b16aa9ea/image.PNG" alt=""></p>
<ul>
<li>어노테이션을 활용해 쿼리문을 짤 수 도 있다. </li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/d1390222-ce6b-425f-aaf4-a8e09f2d7ece/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/d00e692a-5247-4b34-855e-f1ad808b3f43/image.PNG" alt=""></p>
<ul>
<li>timeMapper객체를 생성하고 의존성 주입</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/50d4365c-a2bb-49a5-a47c-7329a7908ae5/image.PNG" alt=""></p>
<ul>
<li>연동이 잘 되었는지 JUnit으로 테스트</li>
</ul>
<br>

<hr>
<h2 id="4log4jdbc-log4j2-설정">4.log4jdbc-log4j2 설정</h2>
<p>SQL문의 값을 제대로 확인하기 위해 SQL로그를 편리하게 바꿔주는 라이브러리</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/8981e7f8-ac8b-4e08-a2ae-01a8c61c6495/image.PNG" alt=""></p>
<ul>
<li>pom.xml에 라이브러리 등록</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/2f997255-ecba-430b-b216-bea9a80bbc37/image.PNG" alt=""></p>
<ul>
<li>src/main/resources 에 log4jdbc.log4f2.properties 추가</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/ddb23356-de95-4f0f-ba15-3626bc02c359/image.PNG" alt=""></p>
<ul>
<li>Hikari 셋팅을 위와 같이 해준다</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/2532ebda-b60e-425d-bfe4-dc10f7e2f1bf/image.PNG" alt=""></p>
<ul>
<li>위와 같이 가독성 좋게 로그가 출력</li>
</ul>
<br>

<hr>
<h2 id="5-mvc-controller">5. MVC Controller</h2>
<p>MVC 패턴에서의 Controller의 역할</p>
<ul>
<li>HttpServletRequest, HttpServletResponse를 거의 사용할 필요 없이 구현이 가능</li>
<li>다양한 타입의 파라미터 처리 및 리턴이 가능</li>
<li>Get,Post 방식에 대한 어노테이션으로 처리가 가능</li>
<li>상속/인터페이스 방식 대신 어노테이션 만으로도 설정이 가능</li>
</ul>
<br>

<p><strong>예제</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/a83ff123-b6df-48b6-bf8d-10837080f573/image.PNG" alt=""></p>
<ul>
<li><code>@Controller</code> 는 해당 클래스를 자동적으로 스프링에 객체로 등록하게 해준다</li>
<li><code>@RequestMapping</code>은 메소드의 경로를 표현한다. 클래스에 선언할 시 클래스의 하위 메소드의 상위 주소를 가진다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/4b6ac500-ee80-4951-a325-adf04163053a/image.PNG" alt=""></p>
<ul>
<li>SampleDTO에 @Data 어노테이션 적용</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/c4428e0e-1016-49ce-b64f-98077c85fe66/image.PNG" alt=""></p>
<ul>
<li>위 방식은 SampleDTO를 직접 파라미터에 선언하는 command 방식</li>
<li>객체 자체를 출력하면 내부 변수들이 출력</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/a79c51ec-f14b-4a91-a48d-f22d5e4e3f1c/image.PNG" alt=""></p>
<ul>
<li>@RequestParam을 사용해 객체의 변수명을 가져오고 변수를 셋팅</li>
<li>각 객체에 대한 변수를 선언 하여 출력</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[KOSTA] Spring 기반 Cloud 서비스 개발자 양성 과정 72일차 - Spring (CRUD, Mybatis, RequestParam, ModelAttribute, Restful, PathVariable, tiles)]]></title>
            <link>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-72%EC%9D%BC%EC%B0%A8-Spring-CRUD-Mybatis-tiles</link>
            <guid>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-72%EC%9D%BC%EC%B0%A8-Spring-CRUD-Mybatis-tiles</guid>
            <pubDate>Tue, 17 May 2022 02:39:53 GMT</pubDate>
            <description><![CDATA[<h2 id="📖-배운-내용">📖 배운 내용</h2>
<ol>
<li>Mybatis</li>
<li>CRUD</li>
<li>@RequestParam</li>
<li>@ModelAttibute</li>
<li>@PathVariable(RESTful)</li>
<li>tiles</li>
</ol>
<br>
<br>

<h3 id="1-mybatis-연동">1. Mybatis 연동</h3>
<pre><code class="language-xml"> &lt;Context docBase=&quot;spring_web&quot; 
          path=&quot;/spring_web&quot; 
          reloadable=&quot;true&quot; 
          source=&quot;org.eclipse.jst.jee.server:spring_web&quot;&gt;
          &lt;Resource auth=&quot;Container&quot; 
                  driverClassName=&quot;oracle.jdbc.driver.OracleDriver&quot; 
                  maxActive=&quot;100&quot; maxIdle=&quot;30&quot; maxWait=&quot;10000&quot; name=&quot;jdbc/oracle&quot;
                  password=&quot;1234&quot; type=&quot;javax.sql.DataSource&quot; 
                  url=&quot;jdbc:oracle:thin:@localhost:1521:XE&quot; username=&quot;kosta236&quot;/&gt;
 &lt;/Context&gt;</code></pre>
<p>위와 같은 형식으로 server.xml에 등록 해준다.</p>
<p><br><br></p>
<pre><code class="language-xml">&lt;!-- Mybatis Setting --&gt;

    &lt;bean id=&quot;sqlSessionTemplate&quot;
        class=&quot;org.mybatis.spring.SqlSessionTemplate&quot;&gt;
        &lt;constructor-arg name=&quot;sqlSessionFactory&quot; ref=&quot;sqlSessionFactory&quot;&gt;&lt;/constructor-arg&gt;    
    &lt;/bean&gt;

    &lt;bean id=&quot;sqlSessionFactory&quot;
        class=&quot;org.mybatis.spring.SqlSessionFactoryBean&quot;&gt;
        &lt;property name=&quot;dataSource&quot; ref=&quot;myDataSource&quot;/&gt;
        &lt;property name=&quot;configLocation&quot; value=&quot;/WEB-INF/mybatis-config.xml&quot;&gt;&lt;/property&gt;
    &lt;/bean&gt;

    &lt;bean id=&quot;myDataSource&quot;
        class=&quot;org.springframework.jndi.JndiObjectFactoryBean&quot;&gt;
        &lt;property name=&quot;jndiName&quot; value=&quot;jdbc/oracle&quot;/&gt;
        &lt;property name=&quot;resourceRef&quot; value=&quot;true&quot;/&gt;
    &lt;/bean&gt;</code></pre>
<p>sqlSessionTemplate을 사용하기 위해 위와 같은 과정을 진행한다.</p>
<p><br><br></p>
<pre><code class="language-java">
@Repository
public class BoardDao {

    @Autowired
    private SqlSessionTemplate sqlTemplate;

    public void insert(Board board) {
        sqlTemplate.getMapper(BoardMapper.class).insertBoard(board);
    }
}
</code></pre>
<p>최종적으로 DAO에서 sqlSessionTemplate을 사용하여 Mapping 한다.</p>
<p><br><br></p>
<hr>
<h3 id="2crud">2.CRUD</h3>
<p>CRUD (Create, Read, Update, Delete)를 Spring을 이용하여 구현</p>
<pre><code class="language-xml">&lt;mapper namespace=&quot;kosta.mapper.BoardMapper&quot;&gt;
    &lt;cache /&gt;

    &lt;insert id=&quot;insertBoard&quot; parameterType=&quot;Board&quot;&gt;
        insert into board(
            seq,title,writer,contents, regdate, hitcount
        )values(
            board_seq.nextval, #{title}, #{writer}, #{contents}, sysdate, 0 
        )

    &lt;/insert&gt;

      &lt;select id=&quot;listBoard&quot; resultType=&quot;Board&quot;&gt;
        select * from board
        order by seq desc
    &lt;/select&gt;

    &lt;select id=&quot;detailBoard&quot; resultType=&quot;Board&quot; parameterType=&quot;int&quot;&gt;
        select * from board where seq=#{seq}
    &lt;/select&gt; 

    &lt;update id=&quot;updateBoard&quot; parameterType=&quot;Board&quot;&gt;
        update board set title=#{title}, contents=#{contents} where seq=#{seq}
    &lt;/update&gt;

    &lt;delete id=&quot;deleteBoard&quot; parameterType=&quot;int&quot;&gt;
        delete from board where seq=#{seq}
    &lt;/delete&gt;   
&lt;/mapper&gt;</code></pre>
<p>Mapping할 CRUD의 쿼리문을 사용하기 위한 xml파일을 생성해 위와 같이 코딩
select를 제외한 모든 DML에는 <code>parameterType</code>을 선언</p>
<br>
<br>

<pre><code class="language-java">public interface BoardMapper {
    List&lt;Board&gt; listBoard();
    int insertBoard(Board board);
    Board detailBoard(int seq);
    int updateBoard(Board board);
    int deleteBoard(int seq);

}</code></pre>
<p>CRUD에 해당되는 추상 메소드들을 Mapping</p>
<p><br><br></p>
<pre><code class="language-java">package kosta.model;

import java.io.Serializable;

import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.NotEmpty;

public class Board implements Serializable{

    private int seq;

    @NotEmpty(message = &quot;반드시 입력하세요&quot;)
    @Size(min = 2, max = 5, message = &quot;글자수 2~5까지&quot;)
    private String title;

    @Pattern(regexp = &quot;[0-9a-zA-Z가-힣]*&quot;, message = &quot;특수문자 금지&quot;)
    private String writer;

    private String contents;
    private String regdate;
    private int hitcount;

    public Board() {

    }

    public Board(int seq, String title, String writer, String contents, String regdate, int hitcount) {
        super();
        this.seq = seq;
        this.title = title;
        this.writer = writer;
        this.contents = contents;
        this.regdate = regdate;
        this.hitcount = hitcount;
    }

    public int getSeq() {
        return seq;
    }

    public void setSeq(int seq) {
        this.seq = seq;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getWriter() {
        return writer;
    }

    public void setWriter(String writer) {
        this.writer = writer;
    }

    public String getContents() {
        return contents;
    }

    public void setContents(String contents) {
        this.contents = contents;
    }

    public String getRegdate() {
        return regdate;
    }

    public void setRegdate(String regdate) {
        this.regdate = regdate;
    }

    public int getHitcount() {
        return hitcount;
    }

    public void setHitcount(int hitcount) {
        this.hitcount = hitcount;
    }

    @Override
    public String toString() {
        return &quot;Board [seq=&quot; + seq + &quot;, title=&quot; + title + &quot;, writer=&quot; + writer + &quot;, contents=&quot; + contents + &quot;, regdate=&quot;
                + regdate + &quot;, hitcount=&quot; + hitcount + &quot;]&quot;;
    }

}
</code></pre>
<p>Serializable한 DTO 객체 생성</p>
<p><br><br></p>
<pre><code class="language-java">@Repository
public class BoardDao {

    @Autowired
    private SqlSessionTemplate sqlTemplate;

    public void insert(Board board) {
        sqlTemplate.getMapper(BoardMapper.class).insertBoard(board);
    }

    public List&lt;Board&gt; list() {
        return sqlTemplate.getMapper(BoardMapper.class).listBoard();
    }

    public Board detail(int seq) {
        return sqlTemplate.getMapper(BoardMapper.class).detailBoard(seq);
    }

    public void update(Board board) {
        sqlTemplate.getMapper(BoardMapper.class).updateBoard(board);
    }

    public void delete(int seq) {
        sqlTemplate.getMapper(BoardMapper.class).deleteBoard(seq);
    }
}</code></pre>
<p>@Repository를 사용하여 빈 등록을 해 Container에 객체 생성
@Autowired를 통해 의존성 주입
sql 객체를 생성한 sqlTemplate으로 Mapping</p>
<p><br><br></p>
<pre><code class="language-java">
@Controller
public class BoardController {
    @Autowired
    private BoardDao dao;

    //@RequestMapping(value = &quot;/board_insert&quot;, method = RequestMethod.GET)
    @GetMapping(&quot;/board_insert&quot;)
    public String board_form(@ModelAttribute(&quot;boardCommand&quot;) Board board) {
        System.out.println(&quot;form 페이지 이동&quot;);
        return &quot;insert_form&quot;;
    }

    //@RequestMapping(value = &quot;/board_insert&quot;, method = RequestMethod.POST)
    @PostMapping(&quot;/board_insert&quot;)
    public String board_insert(@ModelAttribute(&quot;boardCommand&quot;) @Valid Board board, BindingResult errors) {

        if(errors.hasErrors()) {
            System.out.println(&quot;에러발생&quot;);
            return &quot;insert_form&quot;;
        }

        dao.insert(board);

        return &quot;redirect:board_list&quot;;
    }

    @RequestMapping(&quot;/board_list&quot;)
    public String board_list(Model model) {
        List&lt;Board&gt; list = dao.list();

        model.addAttribute(&quot;list&quot;,list);

        return &quot;list&quot;;
    }

    /*
     * @RequestMapping(&quot;/board_detail&quot;) public String
     * board_detail(@RequestParam(&quot;seq&quot;) int seq, Model model) {
     * model.addAttribute(&quot;board&quot;,dao.detail(seq));
     * 
     * return &quot;detail&quot;; }
     */

    @RequestMapping(&quot;/board_detail{seq}&quot;)
    public String board_detail(@PathVariable int seq, Model model) {
        model.addAttribute(&quot;board&quot;,dao.detail(seq));

        return &quot;detail&quot;;
    }

    @GetMapping(&quot;/board_update&quot;)
    public String update_form(@RequestParam(&quot;seq&quot;) int seq, Model model) {
        model.addAttribute(&quot;board&quot;, dao.detail(seq));

        return &quot;updateForm&quot;;
    }

    @PostMapping(&quot;/board_update&quot;)
    public String board_update(Board board) {
        dao.update(board);

        return &quot;redirect:board_list&quot;;
    }

    @RequestMapping(&quot;/board_delete&quot;)
    public String delete_board(@RequestParam(&quot;seq&quot;) int seq) {
        dao.delete(seq);

        return(&quot;redirect:board_list&quot;);
    }

}</code></pre>
<p>클래스에 @Controller를 선언하여 Controller임을 알려주고 @RequestMapping을 통하여 URL Mapping
String을 이용하여 바로 view로 return
각 메소드별 data를 받는 파라미터에 따라 Mapping</p>
<p><br><br></p>
<hr>
<h2 id="3-requestparam">3. @RequestParam</h2>
<p>파라미터값을 가져올 수 있는 어노테이션이다. 가져오는 파라미터값을 명확하게 하기 위해 사용한다.</p>
<ul>
<li>1:1로 파라미터를 받는 경우에 사용한다.</li>
<li>name, value : 파라미터 이름</li>
<li>required : 해당 파라미터가 필요한지의 여부</li>
<li>defaultValue : 해당 파라미터의 기본 값</li>
</ul>
<pre><code class="language-java">@GetMapping(&quot;/board_update&quot;)
    public String update_form(@RequestParam(&quot;seq&quot;) int seq, Model model) {
        model.addAttribute(&quot;board&quot;, dao.detail(seq));

        return &quot;updateForm&quot;;
    }</code></pre>
<p> seq라는 파라미터값을 가져와 seq 라는 변수를 선언</p>
 <br>
 <br>




<h2 id="4-modelattribute">4. @ModelAttribute</h2>
<p> 파라미터값을 가져올 수 있는 어노테이션</p>
<ul>
<li><p>@RequestParam 과의 차이점으로는 도메인, 오브젝트를 통하여 파라미터를 받는다.</p>
</li>
<li><p>Validation을 사용하여 에러 처리가 가능하다.</p>
<pre><code class="language-java">@PostMapping(&quot;/board_insert&quot;)
 public String board_insert(@ModelAttribute(&quot;boardCommand&quot;) @Valid Board board, BindingResult errors) {

     if(errors.hasErrors()) {
         System.out.println(&quot;에러발생&quot;);
         return &quot;insert_form&quot;;
     }

     dao.insert(board);

     return &quot;redirect:board_list&quot;;
 }
</code></pre>
</li>
<li><p>boardCommand 라는 commandName을 가진 form 태그의 정보들을 한 번에 가져오기 위해 사용</p>
</li>
</ul>
 <br>
 <br>


<h2 id="5-pathvariablerestful">5. @PathVariable(RESTful)</h2>
<p> URL 경로에 변수를 넣어주는 어노테이션</p>
<ul>
<li><p>@RequestMapping의 URL 정의 부분과 메소드 내의 파라미터 부분에 정의하여 사용</p>
</li>
<li><p>null 혹은 공백값이 들어가는 파라미터라면 적용이 되지 않는다.</p>
</li>
<li><p>해당 어노테이션과 동일한 이름(템플릿 변수)를 가지는 파라미터에 적용</p>
<pre><code class="language-java">@RequestMapping(&quot;/board_detail{seq}&quot;)
 public String board_detail(@PathVariable int seq, Model model) {
     model.addAttribute(&quot;board&quot;,dao.detail(seq));

     return &quot;detail&quot;;
 }
</code></pre>
</li>
<li><p>URL 주소 옆에 해당 변수 값을 {} 내에 추가</p>
</li>
<li><p>@PathVariable을 통해 int seq를 선언한다.</p>
</li>
</ul>
<p><br><br></p>
<h2 id="6-tiles">6. tiles</h2>
<p>tiles는 View의 기존 구조를 쉽게 적용하기 위한 템플릿 프레임워크이다.</p>
<ul>
<li>페이지 수정이 쉬워 유지보수가 용이</li>
<li>일관적인 페이지 관리 가능</li>
</ul>
<p><strong>1. pom.xml에 라이브러리 추가</strong></p>
<pre><code class="language-xml">        &lt;dependency&gt;
            &lt;groupId&gt;org.apache.tiles&lt;/groupId&gt;
            &lt;artifactId&gt;tiles-jsp&lt;/artifactId&gt;
            &lt;version&gt;3.0.7&lt;/version&gt;
        &lt;/dependency&gt;

        &lt;dependency&gt;
            &lt;groupId&gt;org.apache.tiles&lt;/groupId&gt;
            &lt;artifactId&gt;tiles-core&lt;/artifactId&gt;
            &lt;version&gt;3.0.7&lt;/version&gt;
        &lt;/dependency&gt;

        &lt;dependency&gt;
            &lt;groupId&gt;org.apache.tiles&lt;/groupId&gt;
            &lt;artifactId&gt;tiles-servlet&lt;/artifactId&gt;
            &lt;version&gt;3.0.7&lt;/version&gt;
        &lt;/dependency&gt;</code></pre>
<ul>
<li>총 세가지의 라이브러리를 추가</li>
<li>버전은 3.0.7로 통일</li>
</ul>
<br>

<p><strong>2. Dispatcher Servlet.xml에 View Resolver, xml 추가</strong></p>
<pre><code class="language-xml">&lt;!-- Tiles Setting --&gt;

    &lt;bean id=&quot;viewResolver2&quot;
        class=&quot;org.springframework.web.servlet.view.UrlBasedViewResolver&quot;&gt;
        &lt;property name=&quot;viewClass&quot;
            value=&quot;org.springframework.web.servlet.view.tiles3.TilesView&quot;/&gt;
        &lt;property name=&quot;order&quot; value=&quot;1&quot;/&gt;    
    &lt;/bean&gt;

    &lt;bean id=&quot;tilesConfigurer&quot; 
        class=&quot;org.springframework.web.servlet.view.tiles3.TilesConfigurer&quot;&gt;
        &lt;property name=&quot;definitions&quot;&gt;
            &lt;list&gt;
                &lt;value&gt;/WEB-INF/tiles2def.xml&lt;/value&gt;
            &lt;/list&gt;
        &lt;/property&gt;
    &lt;/bean&gt;</code></pre>
<ul>
<li>중요한 부분은 order 속성을 최우선 1번 지정하여 tiles에 해당되는 로직을 우선적으로 로드 시킨 다는 의미이다.</li>
<li>이에 따라 다른 order 속성도 차후 번호를 선언하여 주어야 한다.</li>
</ul>
<br>

<p><strong>3. tile-def.xml 설정</strong></p>
<pre><code class="language-xml">&lt;tiles-definitions&gt;

    &lt;definition name=&quot;base_layout&quot; template=&quot;/view/module/template.jsp&quot;&gt;
        &lt;put-attribute name=&quot;header&quot; value=&quot;/view/module/header.jsp&quot;/&gt;    
        &lt;put-attribute name=&quot;logo&quot; value=&quot;/view/module/logo.jsp&quot;/&gt;    
        &lt;put-attribute name=&quot;footer&quot; value=&quot;/view/module/footer.jsp&quot;/&gt;    
    &lt;/definition&gt;

    &lt;definition name=&quot;insert_form&quot; extends=&quot;base_layout&quot;&gt;
        &lt;put-attribute name=&quot;body&quot; value=&quot;/view/insert_form.jsp&quot;/&gt;
    &lt;/definition&gt;

    &lt;definition name=&quot;list&quot; extends=&quot;base_layout&quot;&gt;
        &lt;put-attribute name=&quot;body&quot; value=&quot;/view/list.jsp&quot;/&gt;
    &lt;/definition&gt;


&lt;/tiles-definitions&gt;</code></pre>
<ul>
<li>위 설정 파일은 tiles의 layout을 적용하는 화면을 설정</li>
<li>base_layout이라는 name을 가진 템플릿은 value로 설정한 경로의 내용에 맞는 header와 footer를 가지고 있다.</li>
<li>나머지 name을 가진 태그들은 base_layout을 상속받아 기본적으로 header, footer의 속성을 가지고 있을 수 있게 선언</li>
<li>name은 URL을 통해서 가는 View와 이름이 같아야 한다.</li>
</ul>
<br>

<p><strong>4. 기본 레이아웃을 JSP에 추가</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/eb8fc945-427d-4638-86f5-b5b9b4ae9554/image.PNG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/13844f7e-6127-48a8-a96b-9c1edc037372/image.PNG" alt=""></p>
<ul>
<li>template.jsp 에서 tiles 태그를 사용해 xml에서 정해준 name을 선언</li>
</ul>
<br>

<p><strong>5. 결과</strong>
<img src="https://velog.velcdn.com/images/junbeomm-park/post/95bd4ebd-337b-40ae-8a3a-84c354e2a1a0/image.PNG" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[KOSTA] Spring 기반 Cloud 개발자 양성 과정 71일차 - Spring MVC]]></title>
            <link>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-Spring</link>
            <guid>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-Spring</guid>
            <pubDate>Mon, 16 May 2022 00:37:46 GMT</pubDate>
            <description><![CDATA[<h2 id="🤔-mvc-">🤔 MVC ?</h2>
<p>어플리케이션의 확장을 위해 Model, View, Controller로 분리하여 개발 하는 방법</p>
<ul>
<li>컴포넌트의 변경이 다른 영역 컴포넌트에 영향을 미치지 않음</li>
<li>컴포넌트 간의 결합성이 낮아 프로그램 수정이 용이</li>
</ul>
<p><strong>장점</strong></p>
<ul>
<li>화면과 비즈니스 로직을 분리해서 작업 가능</li>
<li>영역별 개발로 확장성이 뛰어남</li>
<li>표준화된 코드를 사용하여 공동작업 및 유지보수가 편리함</li>
</ul>
<p><strong>단점</strong> </p>
<ul>
<li>개발과정이 복잡, 초기 개발속도가 늦을 수 있음</li>
<li>초보자가 활용하기엔 난이도가 높음</li>
</ul>
<br>
<br>

<p><strong>MVC 패턴 구조 순서</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/6f3f9e52-4ba7-4591-a327-52eaa33c8438/image.PNG" alt=""></p>
<p>Dispatcher Servlet : url의 요청을 받아서 연결 시켜줌
Handler Mapping : Dispatcher Servlet이 Controller로 매핑 하는 방식을 결정
Controller : 로직을 처리
ModelAndView : view 이름, data를 담는다
ViewResolver : view 타입을 정함
View : 받은 data를 출력</p>
<br>
<br>

<p><strong>요청 처리 순서</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/48c240ed-b43c-472f-9742-ecf83de3c1a8/image.PNG" alt=""></p>
<ol>
<li>Dispatcher Servlet이 request를 수신 -&gt; 어느 컨트롤러에 요청할지 Handler Mapping에게 보냄</li>
<li>Handler Mapping은 Dispatcher Servlet에게 요청을 받아 URL과 Mapping</li>
<li>Dispatcher Servlet은 요청을 Controller에게 전송하여 Controller는 요청을 처리 후 Model을 생성하고 View를 return</li>
<li>ModelAndView 오브젝트는 수행결과를 포함하여 Dispathcer Servlet에 return</li>
<li>ViewResolver가 JSP로 출력하도록 논리적 이름을 실제로 변환</li>
<li>View에 출력</li>
</ol>
<br>
<br>

<hr>
<br>

<p><strong>Maven 셋팅</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/fa9dc776-27eb-440e-9ecb-07ccf9d48a53/image.PNG" alt=""></p>
<ul>
<li>Spring MVC : mvc를 사용하기 위함</li>
<li>validator : @valid, @InitBinder 어노테이션을 주기 위함</li>
</ul>
<br>
<br>

<p><strong>Dispatcher Servlet 셋팅</strong></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/c658a73c-93ce-406c-9aba-3435578b5578/image.PNG" alt=""></p>
<ul>
<li>springapp인 servlet-name을 선언</li>
<li>mapping시 동일한 name을 선언</li>
<li>url-pattern은 /를 주어 모든 요청에 대한 Dispathcer Serlvet이 처리하는 URL Mapping 패턴을 정의</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/e8373948-e017-450b-a2d1-05cf2a2f8417/image.PNG" alt=""></p>
<ul>
<li>web.xml에서 주었던 name으로 xml 생성</li>
<li>context 태그를 이용하여 kosta 패키지 안의 어노테이션을 scan</li>
<li>mvc 태그를 이용하여 Mapping되는 Controller가 없어도 Handler가 default로 빈 객체로 등록되어 요청을 전달</li>
<li>ViewResolver는 Controller가 넘긴 view 이름을 받아 view를 찾음</li>
</ul>
<p><br><br></p>
<hr>
<h3 id="📘-mvc-예제">📘 MVC 예제</h3>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/17caf49c-5d19-497f-8f6f-e81c0d2b6cbc/image.PNG" alt=""></p>
<ul>
<li>getMessage 메소드에서 String 타입을 return</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/e8a6aa0c-0a9a-461c-89e0-747663305ae3/image.PNG" alt=""></p>
<ul>
<li>@Controller로 Controller인 클래스를 지정해주고 setter를 통해 의존성 주입</li>
<li>@RequestMapping을 통해 URL 지정을 해주고 ModelAndView 객체를 생성하여 view의 이름과 메세지의 data를 담아 return</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/47e8e737-7322-42f9-88a9-9a6b4e34810a/image.PNG" alt=""></p>
<ul>
<li>message라고 정한 data를 가져온다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/3f39898c-a0fc-4faa-a7b5-9e183ae88f1b/image.PNG" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[KOSTA] Spring 기반 Cloud 서비스 개발자 양성 과정 53일차 - MVC 패턴]]></title>
            <link>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-53%EC%9D%BC%EC%B0%A8-MVC-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-53%EC%9D%BC%EC%B0%A8-MVC-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Tue, 19 Apr 2022 00:13:36 GMT</pubDate>
            <description><![CDATA[<p>📃 MVC (Model, View, Controller) 로 웹 구성하기</p>
<p><strong>Board.java - 객체</strong> </p>
<pre><code class="language-java">package kosta.model;

import java.io.Serializable;

public class Board implements Serializable {
    private int seq;
    private String title;
    private String writer;
    private String contents;
    private String regdate;
    private int hitcount;

    public Board() {

    }

    public Board(int seq, String title, String writer, String contents, String regdate, int hitcount) {
        super();
        this.seq = seq;
        this.title = title;
        this.writer = writer;
        this.contents = contents;
        this.regdate = regdate;
        this.hitcount = hitcount;
    }

    public int getSeq() {
        return seq;
    }

    public void setSeq(int seq) {
        this.seq = seq;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getWriter() {
        return writer;
    }

    public void setWriter(String writer) {
        this.writer = writer;
    }

    public String getContents() {
        return contents;
    }

    public void setContents(String contents) {
        this.contents = contents;
    }

    public String getRegdate() {
        return regdate;
    }

    public void setRegdate(String regdate) {
        this.regdate = regdate;
    }

    public int getHitcount() {
        return hitcount;
    }

    public void setHitcount(int hitcount) {
        this.hitcount = hitcount;
    }

    @Override
    public String toString() {
        return &quot;Board [seq=&quot; + seq + &quot;, title=&quot; + title + &quot;, writer=&quot; + writer + &quot;, contents=&quot; + contents + &quot;, regdate=&quot;
                + regdate + &quot;, hitcount=&quot; + hitcount + &quot;]&quot;;
    }


}
</code></pre>
<br>

<p><strong>BoardDao.java</strong></p>
<pre><code class="language-java">public class BoardDao2 {
    private static BoardDao2 dao = new BoardDao2();

    public static BoardDao2 getInstance() {
        return dao;
    }

    public SqlSessionFactory getSqlSessionFactory() {
        //mybatis-config.xml =&gt; SqlSessionFactory 변환
        String resource = &quot;mybatis-config.xml&quot;;
        InputStream in = null;

        try {
            in = Resources.getResourceAsStream(resource);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return new SqlSessionFactoryBuilder().build(in);
    }



    public int insertBoard(Board board) {
        SqlSession sqlSession = getSqlSessionFactory().openSession();
        int re = -1;

        try {
            //re = sqlSession.insert(&quot;kosta.mapper.BoardMapper.insertBoard&quot;, board);
            re = sqlSession.getMapper(BoardMapper.class).insertBoard(board);
            if(re&gt;0) {
                sqlSession.commit();
            }else {
                sqlSession.rollback();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(sqlSession != null) {
                sqlSession.close();
            }
        }

        return re;
    }

    public List&lt;Board&gt; listBoard(){
        SqlSession sqlSession = getSqlSessionFactory().openSession();
        List&lt;Board&gt; list = null;

        try {
            //list = sqlSession.selectList(&quot;kosta.mapper.BoardMapper.listBoard&quot;);
            list = sqlSession.getMapper(BoardMapper.class).listBoard();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(sqlSession != null) {
                sqlSession.close();
            }
        }
        return list;
    }

    public Board detailBoard(int seq) {
        SqlSession sqlSession = getSqlSessionFactory().openSession();
        Board board = null;

        try {
            board = sqlSession.getMapper(BoardMapper.class).detailBoard(seq);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(sqlSession != null) {
                sqlSession.close();
            }
        }
        return board;
    }</code></pre>
<br>

<p><strong>BoardService.java</strong></p>
<pre><code class="language-java">package kosta.service;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import kosta.model.Board;
import kosta.model.BoardDao2;

public class BoardService {
    private static BoardService service = new BoardService();
    private static BoardDao2 dao;

    public static BoardService getInstance() {
        dao = BoardDao2.getInstance();
        return service;
    }

    public int insertBoardService(HttpServletRequest request)throws Exception {
        request.setCharacterEncoding(&quot;utf-8&quot;);
        Board board = new Board();
        board.setTitle(request.getParameter(&quot;title&quot;));
        board.setWriter(request.getParameter(&quot;writer&quot;));
        board.setContents(request.getParameter(&quot;contents&quot;));

        return dao.insertBoard(board);
    }

    public List&lt;Board&gt; listBoardService(HttpServletRequest request)throws Exception{
        List&lt;Board&gt; list = dao.listBoard();

        return list;
    }

    public Board detailBoard(int seq)throws Exception {

        return dao.detailBoard(seq);
    }
}

</code></pre>
<p><strong>Controller.java</strong></p>
<pre><code class="language-java">package kosta.controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kosta.action.Action;
import kosta.action.ActionForward;
import kosta.action.DetailAction;
import kosta.action.InsertAction;
import kosta.action.InsertFormAction;
import kosta.action.ListAction;

@WebServlet(&quot;/board/*&quot;)
public class MyController extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public MyController() {
        super();
    }

    public void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException  {
        //url 식별
        String requestURI = request.getRequestURI();  // /MVC/board/list.do
        String contextPath = request.getContextPath();
        String command = requestURI.substring(contextPath.length()+7);
        System.out.println(command);

        Action action = null;
        ActionForward forward = null;

        if(command.equals(&quot;insertForm.do&quot;)) {
            action = new InsertFormAction();
            try {
                forward = action.execute(request, response);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }else if(command.equals(&quot;insertAction.do&quot;)) {
            action = new InsertAction();
            try {
                forward = action.execute(request, response);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }else if(command.equals(&quot;listAction.do&quot;)) {
            action = new ListAction();
            try {
                forward = action.execute(request, response);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else if(command.equals(&quot;detailAction.do&quot;)) {
            action = new DetailAction();
            try {
                forward = action.execute(request, response);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        if(forward != null) {
            if(forward.isRedirect()) { //redirect
                response.sendRedirect(forward.getPath());
            }else { //Dispatcher
                RequestDispatcher dispatcher = request.getRequestDispatcher(forward.getPath());
                dispatcher.forward(request, response);
            }
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doProcess(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doProcess(request, response);
    }

}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[KOSTA] Spring 기반 Cloud 서비스 개발자 양성과정 50일차 - JDBC 실습 ]]></title>
            <link>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1%EA%B3%BC%EC%A0%95-50%EC%9D%BC%EC%B0%A8-JDBC-%EC%8B%A4%EC%8A%B5</link>
            <guid>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1%EA%B3%BC%EC%A0%95-50%EC%9D%BC%EC%B0%A8-JDBC-%EC%8B%A4%EC%8A%B5</guid>
            <pubDate>Wed, 13 Apr 2022 09:36:19 GMT</pubDate>
            <description><![CDATA[<p>📃 JDBC를 사용하여 오라클 DB내 데이터를 화면 출력
<img src="https://velog.velcdn.com/images/junbeomm-park/post/142f80a7-f972-4548-a887-e479c9ad6b1f/image.PNG" alt=""></p>
<p><strong>BoardDao.java</strong></p>
<pre><code class="language-java">public List&lt;Board&gt; listBoard() {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        List&lt;Board&gt; list = null; //ResultSet =&gt; Board =&gt; List

        String sql = &quot;select * from board order by seq desc&quot;;

        try {
            conn = getDBCPConnection();
            pstmt = conn.prepareStatement(sql);
            rs = pstmt.executeQuery();
            list = new ArrayList&lt;Board&gt;();

            while(rs.next()) {
                Board board = new Board(); //1객체 &lt;= 1로우
                board.setSeq(rs.getInt(&quot;seq&quot;));
                board.setTitle(rs.getString(&quot;title&quot;));
                board.setWriter(rs.getString(&quot;writer&quot;));
                board.setContents(rs.getString(&quot;contents&quot;));
                board.setRegdate(rs.getString(&quot;regdate&quot;));
                board.setHitcount(rs.getInt(&quot;hitcount&quot;));

                list.add(board);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(pstmt != null) {
                try {

                } catch (Exception e2) {}
            }
        }

        return list;
    }
</code></pre>
<p><strong>list.jsp</strong></p>
<pre><code class="language-jsp">&lt;%@page import=&quot;kosta.bean.Board&quot;%&gt;
&lt;%@page import=&quot;java.util.List&quot;%&gt;
&lt;%@page import=&quot;kosta.bean.BoardDao2&quot;%&gt;
&lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&gt;

&lt;%
    BoardDao2 dao = BoardDao2.getInstance();
    List&lt;Board&gt; list = dao.listBoard();
%&gt;
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;title&gt;Insert title here&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;a href=&quot;insert_form.jsp&quot;&gt;글쓰기&lt;/a&gt;
    &lt;table border=&quot;1&quot;&gt;
        &lt;tr&gt;
            &lt;td&gt;글번호&lt;/td&gt;
            &lt;td&gt;제목&lt;/td&gt;
            &lt;td&gt;작성자&lt;/td&gt;
            &lt;td&gt;작성일자&lt;/td&gt;
            &lt;td&gt;조회수&lt;/td&gt;
        &lt;/tr&gt;
        &lt;% for(int i = 0; i &lt; list.size(); i++) { 
                Board board = list.get(i);
        %&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;%= board.getSeq() %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;a href=&quot;detail.jsp?seq=&lt;%= board.getSeq() %&gt;&quot;&gt;&lt;%= board.getTitle() %&gt;&lt;/a&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= board.getWriter() %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= board.getRegdate() %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= board.getHitcount() %&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;%} %&gt;
    &lt;/table&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p><br><br>
📃 각 게시글에 대한 상세 정보 가져오기</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/43c20f4b-b8f3-4368-ad73-56166d7909ea/image.PNG" alt=""></p>
<p><strong>board.java</strong></p>
<pre><code class="language-java">    public Board detailBoard(int seq) {
        Board board = new Board();
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        String sql = &quot;select * from board where seq=?&quot;;

        try {
            conn = getDBCPConnection();
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, seq);
            rs = pstmt.executeQuery();

            if(rs.next()) {

                board.setSeq(rs.getInt(&quot;seq&quot;));
                board.setTitle(rs.getString(&quot;title&quot;));
                board.setWriter(rs.getString(&quot;writer&quot;));
                board.setContents(rs.getString(&quot;contents&quot;));
                board.setRegdate(rs.getString(&quot;regdate&quot;));
                board.setHitcount(rs.getInt(&quot;hitcount&quot;));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {

        }

        return board;
    }</code></pre>
<p><strong>detail.jsp</strong></p>
<pre><code class="language-jsp">&lt;%@page import=&quot;kosta.bean.Board&quot;%&gt;
&lt;%@page import=&quot;kosta.bean.BoardDao&quot;%&gt;
&lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&gt;

&lt;!-- 글번호 받기 String -&gt; int
    BoardDao 객체 구하기
    BoardDao detailBoard() 호출
    결과값을 화면에 적절히 출력 --&gt;    

&lt;%
    int seq = 1;
    if(request.getParameter(&quot;seq&quot;) != null){
        seq = Integer.parseInt(request.getParameter(&quot;seq&quot;));
    }

    BoardDao dao = BoardDao.getInstance();
    Board board = dao.detailBoard(seq);

%&gt;

&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;title&gt;Insert title here&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;%= board.getSeq() %&gt;&lt;/li&gt;
    &lt;li&gt;&lt;%= board.getTitle() %&gt;&lt;/li&gt;
    &lt;li&gt;&lt;%= board.getWriter() %&gt;&lt;/li&gt;
    &lt;li&gt;&lt;%= board.getContents() %&gt;&lt;/li&gt;
    &lt;li&gt;&lt;%= board.getHitcount() %&gt;&lt;/li&gt;

&lt;/ul&gt;
&lt;br&gt;

&lt;a href=&quot;updateForm.jsp?seq=&lt;%=seq%&gt;&quot;&gt;글수정&lt;/a&gt;

&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p><br><br></p>
<p>📃 글 내용 수정하기</p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/db2bedb1-6ecd-4e00-84a3-0720bf73a632/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/1fbf9aa5-bff1-4bde-95ce-6b65733dd335/image.PNG" alt=""></p>
<p><strong>BoardDao.java</strong></p>
<pre><code class="language-java">public int update(Board board) {
        int re = -1;
        Connection conn = null;
        PreparedStatement pstmt = null;

        String sql = &quot;update board set title=?,contents=? where seq=?&quot;;
        try {
            conn = getDBCPConnection();
            pstmt = conn.prepareStatement(sql);

            pstmt.setString(1, board.getTitle());
            pstmt.setString(2, board.getContents());
            pstmt.setInt(3, board.getSeq());

            re = pstmt.executeUpdate();

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(pstmt != null) {
                try {
                    pstmt.close();
                } catch (Exception e2) {}
            }
        }
        return re;
    }</code></pre>
<br>


<p><strong>updateForm.jsp</strong></p>
<pre><code class="language-jsp">&lt;%@page import=&quot;kosta.bean.Board&quot;%&gt;
&lt;%@page import=&quot;kosta.bean.BoardDao&quot;%&gt;
&lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&gt;

    &lt;%
    int seq = 1;
    if(request.getParameter(&quot;seq&quot;) != null){
        seq = Integer.parseInt(request.getParameter(&quot;seq&quot;));
    }

    BoardDao dao = BoardDao.getInstance();
    Board board = dao.detailBoard(seq);

%&gt;
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;title&gt;Insert title here&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h3&gt;글 수정 폼&lt;/h3&gt;
    &lt;form action=&quot;updateProc.jsp&quot; method=&quot;post&quot;&gt;
        &lt;input type=&quot;hidden&quot; name=&quot;seq&quot; value=&quot;&lt;%= board.getSeq()%&gt;&quot;&gt;
        작성자 : &lt;%= board.getWriter() %&gt;&lt;br&gt;
        제목 : &lt;input type=&quot;text&quot; name=&quot;title&quot; value=&quot;&lt;%= board.getTitle()%&gt;&quot;&gt;&lt;br&gt;
        내용 : &lt;br&gt;
        &lt;textarea rows=&quot;6&quot; cols=&quot;70&quot; name=&quot;contents&quot;&gt;&lt;%= board.getContents()%&gt;&lt;/textarea&gt;
        &lt;input type=&quot;submit&quot; value=&quot;수정완료&quot;&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<br>


<p><strong>updateProc.jsp</strong></p>
<pre><code class="language-jsp">&lt;%@page import=&quot;kosta.bean.BoardDao&quot;%&gt;
&lt;%@page import=&quot;java.sql.ResultSet&quot;%&gt;
&lt;%@page import=&quot;java.sql.PreparedStatement&quot;%&gt;
&lt;%@page import=&quot;java.sql.Connection&quot;%&gt;
&lt;%@page import=&quot;kosta.bean.Board&quot;%&gt;
&lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&gt;

&lt;%
    request.setCharacterEncoding(&quot;utf-8&quot;);
%&gt;
&lt;jsp:useBean id=&quot;board&quot; class=&quot;kosta.bean.Board&quot;/&gt;
&lt;jsp:setProperty property=&quot;*&quot; name=&quot;board&quot;/&gt;
&lt;%
    BoardDao dao = BoardDao.getInstance();
    int re = dao.update(board);

    if(re &gt; 0){
        response.sendRedirect(&quot;list.jsp&quot;);
    }

%&gt;
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;title&gt;Insert title here&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;/body&gt;
&lt;/html&gt;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] JDBC 사용하기]]></title>
            <link>https://velog.io/@junbeomm-park/Java-JDBC-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@junbeomm-park/Java-JDBC-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 13 Apr 2022 03:04:07 GMT</pubDate>
            <description><![CDATA[<h2 id="🤔-jdbcjava-database-connectivity-">🤔 JDBC(Java DataBase Connectivity) ?</h2>
<p>자바 어플리케이션에서도 직접 관계형 DBMS를 제어할 수 있다. 그러한 역할을 돕는 API가 JDBC(Java DataBase Connectivity) API이다. </p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/7facfd94-2f43-409c-b529-5ee2ebb5ca18/image.PNG" alt=""></p>
<h3 id="java-코드를-이용한-dbms-제어">Java 코드를 이용한 DBMS 제어</h3>
<p>** 1. JDBC 드라이버 로딩**</p>
<p><code>Class.forName(&quot;JDBC드라이버 이름&quot;);</code> 으로 JDBC 드라이버를 로딩한다.</p>
<ul>
<li>Oracle : &quot;jdbc:oracle:thin:@localhost:1521:XE&quot;</li>
<li>MySQL :  &quot;com.mysql.cj.jdbc.Driver&quot;</li>
</ul>
<br>

<p>** 2. Connection 객체 생성 **</p>
<p>로드한 JDBC 드라이버를 통해 관계형 DBMS와 연결하는 단계</p>
<ul>
<li>DriverManager : 관계형 DBMS와의 연결을 요청하는 <code>getConncetion</code> 메서드를 가짐</li>
<li>JDBC URL : DBMS와의 연결을 위한 식별값</li>
<li>Connection : 관계형 DBMS와 통신하는 메서드로 구성</li>
</ul>
<br>

<p>**
 3. Statement 객체 생성**</p>
<p>해당 객체는 쿼리를 생성 및 실행할 작업 영역을 제공</p>
<br>

<p>** 4. 쿼리수행**</p>
<p><br><br></p>
<h3 id="jdbc-기본적인-사용">JDBC 기본적인 사용</h3>
<h4 id="연결-테스트">연결 테스트</h4>
<pre><code class="language-java">package test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class ConnectionTest {
    public static void main(String[] args) {
        // java 표준인 java.sql.Connection 클래스를 import해야 한다.
        Connection conn = null;

        try{
            // 1. 드라이버 로딩
            // 드라이버 인터페이스를 구현한 클래스를 로딩
            // mysql, oracle 등 각 벤더사 마다 클래스 이름이 다르다.
            // mysql은 &quot;com.mysql.jdbc.Driver&quot;이며, 이는 외우는 것이 아니라 구글링하면 된다.
            // 참고로 이전에 연동했던 jar 파일을 보면 com.mysql.jdbc 패키지에 Driver 라는 클래스가 있다.
            Class.forName(&quot;com.mysql.jdbc.Driver&quot;);

            // 2. 연결하기
            // 드라이버 매니저에게 Connection 객체를 달라고 요청한다.
            // Connection을 얻기 위해 필요한 url 역시, 벤더사마다 다르다.
            // mysql은 &quot;jdbc:mysql://localhost/사용할db이름&quot; 이다.
            String url = &quot;jdbc:mysql://localhost/dev&quot;;

            // @param  getConnection(url, userName, password);
            // @return Connection
            conn = DriverManager.getConnection(url, &quot;dev&quot;, &quot;dev&quot;);
            System.out.println(&quot;연결 성공&quot;);

        }
        catch(ClassNotFoundException e){
            System.out.println(&quot;드라이버 로딩 실패&quot;);
        }
        catch(SQLException e){
            System.out.println(&quot;에러: &quot; + e);
        }
        finally{
            try{
                if( conn != null &amp;&amp; !conn.isClosed()){
                    conn.close();
                }
            }
            catch( SQLException e){
                e.printStackTrace();
            }
        }
    }
}</code></pre>
<p><br><br></p>
<h4 id="select-쿼리-실행">SELECT 쿼리 실행</h4>
<pre><code class="language-java">public class SelectTest {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        try{
            // 1. 드라이버 로딩
            Class.forName(&quot;com.mysql.jdbc.Driver&quot;);

            // 2. 연결하기
            String url = &quot;jdbc:mysql://localhost/dev&quot;;
            conn = DriverManager.getConnection(url, &quot;dev&quot;, &quot;dev&quot;);


            // 3. 쿼리 수행을 위한 Statement 객체 생성
            stmt = conn.createStatement();

            // 4. SQL 쿼리 작성
            // 주의사항
            // 1) JDBC에서 쿼리를 작성할 때는 세미콜론(;)을 빼고 작성한다.
            // 2) SELECT 할 때 * 으로 모든 칼럼을 가져오는 것보다
            //   가져와야 할 칼럼을 직접 명시해주는 것이 좋다.
            // 3) 원하는 결과는 쿼리로써 마무리 짓고, java 코드로 후작업 하는 것은 권하지 않음
            // 4) 쿼리를 한 줄로 쓰기 어려운 경우 들여쓰기를 사용해도 되지만 띄어쓰기에 유의 !!
            String sql = &quot;SELECT name, owner, date_format(birth, &#39;%Y년%m월%d일&#39; date FROM pet&quot;;


            // 5. 쿼리 수행
            // 레코드들은 ResultSet 객체에 추가된다.
            rs = stmt.executeQuery(sql);

            // 6. 실행결과 출력하기
            while(rs.next()){
                // 레코드의 칼럼은 배열과 달리 0부터 시작하지 않고 1부터 시작한다.
                // 데이터베이스에서 가져오는 데이터의 타입에 맞게 getString 또는 getInt 등을 호출한다.
                String name = rs.getString(1);
                String owner = rs.getString(2);
                String date = rs.getString(3);

                System.out.println(name + &quot; &quot; + owner + &quot; &quot; + date);
            }
        }
        catch( ClassNotFoundException e){
            System.out.println(&quot;드라이버 로딩 실패&quot;);
        }
        catch( SQLException e){
            System.out.println(&quot;에러 &quot; + e);
        }
        finally{
            try{
                if( conn != null &amp;&amp; !conn.isClosed()){
                    conn.close();
                }
                if( stmt != null &amp;&amp; !stmt.isClosed()){
                    stmt.close();
                }
                if( rs != null &amp;&amp; !rs.isClosed()){
                    rs.close();
                }
            }
            catch( SQLException e){
                e.printStackTrace();
            }
        }
    }
}
</code></pre>
<p><br><br></p>
<h4 id="insert-쿼리-실행">INSERT 쿼리 실행</h4>
<pre><code class="language-java">    public int insertBoard(Board board) {
        Connection conn = null;
        PreparedStatement pstmt = null;

        //url, user, password 
        String url = &quot;jdbc:oracle:thin:@localhost:1521:XE&quot;;
        String user = &quot;kosta236&quot;;
        String password = &quot;1234&quot;;

        String sql = &quot;insert into board values(board_seq.nextval,?,?,?,sysdate,0)&quot;;
        int re = -1;


        try {
            //1단계 : JDBC 드라이버 로딩 =&gt; 어떤 DB?
            Class.forName(&quot;oracle.jdbc.driver.OracleDriver&quot;);

            //2단계 : DB 연결 (Connenction 객체 생성)
            conn = DriverManager.getConnection(url, user, password);
            System.out.println(&quot;conn : &quot; + conn);

            //3단계 : PrepareStatement 객체 생성(SQL 질의)
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, board.getTitle());
            pstmt.setString(2, board.getWriter());
            pstmt.setString(3, board.getContents());

            //4단계 : SQL문 실행(re =&gt; 실행된 row 갯수)
            re = pstmt.executeUpdate(); //insert, update, delete

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(pstmt != null) {
                try {
                    pstmt.close();
                } catch (Exception e2) {}
            }
            if(conn != null) {
                try {
                    conn.close();
                } catch (Exception e2) {}
            }
        }//end finally

        return re;
    }//end insertBoard
}//end class
</code></pre>
<p>쿼리를 수행할 때 동적으로 할댕해야 하는 값이 있으면 <code>PreparedStatement</code> 객체를 사용하고, 동적으로 할당할 필요가 없으면 <code>Statement</code> 객체를 사용한다.</p>
<p>쿼리의 결과가 있으면 <code>executeQuery()</code> 메서드를 호출하여 <code>ResultSet</code> 객체에 담고, 쿼리의 결과가 없으면 <code>executeUpdate()</code> 메서드를 호출하여 int형 변수에 결과 값을 할당 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[KOSTA] Spring 기반 Cloud 서비스 개발자 양성 과정 49일차 - JSP 실습]]></title>
            <link>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-49%EC%9D%BC%EC%B0%A8-JSP-%EC%8B%A4%EC%8A%B5</link>
            <guid>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-49%EC%9D%BC%EC%B0%A8-JSP-%EC%8B%A4%EC%8A%B5</guid>
            <pubDate>Tue, 12 Apr 2022 06:26:18 GMT</pubDate>
            <description><![CDATA[<p>📃 내장객체 session을 이용한 장바구니
<img src="https://velog.velcdn.com/images/junbeomm-park/post/29e752ab-b90f-45a1-aef9-6ce026474fc9/image.PNG" alt=""></p>
<p><strong>login.jsp</strong></p>
<pre><code class="language-jsp">&lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot; pageEncoding=&quot;UTF-8&quot;%&gt;
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot;&gt;
&lt;title&gt;ch06 : login.jsp&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div align=&quot;center&quot;&gt;
    &lt;H2&gt;로그인&lt;/H2&gt;
    &lt;form name=&quot;form1&quot; method=&quot;POST&quot; action=&quot;selProduct.jsp&quot;&gt;
        &lt;input type=&quot;text&quot; name=&quot;username&quot;/&gt;
        &lt;input type=&quot;submit&quot; value=&quot;로그인&quot;/&gt;
    &lt;/form&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p><br><br></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/dd5c34ba-c004-4246-8ac0-6ac8e7a4f926/image.PNG" alt=""></p>
<p><strong>selProduct.jsp</strong></p>
<pre><code class="language-jsp">&lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot; pageEncoding=&quot;UTF-8&quot; import=&quot;java.util.*&quot;%&gt;
&lt;%
    request.setCharacterEncoding(&quot;utf-8&quot;);
    String username = request.getParameter(&quot;username&quot;);
    session.setAttribute(&quot;username&quot;, username);
%&gt;

&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt;
&lt;HTML&gt;
&lt;HEAD&gt;
&lt;title&gt;ch06 : selProduct.jsp&lt;/title&gt;
&lt;/head&gt;

&lt;body&gt;
&lt;div align=&quot;center&quot;&gt;
    &lt;H2&gt;상품선택&lt;/H2&gt;
    &lt;HR&gt;
    ${username } 님 환영합니다!!!!
    &lt;HR&gt;
    &lt;form name=&quot;form1&quot; method=&quot;POST&quot; action=&quot;add.jsp&quot;&gt;
        &lt;SELECT name=&quot;fruit&quot;&gt;
            &lt;option&gt;사과&lt;/option&gt;
            &lt;option&gt;귤&lt;/option&gt;
            &lt;option&gt;파인애플&lt;/option&gt;
            &lt;option&gt;자몽&lt;/option&gt;
            &lt;option&gt;레몬&lt;/option&gt;
        &lt;/SELECT&gt;
        가격 : &lt;input type=&quot;text&quot; name=&quot;price&quot;&gt;&lt;br&gt;
        수량 : &lt;input type=&quot;text&quot; name=&quot;amount&quot;&gt;&lt;br&gt;
        &lt;input type=&quot;submit&quot; value=&quot;추가&quot;/&gt;
    &lt;/form&gt;
    &lt;a href=&quot;checkOut.jsp&quot;&gt;계산&lt;/a&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;




</code></pre>
<p><br><br></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/bc85e4d1-31cc-47ab-88b6-68c6f526cf99/image.PNG" alt=""></p>
<p><strong>add.jsp</strong></p>
<pre><code class="language-jsp">&lt;%@page import=&quot;kosta.bean.Product&quot;%&gt;
&lt;%@page import=&quot;java.util.List&quot;%&gt;
&lt;%@page import=&quot;java.util.ArrayList&quot;%&gt;
&lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&gt;

    &lt;%! List&lt;Product&gt; list = new ArrayList&lt;Product&gt;(); %&gt;

    &lt;%
        request.setCharacterEncoding(&quot;utf-8&quot;);
    %&gt;

    &lt;jsp:useBean id=&quot;product&quot; class=&quot;kosta.bean.Product&quot;/&gt;
    &lt;jsp:setProperty property=&quot;*&quot; name=&quot;product&quot;/&gt;

    &lt;% 

        list = (List)session.getAttribute(&quot;productlist&quot;);

        if(list == null){
            list = new ArrayList&lt;Product&gt;();
            session.setAttribute(&quot;productlist&quot;, list);
        }

        list.add(product);

    %&gt;




&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot;&gt;
&lt;title&gt;Insert title here&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;a href=&quot;javascript:history.back()&quot;&gt;뒤로가기&lt;/a&gt;
    &lt;%=product.getFruit() %&gt;

&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p><br><br></p>
<p><img src="https://velog.velcdn.com/images/junbeomm-park/post/173257e2-b9d4-4dba-a53d-6df573242abe/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/junbeomm-park/post/9d37392e-84c8-4753-8e46-530969e63ca2/image.PNG" alt=""></p>
<p><strong>checkOut.jsp</strong></p>
<pre><code class="language-jsp">&lt;%@page import=&quot;kosta.bean.Product&quot;%&gt;
&lt;%@page import=&quot;java.util.List&quot;%&gt;
&lt;%@page import=&quot;java.util.ArrayList&quot;%&gt;
&lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&gt;
    &lt;%
        request.setCharacterEncoding(&quot;utf-8&quot;);

        List&lt;Product&gt; list = (List)session.getAttribute(&quot;productlist&quot;);

    /*     if(list == null){
            out.println(&quot;상품없음&quot;);
        }else{
            for(String fruit : list){
                out.println(fruit + &quot;&lt;br&gt;&quot;);
            }
        } */


    %&gt;


&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot;&gt;
&lt;title&gt;Insert title here&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;%
        if(list == null){
    %&gt;
        &lt;b&gt;선택한 상품이 없습니다.&lt;/b&gt;
    &lt;%    }else { %&gt;
        &lt;ul&gt;
    &lt;% 
            int total = 0;
            for(int i = 0; i &lt; list.size(); i++) {
                Product product = list.get(i);
                total += (product.getPrice() * product.getAmount());
    %&gt;
            &lt;li&gt;&lt;%= product.getFruit() %&gt; : &lt;%= product.getPrice() %&gt; * &lt;%= product.getAmount() %&gt; = &lt;%= (product.getPrice() * product.getAmount()) %&gt;&lt;/li&gt;
        &lt;%} %&gt;
        &lt;/ul&gt;
        &lt;br&gt;
        주문한 총 금액 : &lt;%= total %&gt; 원
    &lt;%} %&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Servlet & JSP] JSP 기초 문법]]></title>
            <link>https://velog.io/@junbeomm-park/Servlet-JSP-JSP-%EA%B8%B0%EC%B4%88-%EB%AC%B8%EB%B2%95</link>
            <guid>https://velog.io/@junbeomm-park/Servlet-JSP-JSP-%EA%B8%B0%EC%B4%88-%EB%AC%B8%EB%B2%95</guid>
            <pubDate>Fri, 08 Apr 2022 08:14:39 GMT</pubDate>
            <description><![CDATA[<h2 id="📘-jsp-기초-문법">📘 JSP 기초 문법</h2>
<p>JSP는 기본적으로 HTML 문서 안에 자바 언어를 삽입해 사용할 수 있도록 해준다.</p>
<p>그래서 실제로 대부분의 변수 선언, 메서드 선언, 로직 등은 자바 언어로 짜게 된다.</p>
<p>하지만 자바 코드를 HTML 사이에 끼워 넣을 때 필요한 문법이 몇가지 있다.</p>
<p><br><br></p>
<h3 id="1-스크립트릿scriptlet">1. 스크립트릿(Scriptlet)</h3>
<p><code>&lt;% %&gt;</code> 으로 시작하고 끝나는 태그</p>
<p>JSP 문법의 가장 기본이 되는 태그, 대부분의 JSP 문법 표현을 이 스크립트릿을 기본으로 한다.</p>
<p><code>&lt;% %&gt;</code> 사이에 실행될 자바 코드를 입력하면 된다.</p>
<br>

<pre><code class="language-html">&lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&gt;
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;title&gt;Insert title here&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
         &lt;!-- 1 ~ 100까지 합을 구하기 --&gt;
    &lt;%

        int sum = 0;

        for(int i = 1; i &lt;= 100; i++){
            sum += i;
        }
    %&gt;

&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p><br><br></p>
<h3 id="2-선언부declaration">2. 선언부(Declaration)</h3>
<p><code>&lt;%! %&gt;</code> 는 변수, 메서드 등을 선언할 때 이용하는 태그이다.</p>
<pre><code class="language-html">&lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&gt;
&lt;!DOCTYPE html&gt;

&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;title&gt;Insert title here&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;

    &lt;!-- 선언문(선언만 가능) --&gt;
    &lt;%! String name = &quot;홍길동&quot;; %&gt;
    &lt;%! public int plus(int a, int b){ return a+b; } %&gt;

&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p><br><br></p>
<h3 id="3-표현부expession">3. 표현부(Expession)</h3>
<p><code>&lt;%= %&gt;</code>는 변수, 메서드 등의 실행에 관한 부분을 맡아 그 결과를 표현한다.</p>
<pre><code class="language-html">&lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&gt;
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;title&gt;Insert title here&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;%
        int sum = 0;

        for(int i = 1; i &lt;= 100; i++){
            sum += i;
        }
    %&gt;

    &lt;!-- 구현부 (변수 선언, 변수 및 메서드에 대한 실행 가능) --&gt;
    &lt;h1&gt;1~100 까지 합 결과 : &lt;%= sum %&gt;&lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p><br><br></p>
<h3 id="4-jsp-지시어">4. JSP 지시어</h3>
<p>JSP 지시문은 서블릿 클래스의 전체 구조에 영향을 준다.</p>
<p>해당 JSP 파일을 어떻게 처리할지 정보 등을 기술한다.</p>
<p><img src="https://velog.velcdn.com/cloudflare/junbeomm-park/ec654af6-254e-47e0-b25a-299812bee69f/%EC%BA%A1%EC%B2%98.PNG" alt=""></p>
<p><br><br></p>
<h3 id="5-jsp-액션-태그">5. JSP 액션 태그</h3>
<p>JSP 문서 내에서 간단하게 다양한 구현을 할 수 있도록 만든 태그이다.</p>
<p><img src="https://velog.velcdn.com/cloudflare/junbeomm-park/e0f0c755-f9fb-47e1-8f4b-f1f4c08c78cf/%EC%BA%A1%EC%B2%98.PNG" alt=""></p>
<p><strong>참고자료</strong>
<a href="https://sgcomputer.tistory.com/228">https://sgcomputer.tistory.com/228</a>
<a href="https://atoz-develop.tistory.com/entry/JSP-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95-%EC%B4%9D-%EC%A0%95%EB%A6%AC-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%8D%B0%EC%9D%B4%ED%84%B0-JSP-%EC%A0%84%EC%9A%A9-%ED%83%9C%EA%B7%B8-%EB%82%B4%EC%9E%A5-%EA%B0%9D%EC%B2%B4">https://atoz-develop.tistory.com/entry/JSP-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95-%EC%B4%9D-%EC%A0%95%EB%A6%AC-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%8D%B0%EC%9D%B4%ED%84%B0-JSP-%EC%A0%84%EC%9A%A9-%ED%83%9C%EA%B7%B8-%EB%82%B4%EC%9E%A5-%EA%B0%9D%EC%B2%B4</a>
<a href="https://chlee21.tistory.com/149">https://chlee21.tistory.com/149</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Servlet & JSP] Dispatcher-Servlet (디스패처 서블릿)]]></title>
            <link>https://velog.io/@junbeomm-park/Servlet-JSP-Dispatcher-Servlet-%EB%94%94%EC%8A%A4%ED%8C%A8%EC%B2%98-%EC%84%9C%EB%B8%94%EB%A6%BF</link>
            <guid>https://velog.io/@junbeomm-park/Servlet-JSP-Dispatcher-Servlet-%EB%94%94%EC%8A%A4%ED%8C%A8%EC%B2%98-%EC%84%9C%EB%B8%94%EB%A6%BF</guid>
            <pubDate>Fri, 08 Apr 2022 07:41:00 GMT</pubDate>
            <description><![CDATA[<h2 id="🤔-dispatcher-servlet-">🤔 Dispatcher-Servlet ?</h2>
<p>디스패처 서블릿의 dispatch는 &quot;보내다&quot;라는 뜻이다.
디서패처 서블릿은 <span style="color:indianred"><strong>HTTP 프로토콜로 들어오는 모든 요청을 가장 먼저 받아 적합한 컨트롤러에 위임해주는 프론트 컨트롤러(Front Controller)</strong></span>  이다.</p>
<br>

<h3 id="dispatcher-servlet의-장점">Dispatcher-Servlet의 장점</h3>
<p>과거에 모든 서블릿을 URL 매핑을 위해 web.xml에 모두 등록해주어야 했지만, <span style="color:indianred"><strong>Dispatcher-Servlet은 해당 어플리케이션으로 들어오는 모든 요청을 핸들링 해주고 공통 작업을 처리</strong></span> 하면서 편리하게 이용할 수 있게 되었다. 즉, 컨트롤러를 구현해두기만 하면 Dispatcher-Servlet가 알아서 적합한 컨트롤러로 위임 해주는 구조가 되었다.</p>
<br>

<hr>
<h3 id="dispatcher-servlet-동작-과정">Dispatcher-Servlet 동작 과정</h3>
<p><img src="https://velog.velcdn.com/cloudflare/junbeomm-park/f9640aba-f12a-4ab1-96dd-fe026e2e5fa4/%EC%BA%A1%EC%B2%98.PNG" alt=""></p>
<ol>
<li>클라이언트의 요청을 디스패처 서블릿이 받음</li>
<li>요청 정보를 통해 요청을 위임할 컨트롤러를 찾음</li>
<li>요청을 컨트롤러로 위임할 핸들러 어댑터를 찾아서 전달</li>
<li>핸들러 어댑터가 컨트롤러로 요청을 위임</li>
<li>비지니스 로직 처리</li>
<li>컨트롤러가 반환값을 리턴</li>
<li>핸들러 어댑터가 반환값을 처리</li>
<li>서버의 응답을 클라이언트로 반환</li>
</ol>
<p><br><br></p>
<p><strong>결론</strong></p>
<p><span style="color:indianred"><strong>디스패처 서블릿을 통해 요청을 처리할 컨트롤러를 찾아서 위임하고, 그 결과를 받아온다.</strong></span></p>
<p><br><br></p>
<p><strong>예제</strong></p>
<pre><code class="language-java">@WebServlet(&quot;/CalServlet&quot;)
public class CalServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public CalServlet() {
        super();
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //num1, num2 값을 받아서 합을 구하기
        int num1, num2 = 0;
        String name = &quot;&quot;;

        request.setCharacterEncoding(&quot;utf-8&quot;); // 한글 깨짐 방지를 위한 인코딩 작업
        num1 = Integer.parseInt(request.getParameter(&quot;num1&quot;)); 
        num2 = Integer.parseInt(request.getParameter(&quot;num2&quot;));
        name = request.getParameter(&quot;userName&quot;);

        int result = num1 + num2;

        request.setAttribute(&quot;result&quot;, result); 
        request.setAttribute(&quot;userName&quot;, name);

        RequestDispatcher re = request.getRequestDispatcher(&quot;/basic/result.jsp&quot;);
        re.forward(request, response);
    }

}
</code></pre>
<p><strong>참고자료</strong>
<a href="https://mangkyu.tistory.com/18">https://mangkyu.tistory.com/18</a>
<a href="https://riimy.tistory.com/87">https://riimy.tistory.com/87</a>
<a href="https://velog.io/@seculoper235/2.-DispatcherServlet-%EC%9D%B4%EB%9E%80">https://velog.io/@seculoper235/2.-DispatcherServlet-%EC%9D%B4%EB%9E%80</a>
<a href="https://coder-in-war.tistory.com/entry/Spring-06-Spring-MVC-Framework%EC%99%80-Dispatcher-Servlet">https://coder-in-war.tistory.com/entry/Spring-06-Spring-MVC-Framework%EC%99%80-Dispatcher-Servlet</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Servlet & JSP] Servlet, JSP의 기본 개념 및 구조]]></title>
            <link>https://velog.io/@junbeomm-park/Servlet-JSP-Servlet-JSP%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90-%EB%B0%8F-%EA%B5%AC%EC%A1%B0</link>
            <guid>https://velog.io/@junbeomm-park/Servlet-JSP-Servlet-JSP%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90-%EB%B0%8F-%EA%B5%AC%EC%A1%B0</guid>
            <pubDate>Fri, 08 Apr 2022 07:10:36 GMT</pubDate>
            <description><![CDATA[<h2 id="🤔-servlet--jsp-">🤔 Servlet &amp; JSP ?</h2>
<p><strong>Servlet</strong></p>
<ol>
<li><code>.java</code> 인 파일</li>
<li>자바의 일반적인 클래스와 동일한 개념</li>
<li>웹을 다룰 수 있도록 해주는 <code>HttpServlet</code> 클래스를 상속받은 클래스를 의미</li>
</ol>
<p><strong>JSP</strong></p>
<ol>
<li><code>.jsp</code>인 파일</li>
<li>Java Server Page</li>
<li>HTML 문서 안에 자바 언어를 삽입해 사용할 수 있도록 해줌</li>
</ol>
<p>Servlet 과 JSP는 완전 다른 개념이 아니며, Servlet을 사용해 웹을 만들 경우 화면 인터페이스 구현이 워낙 까다로운 단점을 보완하기 위해 만든 스크립트 언어가 JSP라고 볼 수 있다.</p>
<h3 id="웹-어플리케이션-구조">웹 어플리케이션 구조</h3>
<p>논리적 구조 : WEB, WAS, DB
물리적 구조 : 사용자수 &amp; 서버스펙 &amp; 보안 &amp; 네트워크 구조 등에 따라 맞추어짐</p>
<ul>
<li>사용자가 URL(또는 IP)를 통해 Web 서버를 호출하고 요청사항을 객체(request)에 담아 전송</li>
<li>WEB 서버는 요청 객체(request)를 받아서 바로 처리하거나 WAS(어플리케이션 서버)로 객체 전달</li>
<li>WAS 서버는 요청에 대한 내용과 요청 객체(request)를 받아 적절히 처리(필요시 DB작업)</li>
<li>WAS 서버는 처리 후 결과를 응답 객체(response)에 담아 WEB서버로 회신</li>
<li>WEB 서버는 응답 객체(response)를 다시 사용자에게 회신</li>
<li>사용자의 브라우저는 WEB서버가 보내준 코드를 해석해 화면을 구성하여 출력</li>
</ul>
<p><br><br></p>
<h3 id="servler--jsp">Servler / JSP</h3>
<ol>
<li>JSP -&gt; Servlet 파일(<code>.java</code>) 파일로 변환</li>
<li>Servlet 파일로 직접 작성하는 것과 같은 코드로 변환</li>
<li>변환된 서블릿 파일을 다시 컴파일해 <code>.class</code> 파일로 만든 뒤 실행</li>
<li>실행 결과는 자바 언어가 모두 사라진 HTML 코드가 되 최종적으로 HTML로 변환되어 사용자에게 전달</li>
</ol>
<p><img src="https://velog.velcdn.com/cloudflare/junbeomm-park/3dea2d1a-2eea-4012-82f5-c62f52613e97/%EC%BA%A1%EC%B2%98.PNG" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[KOSTA] Spring 기반 Cloud 서비스 개발자 양성 과정 45 ~ 47일 - 웹 미니 프로젝트]]></title>
            <link>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-45-47%EC%9D%BC-%EC%9B%B9-%EB%AF%B8%EB%8B%88-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-45-47%EC%9D%BC-%EC%9B%B9-%EB%AF%B8%EB%8B%88-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Fri, 08 Apr 2022 01:03:26 GMT</pubDate>
            <description><![CDATA[<h1 id="📘-웹-미니-프로젝트">📘 웹 미니 프로젝트</h1>
<p>서비스 되고 있는 사이트 중 웹 표준을 지키지 않는 사이트를 선정해 리뉴얼</p>
<h2 id="선정-사이트">선정 사이트</h2>
<p><img src="https://velog.velcdn.com/cloudflare/junbeomm-park/82004bb2-3000-4486-9883-c9c21a11a7d2/%EC%BA%A1%EC%B2%98.PNG" alt=""></p>
<h3 id="선정-이유">선정 이유</h3>
<ol>
<li>가운데 정렬이 되지 않아 왼쪽으로 컨텐츠가 쏠려 있음</li>
<li>전체적인 디자인 old</li>
<li>모바일 화면 최적화 X</li>
<li>웹 표준 미준수</li>
</ol>
<p><img src="https://velog.velcdn.com/cloudflare/junbeomm-park/fdc2a80a-06d5-4b4c-8dfb-dcf45a220831/%EC%BA%A1%EC%B2%98.PNG" alt=""></p>
<p><br><br></p>
<hr>
<h2 id="화면-구상도">화면 구상도</h2>
<p><img src="https://velog.velcdn.com/cloudflare/junbeomm-park/45ddeae1-cef1-4a44-947a-ffe0198a1934/1.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/fae20b14-6d9e-4490-8bfa-6179d3ae65ce/2.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/dcd16b86-bd50-4d43-99b7-9d20eb6f8651/3.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/a9134198-6da1-4809-8d32-016511170c5b/4.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/c266a2ec-6d89-423c-92ac-a2d654d8066b/5.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/c56a92db-5631-4883-b792-e5dc07c65739/6.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/155f91b6-c53f-401d-a8a6-bdd632c9b297/7.PNG" alt=""></p>
<br>

<hr>
<h2 id="리뉴얼">리뉴얼</h2>
<p><img src="https://velog.velcdn.com/cloudflare/junbeomm-park/cc35eda0-c876-400d-bccb-35f1bfe32427/1.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/a64fb47a-5572-494c-b4d2-635fe42ec3c4/2.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/46276d8b-7483-4e21-9945-efa8864f76b8/7.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/c1a70e78-d16d-451c-8562-e83604423b34/8.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/4ce8f4a8-ba9d-4446-9ec1-f3f927b43a64/10.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/91e10beb-dd06-4f1d-ab8f-8881738d61f3/11.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/e6ee1466-0b3b-457b-9549-48ded9310562/12.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/a639c096-2ea0-463b-97eb-a93b13cc8806/13.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/13ffc2d1-5d02-4441-98ba-58e5aec56c95/14.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/1ed6bf97-1b3f-408f-88a1-c6f22772d3ee/15.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/7b37d791-d068-45e3-8e3e-2cc837af264c/16.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/a1822af6-4c1b-4872-bc80-d5fa8d815df6/17.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/5c0e4555-30a7-48ed-af43-41d34546945b/18.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/daf6a523-95a6-480d-b9a3-19b7102e059d/21.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/bec08371-8f9a-454f-b278-6a56bd8d153c/22.PNG" alt="">
<img src="https://velog.velcdn.com/cloudflare/junbeomm-park/e551677f-91bc-4fdd-b958-cc04c64d7b39/23.PNG" alt="">
<img src="blob:https://velog.io/0d0fdd7f-786b-4c3e-abfe-f613dd8a1150" alt="업로드중.."></p>
<br>

<hr>
<h2 id="느낀점">느낀점</h2>
<p>프로젝트 진행 하면서 JavaScript 활용 능력이 많이 부족 하다는 것을 느꼈다. HTML로 구조를 만들고 CSS로 보기 좋게 배치하거나 꾸미는 과정은 수월하게 진행 하였으나 JavaScript로 동적 컨텐츠 만드는데 어려움이 있었고 jQuery 활용 또한 미흡했다. 이번 프로젝트로 인해서 나의 부족한점을 명확하게 찾은 것 같아 좀 더 공부를 해야할 필요성을 느꼈다. 비록 백엔드 개발자를 지망하지만 프론트엔드 영역을 아예 모른다면 메리트가 없다 생각 한다. JavaScript 등으로 구현한  기능에 대해서 어떤 원리로 동작하는지 파악 할 줄 안다면 보다 더 경쟁력을 갖출 수 있을 것 같다는 생각이 든다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[KOSTA] Spring 기반 Cloud 서비스 개발자 양성 과정 44일차 - Ajax 실습]]></title>
            <link>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-44%EC%9D%BC%EC%B0%A8-Ajax-%EC%8B%A4%EC%8A%B5</link>
            <guid>https://velog.io/@junbeomm-park/KOSTA-Spring-%EA%B8%B0%EB%B0%98-Cloud-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%96%91%EC%84%B1-%EA%B3%BC%EC%A0%95-44%EC%9D%BC%EC%B0%A8-Ajax-%EC%8B%A4%EC%8A%B5</guid>
            <pubDate>Mon, 04 Apr 2022 10:57:55 GMT</pubDate>
            <description><![CDATA[<p>📃 step1  - .load() </p>
<p><img src="https://media.vlpt.us/images/junbeomm-park/post/c76d9264-ce17-4c28-8289-4b238fa3d67f/%EC%BA%A1%EC%B2%98.PNG" alt=""></p>
<pre><code class="language-java">$(function(){
    $(&#39;#letter-a a&#39;).click(function(){
        $(&#39;#dictionary&#39;).hide().load(&#39;a.html&#39;, function(){
            $(this).fadeIn();
        });

        return false;
    })
});
</code></pre>
<p><br><br></p>
<p>📃 step2 - getJSON()</p>
<p><img src="https://media.vlpt.us/images/junbeomm-park/post/b4bdad7e-aad7-4065-8c32-2899b8d91492/%EC%BA%A1%EC%B2%98.PNG" alt=""></p>
<pre><code class="language-java">$(function(){
    $(&#39;#letter-b a&#39;).click(function(){
        $.getJSON(&#39;b.json&#39;, function(data){ //callback함수의 파라미터 변수에는 서버의 결과값이 온다.
            //결과값: [{},{}] -&gt; 배열
            $(&#39;#dictionary&#39;).empty();
            $.each(data, function(index, item){
                var html = &#39;&lt;div class=&quot;entry&quot;&gt;&#39;;
                html += &#39;&lt;h3 class=&quot;term&quot;&gt;&#39; + item.term + &#39;&lt;/h3&gt;&#39;;
                html += &#39;&lt;div class=&quot;part&quot;&gt;&#39; + item.part + &#39;&lt;/div&gt;&#39;;
                html += &#39;&lt;div class=&quot;definition&quot;&gt;&#39; + item.definition + &#39;&lt;/div&gt;&#39;;
                html += &#39;&lt;/div&gt;&#39;;

                $(&#39;#dictionary&#39;).append(html);
            });
        });

        return false;
    });
});</code></pre>
<p><br><br></p>
<p>📃 step3 - getScript()</p>
<p><img src="https://media.vlpt.us/images/junbeomm-park/post/a12904fd-9587-4c26-b407-6914972b24f2/%EC%BA%A1%EC%B2%98.PNG" alt=""></p>
<pre><code class="language-java">$(function(){
    $(&#39;#letter-c a&#39;).click(function(){
        $.getScript(&#39;c.js&#39;);        
        return false;
    })
});</code></pre>
<p><br><br></p>
<p>📃 step4 - xml =&gt; HTML 변환, .get()</p>
<p><img src="https://media.vlpt.us/images/junbeomm-park/post/1cfa0d1b-45af-4c96-b548-caf85fc87a28/%EC%BA%A1%EC%B2%98.PNG" alt=""></p>
<pre><code class="language-java">$(function(){
    $(&#39;#letter-d a&#39;).click(function(){
        //xml =&gt; HTML변환
        $.get(&#39;d.xml&#39;, function(data){
            $(data).find(&#39;entry&#39;).each(function(index){
                $entry = $(this);
                var html = &#39;&lt;div class=&quot;entry&quot;&gt;&#39;;
                html += &#39;&lt;h3 class=&quot;term&quot;&gt;&#39; + $entry.attr(&#39;term&#39;) + &#39;&lt;/h3&gt;&#39;;
                html += &#39;&lt;div class=&quot;part&quot;&gt;&#39; + $entry.attr(&#39;part&#39;) + &#39;&lt;/div&gt;&#39;;
                html += &#39;&lt;div class=&quot;definition&quot;&gt;&#39; + $entry.find(&#39;definition&#39;).text() + &#39;&lt;/div&gt;&#39;;
                html += &#39;&lt;/div&gt;&#39;;

                $(&#39;#dictionary&#39;).append(html);
            })
        });

        return false;
    })
});
</code></pre>
<p><br><br></p>
<p>📃 step5 - $.ajax()
<img src="https://media.vlpt.us/images/junbeomm-park/post/5f42ef81-0fad-4140-ac98-41039a699be8/%EC%BA%A1%EC%B2%98.PNG" alt=""></p>
<pre><code class="language-java">$(function(){
    $(&#39;#letter-f form&#39;).submit(function(){
        $.ajax({
            url : &#39;server3.jsp&#39;,
            type : &#39;post&#39;,
            data : $(this).serialize(),
            dataType : &#39;text&#39;,
            success : function(data){
                $(&#39;#dictionary&#39;).text(data);
            }
        })
        return false;
    });
});
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] Ajax]]></title>
            <link>https://velog.io/@junbeomm-park/JavaScript-Ajax</link>
            <guid>https://velog.io/@junbeomm-park/JavaScript-Ajax</guid>
            <pubDate>Mon, 04 Apr 2022 10:48:58 GMT</pubDate>
            <description><![CDATA[<h1 id="🤔-ajax-">🤔 Ajax ?</h1>
<p>Ajax란 Asynchronous JavaScript and XML의 약자이다.
Ajax는 빠르게 동작하는 동적인 웹 페이지를 만들기 위한 개발 기법 중 하나이다.</p>
<p>Ajax는 웹 페이지 전체를 다시 로딩하지 않고도, 웹 페이지의 일부분만을 갱신할 수 있다.
즉 Ajax를 이용하면 백그라운드 영역에서 서버와 통신하여, 그 결과를 웹 페이지의 일부분에만 표시할 수 있다.</p>
<p>이때 JSON, XML, HTML, 텍스트 파일 등과 같은 형태의 데이터를 주고받을 수 있다.</p>
<p><strong>Ajax의 장점</strong></p>
<p>Ajax를 이용하면 여러 장점이 있다.</p>
<ol>
<li>웹 페이지 전체를 다시 로딩하지 않고도, 웹 페이지의 일부분만을 갱신할 수 있다.</li>
<li>웹 페이지가 로드된 후에 서버로 데이터 요청을 보낼 수 있다.</li>
<li>웹 페이지가 로드된 후에 서버로 부터 데이터를 받을 수 있다.</li>
<li>백그라운드 영역에서 서버로 데이터를 보낼 수 있다.</li>
</ol>
<br>

<p><strong>Ajax의 한계</strong></p>
<p>Ajax를 이용하면 여러 장점을 가지지만, Ajax로도 다음과 같은 일들은 처리할 수 없다.</p>
<ol>
<li>Ajax는 클라이언트가 서버에 데이터를 요청하는 클라이언트 풀링 방식을 사용해, 서버 푸시 방식의 실시간 서비스는 만들 수 없다.</li>
<li>Ajax 스크립트가 포함된 서버가 아닌 다른 서버로 Ajax 요청을 보낼 수 없다.</li>
<li>클라이언트의 PC로 Ajax 요청을 보낼 수 없다.</li>
</ol>
<p><br><br></p>
<h3 id="ajax의-동작-원리">Ajax의 동작 원리</h3>
<p><img src="https://media.vlpt.us/images/junbeomm-park/post/e1885797-86b7-4d5b-82c6-d0d4fa469b29/%EC%BA%A1%EC%B2%98.PNG" alt=""></p>
<p><br><br></p>
<hr>
<h2 id="ajax에-관련된-jquery-커맨드">Ajax에 관련된 jQuery 커맨드</h2>
<h3 id="loadurl-parmeters-callback">load(url, parmeters, callback)</h3>
<p>URL과 매개변수로 Ajax요청을 전송, callback 함수는 요청 완료시 호출, 응답 텍스트는 일치하는 엘리먼트의 컨턴체를 대체하고 HTML 결과값일 경우 사용에 용이하다.</p>
<p><code>url</code> : 요청이 전송되는 서버측 URL
<code>parameters</code> : URL에 전달하고자 하는 data
<code>callback</code> : 응답 결과 데이터가 일치하는 엘리먼트로 로드 된 이후 호출 되는 함수</p>
<br>

<p><strong>예제</strong></p>
<pre><code class="language-java">$(function(){
    $(&#39;#letter-a a&#39;).click(function(){ 
        $(&#39;#dictionary&#39;).hide().load(&#39;a.html&#39;, function(){
            $(this).fadeIn();
        });

        return false;
    })
});</code></pre>
<p><br><br></p>
<h3 id="geturl-parameters-callback-posturl-parameters-callback">get(url, parameters, callback), post(url, parameters, callback)</h3>
<p>URL을 사용하여 서버에 대한 GET,POST 요청을 전송
매개변수는 쿼리 문자열로 전달</p>
<p><code>url</code> : 요청이 전송되는 서버측 URL
<code>parameters</code> : URL에 덧붙이는 쿼리 문자열을 구성하기 위한 이름과 값의 쌍으로 프로퍼티를 지닌 객체
<code>callback</code> : 응답 결과 데이터가 일치하는 엘리먼트로 로드 된 이후 호출 되는 함수</p>
<br>
<br>

<h3 id="getjsonurl-parameters-callback">$.getJSON(url, parameters, callback)</h3>
<p>URL을 사용하여 서버에 대한 GET 요청을 전송
매개변수는 쿼리 문자열로 전달
응답은 JSON 문자열로 해석되며 결과는 callback함수에 전달</p>
<p><code>url</code> : 요청이 전송되는 서버측 URL
<code>parameters</code> : URL에 덧붙이는 쿼리 문자열을 구성하기 위한 이름과 값의 쌍으로 프로퍼티를 지닌 객체
<code>callback</code> : 응답 결과 데이터가 일치하는 엘리먼트로 로드 된 이후 호출 되는 함수</p>
<br>

<p>** 예제 **</p>
<pre><code class="language-java">$(function(){
    $(&#39;#letter-b a&#39;).click(function(){
        $.getJSON(&#39;b.json&#39;, function(data){ //callback함수의 파라미터 변수에는 서버의 결과값이 온다.
            //결과값: [{},{}] -&gt; 배열
            $(&#39;#dictionary&#39;).empty();
            $.each(data, function(index, item){
                var html = &#39;&lt;div class=&quot;entry&quot;&gt;&#39;;
                html += &#39;&lt;h3 class=&quot;term&quot;&gt;&#39; + item.term + &#39;&lt;/h3&gt;&#39;;
                html += &#39;&lt;div class=&quot;part&quot;&gt;&#39; + item.part + &#39;&lt;/div&gt;&#39;;
                html += &#39;&lt;div class=&quot;definition&quot;&gt;&#39; + item.definition + &#39;&lt;/div&gt;&#39;;
                html += &#39;&lt;/div&gt;&#39;;

                $(&#39;#dictionary&#39;).append(html);
            });
        });

        return false;
    });
});</code></pre>
<p><br><br></p>
<h3 id="ajaxoptions">$.ajax(options)</h3>
<p>options를 통해 Ajax 요청을 전송</p>
<p><code>options</code> : 요청에 대한 매개변수를 정의 하는 프로퍼티 객체</p>
<pre><code class="language-java">$.ajax({
    url : &#39;b.json&#39;,
    type : &#39;get&#39;,
    dataType : &#39;json&#39;,
    success : function(data){
    }

    ...
})</code></pre>
<p><img src="https://media.vlpt.us/images/junbeomm-park/post/d6d94380-d605-4906-b93c-90d582a4592b/%EC%BA%A1%EC%B2%98.PNG" alt="">
<img src="https://media.vlpt.us/images/junbeomm-park/post/59c452b7-eee3-4325-8836-f9f7715bdd1a/%EC%BA%A1%EC%B2%98.PNG" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>