<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>✿∘˚˳&amp;deg;∘&amp;deg;</title>
    <link>https://recordev.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 24 Aug 2026 10:35:16 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>_HYE_</managingEditor>
    <image>
      <title>✿∘˚˳&amp;deg;∘&amp;deg;</title>
      <url>https://tistory1.daumcdn.net/tistory/5481530/attach/0b5ebe52e6e44c219fd44b26a57086dd</url>
      <link>https://recordev.tistory.com</link>
    </image>
    <item>
      <title>[NOTION] GIT</title>
      <link>https://recordev.tistory.com/77</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.notion.so/GIT-0b15257bc1df4838af9c69ac71ba6fc9&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.notion.so/GIT-0b15257bc1df4838af9c69ac71ba6fc9&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개인공부</category>
      <author>_HYE_</author>
      <guid isPermaLink="true">https://recordev.tistory.com/77</guid>
      <comments>https://recordev.tistory.com/77#entry77comment</comments>
      <pubDate>Mon, 26 Jun 2023 16:43:08 +0900</pubDate>
    </item>
    <item>
      <title>81일차 :  ajax, 에러처리, 웹소켓</title>
      <link>https://recordev.tistory.com/75</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;20230324&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Ajax&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ajax사용을 위한 GSON라이브러리 추가&lt;/p&gt;
&lt;pre id=&quot;code_1679621208367&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;		&amp;lt;!-- GSON 라이브러리 추가 --&amp;gt;
		&amp;lt;!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --&amp;gt;
		&amp;lt;dependency&amp;gt;
		    &amp;lt;groupId&amp;gt;com.google.code.gson&amp;lt;/groupId&amp;gt;
		    &amp;lt;artifactId&amp;gt;gson&amp;lt;/artifactId&amp;gt;
		    &amp;lt;version&amp;gt;2.10.1&amp;lt;/version&amp;gt;
		&amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1 - 1 ) 비밀번호 변경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 비밀번호는 마이페이지에서 바로변경X 암호화때문에 굉장히 복잡하기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러므로 비밀번호 변경페이지를 새로 만들어줄 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정한 mypage.jsp&lt;/p&gt;
&lt;pre id=&quot;code_1679621282285&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;마이페이지&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;form action=&quot;/updateMember.do&quot; method=&quot;post&quot;&amp;gt;
		&amp;lt;fieldset&amp;gt;
			&amp;lt;legend&amp;gt;회원정보&amp;lt;/legend&amp;gt;
			회원번호 : &amp;lt;input type=&quot;text&quot; name=&quot;memberNo&quot; value=&quot;${sessionScope.m.memberNo }&quot; readonly&amp;gt;&amp;lt;br&amp;gt;
			아이디 : &amp;lt;input type=&quot;text&quot; name=&quot;memberId&quot; value=&quot;${sessionScope.m.memberId }&quot; readonly&amp;gt;&amp;lt;br&amp;gt;
			비밀번호 : &amp;lt;button type=&quot;button&quot; onclick=&quot;pwChange();&quot;&amp;gt;비밀번호 변경하기&amp;lt;/button&amp;gt;&amp;lt;br&amp;gt;
			&amp;lt;%-- 비밀번호 : &amp;lt;input type=&quot;password&quot; name=&quot;memberPw&quot; value=&quot;${sessionScope.m.memberPw }&quot; &amp;gt;&amp;lt;br&amp;gt;--%&amp;gt;
			이름 : &amp;lt;input type=&quot;text&quot; name=&quot;memberName&quot; value=&quot;${sessionScope.m.memberName }&quot; readonly&amp;gt;&amp;lt;br&amp;gt;
			전화번호 : &amp;lt;input type=&quot;text&quot; name=&quot;memberPhone&quot; value=&quot;${sessionScope.m.memberPhone }&quot;&amp;gt;&amp;lt;br&amp;gt;
			이메일 : &amp;lt;input type=&quot;text&quot; name=&quot;memberEmail&quot; value=&quot;${sessionScope.m.memberEmail }&quot; &amp;gt;&amp;lt;br&amp;gt;
			&amp;lt;input type=&quot;submit&quot; value=&quot;정보수정&quot;&amp;gt;
		&amp;lt;/fieldset&amp;gt;
	&amp;lt;/form&amp;gt;
	&amp;lt;a href=&quot;/&quot;&amp;gt;메인으로&amp;lt;/a&amp;gt;
	&amp;lt;script&amp;gt;
		function pwChange(){
			location.href=&quot;/pwChangeFrm.do&quot;;
		}
	&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비밀번호변경페이지 pwChange.jsp(여기서 페이지이동없이 ajax로 데이터를 처리해줄것)&lt;/p&gt;
&lt;pre id=&quot;code_1679621336069&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;script src=&quot;https://code.jquery.com/jquery-3.6.1.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;style&amp;gt;
	#pwChangeFrm{
		display: none;
	}
&amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;비밀번호 변경&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	현재 비밀번호 입력 : &amp;lt;input type=&quot;password&quot; name=&quot;currentPw&quot;&amp;gt;
	&amp;lt;button type=&quot;button&quot; id=&quot;checkBtn&quot;&amp;gt;입력&amp;lt;/button&amp;gt;
	&amp;lt;%--현재 비밀번호를 입력해서 ajax를 통해 확인 후 비밀번호가 맞을 경우에 form태그를 보여줄것 --%&amp;gt;
	&amp;lt;form action=&quot;/pwChange.do&quot; method=&quot;post&quot; id=&quot;pwChangeFrm&quot;&amp;gt;
		&amp;lt;input type=&quot;hidden&quot; name=&quot;memberId&quot; value=&quot;${sessionScope.m.memberId }&quot;&amp;gt;
		비밀번호 : &amp;lt;input type=&quot;password&quot; name=&quot;memberPw&quot;&amp;gt;&amp;lt;br&amp;gt;
		비밀번호 확인 : &amp;lt;input type=&quot;password&quot; name=&quot;memberPwRe&quot;&amp;gt;&amp;lt;br&amp;gt;
		&amp;lt;input type=&quot;submit&quot; value=&quot;비밀번호 변경하기&quot; onclick=&quot;return checkPw();&quot;&amp;gt;
	&amp;lt;/form&amp;gt;
	
	&amp;lt;script&amp;gt;
		$(&quot;#checkBtn&quot;).on(&quot;click&quot;, function(){
			const memberPw = $(&quot;[name=currentPw]&quot;).val();
			const memberId = $(&quot;[name=memberId]&quot;).val();
			$.ajax({
				url : &quot;/pwCheck.do&quot;,
				type : &quot;post&quot;,
				data : {memberId:memberId, memberPw:memberPw},
				success : function(data){
					if(data == &quot;ok&quot;){
						$(&quot;#pwChangeFrm&quot;).slideDown();
					}else{
						alert(&quot;비밀번호를 확인하세요&quot;);
					}
				},
				error : function(){
					console.log(&quot;실패&quot;);
				}
			});
		});
		
		function checkPw(){
			const pw = $(&quot;[name=memberPw]&quot;).val();
			const pwRe = $(&quot;[name=memberPwRe]&quot;).val();
			if(pw != pwRe){
				alert(&quot;비밀번호를 확인하세요.&quot;)
				return false;
			}
		}
	&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ajax에서 이동하는 Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679621392822&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	//페이지 이동이 아닌 값 자체를 return하는 코드가 된다.
	@ResponseBody
	@RequestMapping(value=&quot;/pwCheck.do&quot;)
	public String pwCheck(Member member) {
		//아이디&amp;amp;패스워드로 회원을 조회해주는 로그인 로직을 이용할것 -&amp;gt; 암호화도 된다
		Member m = service.selectOneMember(member);
		if(m != null) {
			//상단에 ResponseBody를 붙여줬으므로 페이지이동X 값만 넘겨준다.
			return &quot;ok&quot;;
		}else {
			return &quot;error&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 비밀번호 update를 진행할 Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679621430223&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/pwChange.do&quot;)
	public String pwChange(Member member, String memberPwRe) {
		int result = service.updateMemberPw(member, memberPwRe);
		if(result &amp;gt; 0) {
			return &quot;redirect:/&quot;;
		}else {
			return &quot;redirect:/updateMember.do&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service - update이기 때문에 트랜잭션관리를 해줄 것&lt;/p&gt;
&lt;pre id=&quot;code_1679621480998&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@Transactional
	public int updateMemberPw(Member member, String memberPwRe) {
		return dao.updateMemberPw(member);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679621493998&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int updateMemberPw(Member member) {
		int result = sqlSession.update(&quot;member.pwChangeMember&quot;, member);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;memberSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679621521934&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  	&amp;lt;update id=&quot;pwChangeMember&quot; parameterType=&quot;m&quot;&amp;gt;
  		update member_tbl set member_pw = #{memberPw} where member_id = #{memberId}
  	&amp;lt;/update&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1 - 2 ) 회원가입 시 아이디 중복체크&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가한 joinFrm.jsp - 아이디 input태그 옆에 span태그를 추가하고 ajax코드를 추가하였다&lt;/p&gt;
&lt;pre id=&quot;code_1679621563845&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;script src=&quot;https://code.jquery.com/jquery-3.6.1.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;회원가입&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;form action=&quot;/join.do&quot; method=&quot;post&quot;&amp;gt;
		&amp;lt;fieldset&amp;gt;
			&amp;lt;legend&amp;gt;회원가입&amp;lt;/legend&amp;gt;
			아이디 : &amp;lt;input type=&quot;text&quot; name=&quot;memberId&quot;&amp;gt;&amp;lt;span id=&quot;idChk&quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br&amp;gt;
			비밀번호 : &amp;lt;input type=&quot;password&quot; name=&quot;memberPw&quot;&amp;gt;&amp;lt;br&amp;gt;
			이름 : &amp;lt;input type=&quot;text&quot; name=&quot;memberName&quot;&amp;gt;&amp;lt;br&amp;gt;
			전화번호 : &amp;lt;input type=&quot;text&quot; name=&quot;memberPhone&quot;&amp;gt;&amp;lt;br&amp;gt;
			이메일 : &amp;lt;input type=&quot;text&quot; name=&quot;memberEmail&quot;&amp;gt;&amp;lt;br&amp;gt;
			&amp;lt;input type=&quot;submit&quot; value=&quot;회원가입&quot;&amp;gt;
			&amp;lt;input type=&quot;reset&quot; value=&quot;취소&quot;&amp;gt;
		&amp;lt;/fieldset&amp;gt;
	&amp;lt;/form&amp;gt;
	&amp;lt;a href=&quot;/&quot;&amp;gt;메인으로&amp;lt;/a&amp;gt;
	
	&amp;lt;script&amp;gt;
		$(&quot;[name=memberId]&quot;).on(&quot;change&quot;, function(){
			const memberId = $(this).val();
			$.ajax({
				url : &quot;/idCheck.do&quot;,
				type : &quot;get&quot;,
				data : {memberId : memberId},
				success : function(data){
					if(data == &quot;ok&quot;){
						$(&quot;#idChk&quot;).text(&quot;사용 가능한 아이디 입니다.&quot;);
						$(&quot;#idChk&quot;).css(&quot;color&quot;, &quot;blue&quot;);
					}else{
						$(&quot;#idChk&quot;).text(&quot;이미 사용중인 아이디 입니다.&quot;);
						$(&quot;#idChk&quot;).css(&quot;color&quot;, &quot;red&quot;);
					}
				}
			});
		});
	&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ajax에서 이동하는 Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679621606717&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@ResponseBody
	@RequestMapping(value=&quot;/idCheck.do&quot;)
	public String idCheck(Member member) {
		//매개변수를 String memberId로 받아도 된다
		//Member를 사용하는 이유는 Service에서 메소드를 재사용하려고(아이디찾는 메소드가 이미 있기때문에)
		Member m = service.selectOneMemberId(member);
		if( m == null ) {
			//아이디 사용가능
			return &quot;ok&quot;;
		}else {
			//아이디 중복
			return &quot;dup&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1 - 3 ) ajax로 전체회원 조회하기(객체를 받기)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체를 받기 위해서는 GSON이 필요, 이를 위에 제일처음 라이브러리를 추가해줬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;index.jsp에 추가한 코드&lt;/p&gt;
&lt;pre id=&quot;code_1679621715677&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;			&amp;lt;button id=&quot;allMemberAjax&quot;&amp;gt;전체회원조회&amp;lt;/button&amp;gt;
			&amp;lt;div id=&quot;ajaxResult&quot;&amp;gt;&amp;lt;/div&amp;gt;
			
			&amp;lt;script&amp;gt;
				$(&quot;#allMemberAjax&quot;).on(&quot;click&quot;, function(){
					$.ajax({
						url : &quot;/ajaxAllMember.do&quot;,
						//ajax요청에 의한 데이터를 되돌려 줄 때 문제점2
						//1. 문자열 형식 -&amp;gt; 객체로변경 
						//ajax에서 json을 선언해줘도되지만 이러면 한글이 깨짐 -&amp;gt; 따로인코딩을 해줘야함
						//2. 한글깨짐
						//이 두가지를 동시에 해결하기 위해 Controller에서 진행
						success : function(data){
							$(&quot;#ajaxResult&quot;).empty();
							const table = $(&quot;&amp;lt;table&amp;gt;&quot;);
							const titleTr = $(&quot;&amp;lt;tr&amp;gt;&quot;);
							titleTr.html(&quot;&amp;lt;th&amp;gt;번호&amp;lt;/th&amp;gt;th&amp;gt;아이디&amp;lt;/th&amp;gt;th&amp;gt;이름&amp;lt;/th&amp;gt;th&amp;gt;전화번호&amp;lt;/th&amp;gt;&quot;);
							table.append(titleTr);
							for(let i=0; i&amp;lt;data.length; i++){
								const tr = $(&quot;&amp;lt;tr&amp;gt;&quot;);
								tr.append(&quot;&amp;lt;td&amp;gt;&quot;+data[i].memberNo+&quot;&amp;lt;/td&amp;gt;&quot;);
								tr.append(&quot;&amp;lt;td&amp;gt;&quot;+data[i].memberId+&quot;&amp;lt;/td&amp;gt;&quot;);
								tr.append(&quot;&amp;lt;td&amp;gt;&quot;+data[i].memberName+&quot;&amp;lt;/td&amp;gt;&quot;);
								tr.append(&quot;&amp;lt;td&amp;gt;&quot;+data[i].memberPhone+&quot;&amp;lt;/td&amp;gt;&quot;);
								table.append(tr);
							}
							$(&quot;#ajaxResult&quot;).append(table);
						}
					});
				});
			&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ajax에서 이동하는 Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679621735341&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	//application/json;charset=utf-8 되돌려주는타입이 Json이고 한글타입임을 명시
	@ResponseBody
	@RequestMapping(value=&quot;/ajaxAllMember&quot;, produces = &quot;application/json;charset=utf-8&quot;)
	public String ajaxAllMember() {
		
		ArrayList&amp;lt;Member&amp;gt; list = service.selectAllMember();
		Gson gson = new Gson();
		String result = gson.toJson(list);
		System.out.println(result);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 에러처리 ( 많이 본 에러 : 500, 400, 404 ) &lt;br /&gt;&lt;br /&gt;Http&amp;nbsp;Response.Status&amp;nbsp; &lt;br /&gt;[ 2xx ] -&amp;gt; 정상적으로 페이지가 떳을 때 &lt;br /&gt;200 ok &lt;br /&gt;[ 3xx ] -&amp;gt; redirect &lt;br /&gt;---------------------------------------------------------------------- &lt;br /&gt;[ 4xx ] -&amp;gt; 클라이언트가 잘못한 거 &lt;br /&gt;400&amp;nbsp; -&amp;gt;&amp;nbsp;bad&amp;nbsp;request(잘못된&amp;nbsp;요청) &lt;br /&gt;404 -&amp;gt;&amp;nbsp;not&amp;nbsp;found(사용자가&amp;nbsp;잘못하는&amp;nbsp;경우,&amp;nbsp;개발자잘못) &lt;br /&gt;-&amp;gt;&amp;nbsp;1)&amp;nbsp;Controller를&amp;nbsp;잘못요청하는&amp;nbsp;경우(주소창잘못요청) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;사용자가&amp;nbsp;잘못했을&amp;nbsp;수도&amp;nbsp;있고,&amp;nbsp;개발중에&amp;nbsp;실수가&amp;nbsp;있을&amp;nbsp;수도&amp;nbsp;있음 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(사용자의&amp;nbsp;잘못일&amp;nbsp;수도&amp;nbsp;있으니&amp;nbsp;에러페이지로&amp;nbsp;처리) &lt;br /&gt;-&amp;gt;&amp;nbsp;2)&amp;nbsp;Controller에서&amp;nbsp;리턴하는&amp;nbsp;JSP를&amp;nbsp;만들지&amp;nbsp;않았거나&amp;nbsp;오타가&amp;nbsp;있는&amp;nbsp;경우 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;100%&amp;nbsp;개발자의&amp;nbsp;실수&amp;nbsp;-&amp;gt;&amp;nbsp;에러페이지로&amp;nbsp;처리하면&amp;nbsp;안됨&amp;nbsp;-&amp;gt;&amp;nbsp;소스코드수정 &lt;br /&gt;&lt;br /&gt;[ 5xx ]&amp;nbsp; -&amp;gt; 서버에서 에러난거 &lt;br /&gt;500 -&amp;gt;&amp;nbsp;정보가&amp;nbsp;유출가능성이&amp;nbsp;있음&amp;nbsp;-&amp;gt;&amp;nbsp;소스코드&amp;nbsp;수정 &lt;br /&gt;502 -&amp;gt;&amp;nbsp;bad&amp;nbsp;gateway(서버터졌을때)&amp;nbsp;:&amp;nbsp;그냥&amp;nbsp;에러페이지를&amp;nbsp;띄우느&amp;nbsp;사이트도&amp;nbsp;있지만&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;접속자가&amp;nbsp;많다는&amp;nbsp;페이지로&amp;nbsp;빼는&amp;nbsp;사이트도&amp;nbsp;있다. &lt;br /&gt;&lt;br /&gt;404와&amp;nbsp;500은&amp;nbsp;발생하면&amp;nbsp;안되므로&amp;nbsp;에러처리를&amp;nbsp;해줄&amp;nbsp;것&amp;nbsp; &lt;br /&gt;처리하는&amp;nbsp;방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 web.xml 의 &amp;lt;servlet&amp;gt;&amp;lt;/servlet&amp;gt; 사이에 에러관련 설정을 추가해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1679621870525&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;servlet&amp;gt;
    		&amp;lt;!-- 프로젝트 생성 시 기본 설정 --&amp;gt;
		&amp;lt;servlet-name&amp;gt;appServlet&amp;lt;/servlet-name&amp;gt;
		&amp;lt;servlet-class&amp;gt;org.springframework.web.servlet.DispatcherServlet&amp;lt;/servlet-class&amp;gt;
		&amp;lt;init-param&amp;gt;
			&amp;lt;param-name&amp;gt;contextConfigLocation&amp;lt;/param-name&amp;gt;
			&amp;lt;param-value&amp;gt;/WEB-INF/spring/appServlet/servlet-context.xml&amp;lt;/param-value&amp;gt;
		&amp;lt;/init-param&amp;gt;
		&amp;lt;!-- 에러처리를 위한 추가 설정 --&amp;gt;
		&amp;lt;init-param&amp;gt;
			&amp;lt;param-name&amp;gt;throwExceptionIfNoHandlerFound&amp;lt;/param-name&amp;gt;
			&amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt;
		&amp;lt;/init-param&amp;gt;
		&amp;lt;load-on-startup&amp;gt;1&amp;lt;/load-on-startup&amp;gt;
	&amp;lt;/servlet&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에러 관련 class&lt;/p&gt;
&lt;pre id=&quot;code_1679621974325&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package common;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.NoHandlerFoundException;

//@Component를 포함하고 있는 annotation이기 때문에 이걸 붙여놔도 객체생성O
//@Controller annotation이 포함되어있는 객체에서 에러가 발생했을 때 처리하는 annotation
@ControllerAdvice
public class ErrorUtil {
	
	@ExceptionHandler(Exception.class)
	public String handelException(Exception e) {
		//오류마다 다르게 처리할거면 여러개 생성하면된다.
		System.err.println(&quot;에러발생&quot;);
		//out으로 해도되지만 색 바꾸려고 err
		System.err.println(e.getMessage());
		return &quot;error/error1&quot;;
	}
	@ExceptionHandler(NoHandlerFoundException.class)
	@ResponseStatus(value = HttpStatus.NOT_FOUND) //응답상태가 not_found(404) 오류
	public String notFound(NoHandlerFoundException e) {
		System.err.println(&quot;RequestMapping 오류&quot;);
		System.err.println(e.getMessage());
		return &quot;error/error2&quot;;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;error1.jsp&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1679622032942&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;서버에서 에러가 발생했습니다.&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;h3&amp;gt;잠시후 다시 시도해주세요&amp;lt;/h3&amp;gt;
	&amp;lt;a href=&quot;/&quot;&amp;gt;메인페이지로&amp;lt;/a&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;error2.jsp&lt;/p&gt;
&lt;pre id=&quot;code_1679622050726&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;요청 에러 발생&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;a href=&quot;/&quot;&amp;gt;메인으로&amp;lt;/a&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 짜는 단계에서는 에러확인을 해야하기때문에, 완성 후 에러처리작업을 해주는것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 웹소켓&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹소켓 사용을 위한 라이브러리 추가 - pom.xml&lt;/p&gt;
&lt;pre id=&quot;code_1679624421078&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;		&amp;lt;!-- Websocket사용을 위한 라이브러리(spring-websocket, jackson-databind) --&amp;gt;
		&amp;lt;!-- spring-websocket은 spring버전과 맞춰줘야한다. --&amp;gt;
		&amp;lt;!-- https://mvnrepository.com/artifact/org.springframework/spring-websocket --&amp;gt;
		&amp;lt;dependency&amp;gt;
		    &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
		    &amp;lt;artifactId&amp;gt;spring-websocket&amp;lt;/artifactId&amp;gt;
		    &amp;lt;version&amp;gt;5.0.6.RELEASE&amp;lt;/version&amp;gt;
		&amp;lt;/dependency&amp;gt;
		&amp;lt;!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --&amp;gt;
		&amp;lt;dependency&amp;gt;
		    &amp;lt;groupId&amp;gt;com.fasterxml.jackson.core&amp;lt;/groupId&amp;gt;
		    &amp;lt;artifactId&amp;gt;jackson-databind&amp;lt;/artifactId&amp;gt;
		    &amp;lt;version&amp;gt;2.13.5&amp;lt;/version&amp;gt;
		&amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;servlet-context의 namespace 탭에서 웹소켓 선택&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;487&quot; data-origin-height=&quot;729&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWg90u/btr5t9FSEr0/KMev7zIJU70T5vLrM2HC2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWg90u/btr5t9FSEr0/KMev7zIJU70T5vLrM2HC2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWg90u/btr5t9FSEr0/KMev7zIJU70T5vLrM2HC2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWg90u%2Fbtr5t9FSEr0%2FKMev7zIJU70T5vLrM2HC2k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;487&quot; height=&quot;729&quot; data-origin-width=&quot;487&quot; data-origin-height=&quot;729&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;servlet-context의 source에서 웹소켓을 처리할 객체 생성&lt;/p&gt;
&lt;pre id=&quot;code_1679624510974&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;!-- 웹소켓 채팅을 처리할 객체 생성 --&amp;gt;
	&amp;lt;beans:bean id=&quot;allMemberChat&quot; class=&quot;common.AllMemberChat&quot; /&amp;gt;
	&amp;lt;!-- 웹소켓 매핑 --&amp;gt;
	&amp;lt;websocket:handlers&amp;gt;
	 	&amp;lt;websocket:mapping handler=&quot;allMemberChat&quot; path=&quot;/chat.do&quot;/&amp;gt;
	 &amp;lt;/websocket:handlers&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3 - 1 ) 채팅&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;채팅 페이지 이동&lt;/p&gt;
&lt;pre id=&quot;code_1679624543238&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/allMemberChat.do&quot;&amp;gt;전체채팅&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1679624584846&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/allMemberChat.do&quot;)
	public String allMemberChat() {
		return &quot;member/allMemberChat&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1679624602486&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
    &amp;lt;%@taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;script src=&quot;https://code.jquery.com/jquery-3.6.1.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;style&amp;gt;
	.chatting{
		width: 500px;
		display: none;
	}
		&amp;lt;%-- y축으로 내부컨텐츠가 넘어가면 스크롤생성 --%&amp;gt;
	.messageArea{
		overflow-y : auto;
		border: 1px solid black;
		height: 500px;
		display: flex;
		flex-direction: column;
		background-color: #b2c7d9;
	}
	.messageArea&amp;gt;p{
		text-align: center;
		width: 100%;
	}
	#sendMsg{
		width: 75%;
	}
	#sendBtn{
		width:20%;
	}
	.chat{
		margin-bottom: 10px;
		padding: 8px;
		border-radius: 3px;
	}
	.left{
		position: relative;
		max-width: 300px;
		align-self: flex-start;
		background-color: #fff;
		border-radius: 10px;
		margin-left: 16px;
		padding: 15px;
	}
	.left:after{
		content:'';
		position: absolute;
		border-style: solid;
		border-width: 15px 15px 15px 0;
		border-color: transparent #fff;
		display: block;
		width: 0;
		z-index: 1;
		left: -15px;
		top: 12px;
	}
	.right{
		position: relative;
		max-width: 300px;
		align-self: flex-end;
		background-color: #ffeb33;
		border-radius: 10px;
		margin-right: 16px;
		padding: 15px;
	}
	.right:after{
		content:'';
		position: absolute;
		border-style: solid;
		border-width: 15px 0 15px 15px;
		border-color: transparent #ffeb33;
		display: block;
		width: 0;
		z-index: 1;
		right: -15px;
		top: 12px;
	}
&amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;전체채팅&amp;lt;/h1&amp;gt;
	&amp;lt;c:if test=&quot;${not empty sessionScope.m }&quot;&amp;gt;
	&amp;lt;button onclick=&quot;initChat('${sessionScope.m.memberId}');&quot;&amp;gt;채팅시작하기&amp;lt;/button&amp;gt;
	&amp;lt;div class=&quot;chatting&quot;&amp;gt;
		&amp;lt;div class=&quot;messageArea&quot;&amp;gt;
		&amp;lt;/div&amp;gt;
		&amp;lt;div class=&quot;sendBox&quot;&amp;gt;
			&amp;lt;input type=&quot;text&quot; id=&quot;sendMsg&quot;&amp;gt;
			&amp;lt;button id=&quot;sendBtn&quot; onclick=&quot;sendMsg();&quot;&amp;gt;전송&amp;lt;/button&amp;gt;
		&amp;lt;/div&amp;gt;
	&amp;lt;/div&amp;gt;
	&amp;lt;script&amp;gt;
		let ws; //웹소켓 객체를 저장하는 변수
		let memberId; // 회원아이디를 저장하는 변수
		function initChat(param){
			memberId = param;
			//웹소켓 연결 시도
			//주의점 127.0.0.1 또는 localhost로 사용하면 소켓연결을 할 수 없으므로 반드시 IP로 작성
			ws = new WebSocket(&quot;ws://192.168.10.17/chat.do&quot;);
			//웹소켓 연결 성공 시 실행할 함수 지정
			ws.onopen = startChat;
			//서버에서 데이터를 받으면 처리할 함수 지정
			ws.onmessage = receiveMsg;
			//웹소켓 연결이 종료되면 실행될 함수 지정
			ws.onclose = endChat;
			$(&quot;.chatting&quot;).slideDown();
		}
		function startChat(){
			console.log(&quot;웹소켓 연결완료&quot;);
			const data = {type:&quot;enter&quot;, msg: memberId};
			//문자열이 넘어가야하는데 data는 Object이기 때문에 에러발생 JSON.stringify(data) 형태로 보내줘야한다
			console.log(JSON.stringify(data));
			ws.send(JSON.stringify(data));
			appendChat(&quot;&amp;lt;p&amp;gt;채팅방에 입장했습니다.&amp;lt;/p&amp;gt;&quot;);
		}
		function receiveMsg(param){
			console.log(param);
			appendChat(param.data);
		}
		function endChat(){
			console.log(&quot;웹소켓 연결종료&quot;);
		}
		function sendMsg(){
			const msg = $(&quot;#sendMsg&quot;).val();
			if(msg != ''){
				const data = {type:&quot;chat&quot;, msg:msg}
				ws.send(JSON.stringify(data)); 
				appendChat(&quot;&amp;lt;div class='chat right'&amp;gt;&quot;+msg+&quot;&amp;lt;/div&amp;gt;&quot;);
				$(&quot;#sendMsg&quot;).val(''); //input clear
			}
		}
		$(&quot;#sendMsg&quot;).on(&quot;keyup&quot;, function(e){
			if(e.keyCode == 13){
				//keyCode == 13 : enter
				sendMsg();
			}
		});
		function appendChat(chatMsg){
			$(&quot;.messageArea&quot;).append(chatMsg);	
			//스크롤이 생기면 스크롤 위치를 잡아줌
			$(&quot;.messageArea&quot;).scrollTop($(&quot;.messageArea&quot;)[0].scrollHeight);
		}
	&amp;lt;/script&amp;gt;

	&amp;lt;/c:if&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;a href=&quot;/&quot;&amp;gt;메인으로&amp;lt;/a&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;채팅 Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679624624566&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package common;

import java.util.ArrayList;
import java.util.HashMap;

import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import com.google.gson.JsonElement;
import com.google.gson.JsonParser;


public class AllMemberChat extends TextWebSocketHandler{
	//접속한 회원 세션을 저장하는 리스트
	private ArrayList&amp;lt;WebSocketSession&amp;gt; sessionList;
	//세션에 대한 아이디 mapping
	private HashMap&amp;lt;WebSocketSession, String&amp;gt; memberList;
	
	public AllMemberChat() {
		super();
		sessionList = new ArrayList&amp;lt;WebSocketSession&amp;gt;();
		memberList = new HashMap&amp;lt;WebSocketSession, String&amp;gt;();
	}

	//클라이언트가 웹소켓으로 최초에 접속했을 때 자동으로 수행되는 메소드
	@Override
	public void afterConnectionEstablished(WebSocketSession session) throws Exception{
		System.out.println(&quot;클라이언트 접속&quot;);
		//최초 접속한 session정보를 세션목록에 추가
		sessionList.add(session);
	}
	
	//클라이언트가 메세지를 보내면 처리할 메소드
	@Override
	protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception{
		//System.out.println(&quot;session : &quot;+session);
		System.out.println(&quot;사용자가 전송한 메세지 : &quot;+message.getPayload());
		//message.getPayload() : 문자열 형태로 객체데이터를 쓰기 위해서는 JSON형식으로 변환해서 사용해야함
		//문자열을 JSON으로 변환할 객체
		JsonParser parser = new JsonParser();
		JsonElement element = parser.parseString(message.getPayload());
		//key가 type인 값을 추출
		String type = element.getAsJsonObject().get(&quot;type&quot;).getAsString();
		//key가 msg인 값을 추출
		String msg = element.getAsJsonObject().get(&quot;msg&quot;).getAsString();
		System.out.println(&quot;type : &quot;+type);
		System.out.println(&quot;msg : &quot;+msg);
		if(type.equals(&quot;enter&quot;)) {
			//최초접속했을 때 memberId가 들어있음
			//최초접속이므로 memberList에 정보저장
			memberList.put(session, msg);
			String sendMsg = &quot;&amp;lt;p&amp;gt;&quot;+msg+&quot;님이 입장하셨습니다.&amp;lt;/p&amp;gt;&quot;;
			//클라이언트 전송용 객체
			TextMessage tm = new TextMessage(sendMsg);
			for(WebSocketSession s : sessionList) {
				if(!s.equals(session)) {
					s.sendMessage(tm);
				}
			}
		}else if(type.equals(&quot;chat&quot;)) {
			String sendMsg = &quot;&amp;lt;div class='chat left'&amp;gt;&amp;lt;span class='chatId'&amp;gt;&quot;+memberList.get(session)+&quot; : &amp;lt;/span&amp;gt;&quot;+msg+&quot;&amp;lt;/div&amp;gt;&quot;;
			TextMessage tm = new TextMessage(sendMsg);
			for(WebSocketSession s : sessionList) {
				if(!s.equals(session)) {
					s.sendMessage(tm);
				}
			}
		}
	}
	
	//클라이언트와 연결이 끊어졌을 때 자동으로 수행되는 메소드
	@Override
	public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception{
		System.out.println(&quot;클라이언트 연결 끊김&quot;);
		//연결이 끊기면 세션목록에서 제거
		sessionList.remove(session);
		String sendMsg = &quot;&amp;lt;p&amp;gt;&quot;+memberList.get(session)+&quot;님이 나갔습니다.&amp;lt;/p&amp;gt;&quot;;
		TextMessage tm = new TextMessage(sendMsg);
		for(WebSocketSession s : sessionList) {
			if(!s.equals(session)) {
				s.sendMessage(tm);
			}
		}
		memberList.remove(session);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3 - 2 ) 쪽지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쪽지기능을 위해 DB테이블 생성&lt;/p&gt;
&lt;pre id=&quot;code_1679624716726&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;-- 쪽지기능
CREATE TABLE DIRECT_MESSAGE(
    DM_NO       NUMBER      PRIMARY KEY,
    SENDER      VARCHAR2(20)    REFERENCES MEMBER_TBL(MEMBER_ID) ON DELETE CASCADE,
    RECEIVER    VARCHAR2(20)    REFERENCES MEMBER_TBL(MEMBER_ID) ON DELETE CASCADE,
    DM_CONTENT  VARCHAR2(300)   NOT NULL,
    DM_DATE     DATE,
    READ_CHECK  NUMBER      -- 0이면 읽지앖음 1이면 읽음
);
CREATE SEQUENCE DM_SEQ;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VO : DM.class&lt;/p&gt;
&lt;pre id=&quot;code_1679624758422&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.dm.model.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class DM {
	private int dmNo;
	private String sender;
	private String receiver;
	private String dmContent;
	private String dmDate;
	private int readCheck;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쪽지 페이지 이동&lt;/p&gt;
&lt;pre id=&quot;code_1679624843694&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/dmMain.do&quot;&amp;gt;쪽지함&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1679625017958&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/dmMain.do&quot;)
	public String dmMain() {
		return &quot;dm/dmMain&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1679624851335&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;link rel=&quot;stylesheet&quot; href=&quot;/resources/css/dm.css&quot;&amp;gt;
&amp;lt;script src=&quot;https://code.jquery.com/jquery-3.6.1.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;쪽지함&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;h3&amp;gt;쪽지보내기&amp;lt;/h3&amp;gt;
	&amp;lt;button onclick=&quot;sendDmModal();&quot;&amp;gt;쪽지보내기&amp;lt;/button&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;h3&amp;gt;받은쪽지함&amp;lt;/h3&amp;gt;
	&amp;lt;table border=&quot;1&quot; class=&quot;receiveDmTbl&quot;&amp;gt;
		&amp;lt;thead&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th&amp;gt;보낸사람&amp;lt;/th&amp;gt;
				&amp;lt;th&amp;gt;내용&amp;lt;/th&amp;gt;
				&amp;lt;th&amp;gt;시간&amp;lt;/th&amp;gt;
				&amp;lt;th&amp;gt;읽음여부&amp;lt;/th&amp;gt;
			&amp;lt;/tr&amp;gt;
		&amp;lt;/thead&amp;gt;
		&amp;lt;tbody&amp;gt;&amp;lt;/tbody&amp;gt;
	&amp;lt;/table&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;h3&amp;gt;보낸쪽지함&amp;lt;/h3&amp;gt;
	&amp;lt;table border=&quot;1&quot; class=&quot;sendDmTbl&quot;&amp;gt;
		&amp;lt;thead&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th&amp;gt;받은사람&amp;lt;/th&amp;gt;
				&amp;lt;th&amp;gt;내용&amp;lt;/th&amp;gt;
				&amp;lt;th&amp;gt;시간&amp;lt;/th&amp;gt;
				&amp;lt;th&amp;gt;읽음여부&amp;lt;/th&amp;gt;
			&amp;lt;/tr&amp;gt;
		&amp;lt;/thead&amp;gt;
		&amp;lt;tbody&amp;gt;&amp;lt;/tbody&amp;gt;
	&amp;lt;/table&amp;gt;
	
	
	&amp;lt;!-- 쪽지보내기 모달 --&amp;gt;
	&amp;lt;div id=&quot;sendDm-modal&quot; class=&quot;modal-wrapper&quot;&amp;gt;
		&amp;lt;div class=&quot;modal&quot;&amp;gt;
			&amp;lt;div class=&quot;modal-header&quot;&amp;gt;
				&amp;lt;h2&amp;gt;쪽지보내기&amp;lt;/h2&amp;gt;
			&amp;lt;/div&amp;gt;
			&amp;lt;hr&amp;gt;
			&amp;lt;div class=&quot;modal-content&quot;&amp;gt;
				&amp;lt;div class=&quot;sendDmFrm&quot;&amp;gt;
					&amp;lt;label&amp;gt;수신자 : &amp;lt;/label&amp;gt;
					&amp;lt;select name=&quot;receiver&quot;&amp;gt;&amp;lt;/select&amp;gt;
					&amp;lt;textarea name=&quot;dmContent&quot;&amp;gt;&amp;lt;/textarea&amp;gt;
					&amp;lt;input type=&quot;hidden&quot; id=&quot;sender&quot; value=&quot;${sessionScope.m.memberId }&quot;&amp;gt;
					&amp;lt;button onclick=&quot;dmSend();&quot;&amp;gt;쪽지보내기&amp;lt;/button&amp;gt;
					&amp;lt;button onclick=&quot;closeModal();&quot;&amp;gt;닫기&amp;lt;/button&amp;gt; 
				&amp;lt;/div&amp;gt;
			&amp;lt;/div&amp;gt;
		&amp;lt;/div&amp;gt;
	&amp;lt;/div&amp;gt;
	
	&amp;lt;script src=&quot;/resources/js/dm.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dmMain - css&lt;/p&gt;
&lt;pre id=&quot;code_1679624890967&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@charset &quot;UTF-8&quot;;

h1{
    color: pink;

}
.modal-wrapper{
    position: fixed;
    width: 100vw;
    height: 100vh;
    background-color: rgba(0, 0, 0, 0.5);
    top: 0;
    left: 0;
    display: none;
    justify-content: center;
    align-items: center;
}
.modal{
    width: 350px;
    background-color: #fff;
}
.modal-header{
    padding: 10px;
}
.modal-content{
    padding: 20px;
}
textarea[name=dmContent]{
    width: 100%;
    height: 100px;
    resize: none;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dmMain - js&lt;/p&gt;
&lt;pre id=&quot;code_1679624914455&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/**
 * 
 */

/* 버튼을 클릭하면 회원목록을 아작스로 가져올것*/
/* 회원조회는 memberController에 생성 */
function sendDmModal(){
    $.ajax({
        url : &quot;/selectAllMemberId.do&quot;,
        success : function(list){
            //이름 중첩을 하지않기 위해 
            $(&quot;[name=receiver]&quot;).empty();
            for(let i=0; i&amp;lt;list.length; i++){
                const option = $(&quot;&amp;lt;option&amp;gt;&quot;);
                option.val(list[i]);
                option.text(list[i]);
                $(&quot;[name=receiver]&quot;).append(option);
            }
            $(&quot;#sendDm-modal&quot;).css(&quot;display&quot;, &quot;flex&quot;);
        }
    });
}

function closeModal(){
    $(&quot;#sendDm-modal&quot;).hide();
    //내용도 전부 삭제해줘야함
    $(&quot;textarea[name=dmContent]&quot;).val(&quot;&quot;);
}

function dmSend(){
    //sender receiver dmcotnent를 받아올 것
    const receiver = $(&quot;[name=receiver]&quot;).val();
    const sender = $(&quot;#sender&quot;).val();
    const dmContent = $(&quot;[name=dmContent]&quot;).val();
    console.log(receiver, sender, dmContent);

    $.ajax({
        url : &quot;/insertDm.do&quot;,
        type : &quot;post&quot;,
        data : {receiver:receiver, sender:sender, dmContent:dmContent},
        success : function(data){
            if(data == &quot;0&quot;){
                alert(&quot;쪽지보내기 실패&quot;);
            }
            closeModal();
        }
    });
}

function getSendDm(){
    const sender = $(&quot;#sender&quot;).val();
    $.ajax({
        url : &quot;/myDmList.do&quot;,
        data : {sender:sender},
        success : function(list){
            console.log(list);
        }
    });
}

function getReceiverDm(){
    const receiver = $(&quot;#sender&quot;).val();
    $.ajax({
        url : &quot;/myDmList.do&quot;,
        data : {receiver:receiver},
        success : function(list){
            const tbody = $(&quot;.receiveDmTbl&amp;gt;tbody&quot;);
            tbody.empty();
            for(let i=0; i&amp;lt;list.length; i++){
                const dm = list[i];
                const tr = $(&quot;&amp;lt;tr&amp;gt;&quot;);
                //보낸사람, 내용, 시간 읽음여부
                const td1 = $(&quot;&amp;lt;td&amp;gt;&quot;);
                td1.text(dm.sender);
                const td2 = $(&quot;&amp;lt;td&amp;gt;&quot;);
                td2.text(dm.dmContent);
                const td3 = $(&quot;&amp;lt;td&amp;gt;&quot;);
                td3.text(dm.dmDate);
                const td4 = $(&quot;&amp;lt;td&amp;gt;&quot;);
                if(dm.readCheck == 0){
                    td4.text(&quot;읽지않음&quot;);
                }else{
                    td4.text(&quot;읽음&quot;);
                }
                tr.append(td1).append(td2).append(td3).append(td4);
                tbody.append(tr);               
            }
        }
    });
}

$(function(){
    getReceiverDm();
    getSendDm();
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;css와 js위치 webapp/resources 아래 각각 css js 폴더를 만들어서 cssFile/JavaScriptFile생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쪽지보내기 버튼을 클릭 했을 때 회원들의 ID를 받아올 Controller(기존에 생성해놓았던 Service 사용)&lt;/p&gt;
&lt;pre id=&quot;code_1679625046742&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@ResponseBody
	@RequestMapping(value=&quot;/selectAllMemberId.do&quot;, produces = &quot;application/json;charset=utf-8&quot;)
	public String selectAllMemberId() {
		ArrayList&amp;lt;String&amp;gt; list = service.search3();
		//ajax요청이기 때문에 위에 ResponseBody를 붙어야함
		//전달하려는 값이 객체이므로 produces
		return new Gson().toJson(list);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쪽지를 보낼 Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679625089446&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@ResponseBody
	@RequestMapping(value=&quot;/insertDm.do&quot;)
	public String insertDm(DM dm) {
		int result = service.insertDm(dm);
		return String.valueOf(result);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service - insert이기 때문에 트랙잭션 관리를 해줌&lt;/p&gt;
&lt;pre id=&quot;code_1679625110520&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@Transactional
	public int insertDm(DM dm) {
		return dao.insertDm(dm);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679625132038&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int insertDm(DM dm) {
		int result = sqlSession.insert(&quot;dm.insetDm&quot;, dm);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dmSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679625151182&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;insert id=&quot;insetDm&quot; parameterType=&quot;dm&quot;&amp;gt;
		insert into direct_message values(dm_seq.nextval, #{sender}, #{receiver}, #{dmContent}, sysdate, 0)
	&amp;lt;/insert&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;받은쪽지List를 조회해올 Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679625188239&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@ResponseBody
	@RequestMapping(value=&quot;/myDmList.do&quot;, produces = &quot;application/json;charset=utf-8&quot;)
	public String myDmList(DM dm) {
		ArrayList&amp;lt;DM&amp;gt; list = service.selectDmList(dm);
		return new Gson().toJson(list);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679625198384&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;DM&amp;gt; selectDmList(DM dm) {
		return dao.selectDmList(dm);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679625208495&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;DM&amp;gt; selectDmList(DM dm) {
		List list = sqlSession.selectList(&quot;dm.selectDmList&quot;, dm);
		return (ArrayList&amp;lt;DM&amp;gt;)list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dmSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679625221783&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;select id=&quot;selectDmList&quot; parameterType=&quot;dm&quot; resultType=&quot;dm&quot;&amp;gt;
		select 
			dm_no as dmNo,
			sender,
			receiver,
			dm_content as dmContent,
			to_char(dm_date, 'yyyy-mm-dd hh:mi:ss') as dmDate,
			read_check as readCheck
		from direct_message
		&amp;lt;choose&amp;gt;
			&amp;lt;when test=&quot;sender != null&quot;&amp;gt;
			where sender = #{sender}
			&amp;lt;/when&amp;gt;
			&amp;lt;when test=&quot;receiver != null&quot;&amp;gt;
			where receiver = #{receiver}
			&amp;lt;/when&amp;gt;
		&amp;lt;/choose&amp;gt;
		order by dm_no desc
	&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>국비수업/Spring</category>
      <author>_HYE_</author>
      <guid isPermaLink="true">https://recordev.tistory.com/75</guid>
      <comments>https://recordev.tistory.com/75#entry75comment</comments>
      <pubDate>Fri, 24 Mar 2023 11:34:14 +0900</pubDate>
    </item>
    <item>
      <title>79일차 : Dynamic Mybatis</title>
      <link>https://recordev.tistory.com/73</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;20230321&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dynamic Query(동적쿼리) : 상황에따라 쿼리문이 동적으로 변화한다.&lt;br /&gt;SQL문을&amp;nbsp;여러번&amp;nbsp;호출해야하는경우&amp;nbsp;DAO를&amp;nbsp;여러번&amp;nbsp;호출하여&amp;nbsp;실행하였지만&amp;nbsp;Mybatis에서&amp;nbsp;이를&amp;nbsp;동적으로&amp;nbsp;제어하는&amp;nbsp;구문을&amp;nbsp;제공하여&amp;nbsp;쉽게&amp;nbsp;쿼리를&amp;nbsp;사용하도록&amp;nbsp;지원 &lt;br /&gt;-&amp;nbsp;if&amp;nbsp;/&amp;nbsp;choose&amp;nbsp;/&amp;nbsp;trim(쿼리문에서특정부분을없앨때사용)&amp;nbsp;/&amp;nbsp;foreach&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- login과 searchMemberId의 로직이 굉장히 유사&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;login&lt;/p&gt;
&lt;pre id=&quot;code_1679359387437&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/login.do&quot;)
	public String login(Member m, HttpSession session) {
		Member loginMember = service.selectOneMember(m);
		if(loginMember != null) {
			session.setAttribute(&quot;m&quot;, loginMember);
		}
		return &quot;redirect:/&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;searchMemberId&lt;/p&gt;
&lt;pre id=&quot;code_1679359401473&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/searchMemberId.do&quot;)
	public String searchMemberId(String memberId, Model model) {
		Member m = service.selectOneMember(memberId);
		if(m != null) {
			model.addAttribute(&quot;m&quot;, m);
			return &quot;member/searchMemberId&quot;;
		}else {
			return &quot;redirect:/&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;memberMapper&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;login&lt;/p&gt;
&lt;pre id=&quot;code_1679359548316&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  	&amp;lt;select id=&quot;selectOneMember&quot; parameterType=&quot;m&quot; resultType=&quot;m&quot;&amp;gt;
  		select  
  			member_no as memberNo, 
  			member_id as memberId, 
  			member_pw as memberPw, 
  			member_name as memberName, 
  			member_phone as memberPhone, 
  			member_email as memberEmail
  		from member_tbl where member_id=#{memberId} and member_pw=#{memberPw}
  	&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;searchMemberId&lt;/p&gt;
&lt;pre id=&quot;code_1679359571101&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  	&amp;lt;select id=&quot;searchMemberId&quot; parameterType=&quot;string&quot; resultType=&quot;m&quot;&amp;gt;
  		select
  			member_no as memberNo, 
  			member_id as memberId, 
  			member_pw as memberPw, 
  			member_name as memberName, 
  			member_phone as memberPhone, 
  			member_email as memberEmail
  		from member_tbl where member_id=#{_parameter}
  	&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. if&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; searchMemberId에서 매개변수를 member형으로 받아도 무관 -&amp;gt; 수정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(매개변수가 동일하여, 오버로딩이 불가능하므로 메소드 이름도 변경해준다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;selectOneMember(String memberId) -&amp;gt; selectOneMemberId(Member member)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679360009214&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/searchMemberId.do&quot;)
	public String searchMemberId(Member member, Model model) {
		Member m = service.selectOneMemberId(member);
		if(m != null) {
			model.addAttribute(&quot;m&quot;, m);
			return &quot;member/searchMemberId&quot;;
		}else {
			return &quot;redirect:/&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679360027252&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public Member selectOneMemberId(Member member) {
		return dao.selectOneMemberId(member);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679360044388&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public Member selectOneMemberId(Member member) {
		Member m = sqlSession.selectOne(&quot;member.selectOneMemberId&quot;, member);
		return m;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;memberMapper&lt;/p&gt;
&lt;pre id=&quot;code_1679360078845&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; 	&amp;lt;select id=&quot;selectOneMember&quot; parameterType=&quot;m&quot; resultType=&quot;m&quot;&amp;gt;
  		select  
  			member_no as memberNo, 
  			member_id as memberId, 
  			member_pw as memberPw, 
  			member_name as memberName, 
  			member_phone as memberPhone, 
  			member_email as memberEmail
  		from member_tbl where member_id=#{memberId}
  	&amp;lt;/select&amp;gt; 
    
   	&amp;lt;select id=&quot;searchMemberId&quot; parameterType=&quot;m&quot; resultType=&quot;m&quot;&amp;gt;
  		select
  			member_no as memberNo, 
  			member_id as memberId, 
  			member_pw as memberPw, 
  			member_name as memberName, 
  			member_phone as memberPhone, 
  			member_email as memberEmail
  		from member_tbl where member_id=#{memberId}
  	&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;login과 searchMemberId의 쿼리문이 where절의 and member_pw = #{memberPw} 를 제외하고 동일한걸 확인할 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 이럴 때 동적쿼리의 if문을 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최종 Mapper&lt;/p&gt;
&lt;pre id=&quot;code_1679360169845&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  	&amp;lt;select id=&quot;selectOneMember&quot; parameterType=&quot;m&quot; resultType=&quot;m&quot;&amp;gt;
  		select  
  			member_no as memberNo, 
  			member_id as memberId, 
  			member_pw as memberPw, 
  			member_name as memberName, 
  			member_phone as memberPhone, 
  			member_email as memberEmail
  		from member_tbl where member_id=#{memberId}
  		&amp;lt;if test=&quot;memberPw != null&quot;&amp;gt;
  		and member_pw=#{memberPw}  
  		&amp;lt;/if&amp;gt;
  	&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mapper에서 쿼리문 하나만 남기고, 동일한 Dao를 불러오면된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. choose&lt;/p&gt;
&lt;pre id=&quot;code_1679372183177&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;form action=&quot;/searchMember1.do&quot; method=&quot;post&quot;&amp;gt;
    &amp;lt;select name=&quot;type&quot;&amp;gt;
        &amp;lt;option value=&quot;id&quot;&amp;gt;아이디&amp;lt;/option&amp;gt;
        &amp;lt;option value=&quot;name&quot;&amp;gt;이름&amp;lt;/option&amp;gt;
    &amp;lt;/select&amp;gt;
    &amp;lt;input type=&quot;text&quot; name=&quot;keyword&quot;&amp;gt;
    &amp;lt;input type=&quot;submit&quot; value=&quot;검색&quot;&amp;gt;
&amp;lt;/form&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679372238096&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@RequestMapping(value=&quot;/searchMember1.do&quot;)
public String searchMember1(String type, String keyword, Model model) {
    //type, keyword라는 변수가 없으므로 VO를 만들어주던지 String으로 받아와야함
    //아이디로 검색하면 : where member_id = ? 
    //이름으로 검색하면 : where member_name like %검색어%
    //조회결과가 1개일수도(아이디) 여러개일수도(이름)있으므로 list로 받는게 좋다
    ArrayList&amp;lt;Member&amp;gt; list = service.search1(type, keyword);
    model.addAttribute(&quot;list&quot;, list);
    return &quot;member/allMember&quot;;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679372266745&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public ArrayList&amp;lt;Member&amp;gt; search1(String type, String keyword) {
    //쿼리문 수행을 위해서는 매개변수(type, keyword) 2개를 전송해줘야함
    //Mybatis는 매개변수를 1개만 받을 수 있음
    //해결방법 1) type과 keyword를 묶을 VO생성 - VO를 생성하면 애초에 컨트롤러에서 매개변수로 VO로 받으면된다
    SearchVO search = new SearchVO(type, keyword);
    ArrayList&amp;lt;Member&amp;gt; list = dao.search1(search);
    //해결방법 2) HashMap&amp;lt;String, Object&amp;gt;사용(VO대신 Map으로 묶겠다)
    return list;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679372285353&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public ArrayList&amp;lt;Member&amp;gt; search1(SearchVO search) {
    List list = sqlSession.selectList(&quot;member.search1&quot;, search);
    return (ArrayList&amp;lt;Member&amp;gt;)list;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;memberSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679372310617&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- choose --&amp;gt;
&amp;lt;select id=&quot;search1&quot; parameterType=&quot;kr.or.iei.member.model.vo.SearchVO&quot; resultType=&quot;m&quot;&amp;gt;
    select
        member_no as memberNo, 
        member_id as memberId, 
        member_pw as memberPw, 
        member_name as memberName, 
        member_phone as memberPhone, 
        member_email as memberEmail
    from member_tbl 
    &amp;lt;!-- 조건절이 type에 따라 달라짐 --&amp;gt;
    &amp;lt;choose&amp;gt;
        &amp;lt;when test=&quot;type.equals('id')&quot;&amp;gt;
        where member_id = #{keyword}
        &amp;lt;/when&amp;gt;
        &amp;lt;when test=&quot;type.equals('name')&quot;&amp;gt;
        where member_name like '%'||#{keyword}||'%'
        &amp;lt;/when&amp;gt;
    &amp;lt;/choose&amp;gt;
&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. trim&lt;/p&gt;
&lt;pre id=&quot;code_1679372430940&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;			&amp;lt;h3&amp;gt;아이디 or 이름으로 검색&amp;lt;/h3&amp;gt;
			&amp;lt;p&amp;gt;
				아이디만 입력하고 검색하면 아이디로 조회,
				이름만 입력하고 검색하면 이름으로 조회,
				둘 다 입력하고 검색하면 두개 and조건으로 조회
			&amp;lt;/p&amp;gt;
			&amp;lt;form action=&quot;/searchMember2.do&quot; method=&quot;get&quot;&amp;gt;
				아이디 : &amp;lt;input type=&quot;text&quot; name=&quot;memberId&quot;&amp;gt;&amp;lt;br&amp;gt;
				이름 : &amp;lt;input type=&quot;text&quot; name=&quot;memberName&quot;&amp;gt;&amp;lt;br&amp;gt;
				&amp;lt;input type=&quot;submit&quot; value=&quot;입력&quot;&amp;gt;
			&amp;lt;/form&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679372448648&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/searchMember2.do&quot;)
	public String searchMember2(Member member, Model model) {
		ArrayList&amp;lt;Member&amp;gt; list = service.search2(member);
		//넘어오는 값중 id 또는 name을 입력하지 않으면 null이 아닌 빈값('')
		//choose로 처리할 수 있지만 case가 여러개이기 때문에 코드가 굉장히 복잡해짐
		model.addAttribute(&quot;list&quot;, list);
		return &quot;member/allMember&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679372458201&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;Member&amp;gt; search2(Member member) {
		ArrayList&amp;lt;Member&amp;gt; list = dao.search2(member);
		return list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679372468010&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;Member&amp;gt; search2(Member member) {
		List list = sqlSession.selectList(&quot;member.search2&quot;, member);
		return (ArrayList&amp;lt;Member&amp;gt;)list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;memberSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679372480464&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; 	&amp;lt;!-- trim --&amp;gt;
  	&amp;lt;select id=&quot;search2&quot; parameterType=&quot;m&quot; resultType=&quot;m&quot;&amp;gt;
  		select
  			member_no as memberNo, 
  			member_id as memberId, 
  			member_pw as memberPw, 
  			member_name as memberName, 
  			member_phone as memberPhone, 
  			member_email as memberEmail
  		from member_tbl 
  		&amp;lt;!-- 이대로만 작성하면 where가 없기때문에 에러발생(if문이 실행되지않으면 에러X) : trim을 사용 --&amp;gt;
  		&amp;lt;!-- 경우의 수에따라 where가 필요할때도 and가 필요할때도 있음 --&amp;gt;
  		&amp;lt;trim prefix=&quot;where&quot; prefixOverrides=&quot;and|or&quot;&amp;gt;
  		&amp;lt;!-- trim내부에 있는게 하나라도 동작하면, prefix에 있는 값을 붙여라 --&amp;gt;
  		&amp;lt;!-- 실행된게 and 또는 or로 시작되면 그걸 지워라 --&amp;gt;
  		&amp;lt;!-- 
  			1. 둘다 입력 안한 경우 : 아무런동작X
  			2. 아이디만 입력한 경우 : prefix에 의해 where가 붙음 : 
  			   where member_id like '%'||#{memberId}||'%'
  			3. 이름만 입력한 경우 : prefix에 의해 where가 붙고, prefixOverrides에 의해 and가 지워짐
  			   where member_name like '%'||#{memberName}||'%'
  			4. 둘다 입력한 경우 : prefix에 의해 where가 붙고 prefixOverrides는 실행 X
  			   where member_id like '%'||#{memberId}||'%' and member_name like '%'||#{memberName}||'%'
  		 --&amp;gt;
	  		&amp;lt;if test=&quot;!memberId.equals('')&quot;&amp;gt;
	  			member_id like '%'||#{memberId}||'%'
	  		&amp;lt;/if&amp;gt;
	  		&amp;lt;if test=&quot;!memberName.equals('')&quot;&amp;gt;
	  			and member_name like '%'||#{memberName}||'%'
	  		&amp;lt;/if&amp;gt;
  		&amp;lt;/trim&amp;gt;
  	&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. foreach&lt;/p&gt;
&lt;pre id=&quot;code_1679372499705&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/searchMember3.do&quot;&amp;gt;전체 아이디목록조회&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1679372530624&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/searchMember3.do&quot;)
	public String searchMember3(Model model) {
		//전체회원의 아이디만 받아올것 -&amp;gt; 그래도 여러개이기때문에 ArrayList -&amp;gt; 내부자료형은 String
		ArrayList&amp;lt;String&amp;gt; idList = service.search3();
		model.addAttribute(&quot;idList&quot;, idList);
		return &quot;member/idList&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1679372546544&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;String&amp;gt; search3() {
		ArrayList&amp;lt;String&amp;gt; list = dao.search3();
		return list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1679372554928&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;String&amp;gt; search3() {
		List list = sqlSession.selectList(&quot;member.search3&quot;);
		return (ArrayList&amp;lt;String&amp;gt;)list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1679372567168&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  	&amp;lt;select id=&quot;search3&quot; resultType=&quot;string&quot;&amp;gt;
  		select member_id from member_tbl
  	&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1679372581776&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
    &amp;lt;%@taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;아이디 목록&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;form action=&quot;/searchMember4.do&quot; method=&quot;post&quot;&amp;gt;
	&amp;lt;c:forEach items=&quot;${idList }&quot; var=&quot;memberId&quot;&amp;gt;
		&amp;lt;p&amp;gt;
			&amp;lt;input type=&quot;checkbox&quot; name=&quot;memberId&quot; value=&quot;${memberId }&quot;&amp;gt; 
			${memberId }
		&amp;lt;/p&amp;gt;
	&amp;lt;/c:forEach&amp;gt;
	&amp;lt;input type=&quot;submit&quot; value=&quot;선택회원조회&quot;&amp;gt;
	&amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679372598024&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/searchMember4.do&quot;)
	public String searchMember4(String[] memberId, Model model) {
		ArrayList&amp;lt;Member&amp;gt; list = service.search4(memberId);
		model.addAttribute(&quot;list&quot;, list);
		return &quot;member/allMember&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679372609304&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;Member&amp;gt; search4(String[] memberId) {
		ArrayList&amp;lt;Member&amp;gt; list = dao.search4(memberId);
		return list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679372620576&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;Member&amp;gt; search4(String[] memberId) {
		List list = sqlSession.selectList(&quot;member.search4&quot;, memberId);
		//Mybatis에서 매개변수로 배열을 전달하는 경우
		/* 이방식으로 전달을 한다.
		HashMap&amp;lt;String, Object&amp;gt; map = new HashMap&amp;lt;String, Object&amp;gt;();
		map.put(&quot;array&quot;, memberId); key가 array value가 memberId
		List list = sqlSession.selectList(&quot;member.search4&quot;, map);
		*/
		return (ArrayList&amp;lt;Member&amp;gt;)list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;memberSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679372636057&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  	&amp;lt;select id=&quot;search4&quot; parameterType=&quot;map&quot; resultType=&quot;m&quot;&amp;gt;
  		select
  			member_no as memberNo, 
  			member_id as memberId, 
  			member_pw as memberPw, 
  			member_name as memberName, 
  			member_phone as memberPhone, 
  			member_email as memberEmail
  		from member_tbl
  		where member_id in
  		&amp;lt;!-- collection : 대상이되는 배열의 객체  / item : 배열에서 한바퀴 돌 때마다 꺼낼 값--&amp;gt;
  		&amp;lt;!-- open : foreach시작 시 넣을값 / close : foreach종료 시 넣을 값  / separator : for문 사이 구분자--&amp;gt;
  		&amp;lt;foreach collection=&quot;array&quot; item=&quot;id&quot; open=&quot;(&quot; close=&quot;)&quot; separator=&quot;,&quot;&amp;gt;
  			#{id}
  		&amp;lt;/foreach&amp;gt;
  	&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. &amp;lt;![CDATA[&amp;nbsp;&amp;gt;&amp;nbsp;]]&amp;gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1679372657664&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/searchMember5.do&quot;&amp;gt;회원목록조회(특정조건)&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679372668392&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/searchMember5.do&quot;)
	public String searchMember5(Model model) {
		ArrayList&amp;lt;Member&amp;gt; list = service.serach5();
		model.addAttribute(&quot;list&quot;, list);
		return &quot;member/allMember&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679372676400&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;Member&amp;gt; serach5() {
		ArrayList&amp;lt;Member&amp;gt; list = dao.search5();
		return list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679372684841&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;Member&amp;gt; search5() {
		List list = sqlSession.selectList(&quot;member.search5&quot;);
		return (ArrayList&amp;lt;Member&amp;gt;)list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;memberSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679372697176&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  	&amp;lt;!-- 부등호 --&amp;gt;
  	&amp;lt;select id=&quot;search5&quot; resultType=&quot;m&quot;&amp;gt;
  		select
  			member_no as memberNo, 
  			member_id as memberId, 
  			member_pw as memberPw, 
  			member_name as memberName, 
  			member_phone as memberPhone, 
  			member_email as memberEmail
  		from member_tbl
  		&amp;lt;!-- 에러발생 &amp;lt;가 부등호가 아닌 여는태그로 인식되기때문 : 부등호로 인식시켜줘야함 &amp;lt;![CDATA[ &amp;gt; ]]&amp;gt; 
  		  &amp;lt;![CDATA[ &amp;gt; ]]&amp;gt; 대괄호 영역안에 쿼리문 전체를 넣어줘도된다. --&amp;gt;
  		where member_no &amp;lt;![CDATA[ &amp;gt; ]]&amp;gt; 20
  	&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- [ Board ]&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 게시글 목록(+페이징처리)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679388786118&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/boardList.do&quot;)
	public String boardList(int reqPage, Model model) {
		BoardPageData bpd = service.selectBoardList(reqPage);
		model.addAttribute(&quot;list&quot;, bpd.getList());
		model.addAttribute(&quot;pageNavi&quot;, bpd.getPageNavi());
		return &quot;board/boardList&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679388809310&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public BoardPageData selectBoardList(int reqPage) {
		//한 페이지당 보여줄 게시물 수 
		int numPerPage = 5;
		//reqPage = 1 : 1~2 / 2 : 3~4
		int end = reqPage * numPerPage;
		int start = end - numPerPage + 1;
		//계산된 start, end를 가지고 게시물 목록 조회
		//Mybatis는 매개변수를 하나만 받을 수 있기 때문에 HashMap 사용
		//String : 쿼리문에서 사용하기 쉽게하려고 / Object : 여러자료형을 받을 수 잇도록
		HashMap&amp;lt;String, Object&amp;gt; map = new HashMap&amp;lt;String, Object&amp;gt;();
		map.put(&quot;start&quot;, start);
		map.put(&quot;end&quot;, end);
		ArrayList&amp;lt;Board&amp;gt; list = dao.selectBoardList(map);
		//pageNavi 제작 시작
		//전체페이지 수 계산 필요 -&amp;gt; 전체 게시물 수 조회
		int totalCount = dao.selectBoardCount();
		//전체게시물로 전체 페이지 수 계산
		//방법1
		/*
		int totalPage = 0;
		if(totalCount%numPerPage == 0) {
			totalPage = totalCount/numPerPage;
		}else {
			totalPage = (totalCount/numPerPage) + 1;
		}
		*/
		//방법2
		int totalPage = (int)Math.ceil(totalCount/(double)numPerPage); //ceil : 올림
		//pageNavi 사이즈
		int pageNaviSize = 5;
		
		int pageNo = 1;
		if(reqPage &amp;gt; 3) {
			pageNo = reqPage-2;
		}
		//페이지네비 생성시작
		String pageNavi = &quot;&quot;;
		//이전버튼
		if(pageNo != 1) {
			pageNavi +=&quot;&amp;lt;a href='/boardList.do?reqPage=&quot;+(pageNo-1)+&quot;'&amp;gt;[이전]&amp;lt;/a&amp;gt;&quot;;
		}
		//페이지 숫자 생성
		for(int i=0; i&amp;lt;pageNaviSize; i++) {
			if(pageNo == reqPage) {
				//현재페이지
				pageNavi += &quot;&amp;lt;span&amp;gt;&quot;+pageNo+&quot;&amp;lt;/span&amp;gt;&quot;;
			}else {
				pageNavi += &quot;&amp;lt;a href='/boardList.do?reqPage=&quot;+pageNo+&quot;'&amp;gt;&quot;+pageNo+&quot;&amp;lt;/a&amp;gt;&quot;;
			}
			pageNo++;
			if(pageNo &amp;gt; totalPage) {
				break;
			}
		}
		//다음버튼
		if(pageNo &amp;lt;= totalPage) {
			pageNavi +=&quot;&amp;lt;a href='/boardList.do?reqPage=&quot;+pageNo+&quot;'&amp;gt;[다음]&amp;lt;/a&amp;gt;&quot;;
		}
		BoardPageData bpd = new BoardPageData(list, pageNavi);
		return bpd;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679388828822&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;Board&amp;gt; selectBoardList(HashMap&amp;lt;String, Object&amp;gt; map) {
		List list = sqlSession.selectList(&quot;board.selectBoardList&quot;, map);
		return (ArrayList&amp;lt;Board&amp;gt;)list;
	}

	public int selectBoardCount() {
		int totalCount = sqlSession.selectOne(&quot;board.totalCount&quot;);
		return totalCount;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;boardSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679388914390&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;select id=&quot;selectBoardList&quot; parameterType=&quot;map&quot; resultType=&quot;b&quot;&amp;gt;
		select * from
			(select rownum as rnum, b.* from
				(select 
					board_no as boardNo, 
					board_title as boardTitle, 
					board_writer as boardWriter, 
					board_date as boardDate
				from board
				order by 1 desc)b)
		where rnum between #{start} and #{end}
	&amp;lt;/select&amp;gt;
	&amp;lt;select id=&quot;totalCount&quot; resultType=&quot;_int&quot;&amp;gt;
		select count(*) from board
	&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 게시글 작성&lt;/p&gt;
&lt;pre id=&quot;code_1679388978166&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;게시글작성&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;form action=&quot;/boardWrite.do&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&amp;gt;
		&amp;lt;table border=&quot;1&quot;&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th&amp;gt;제목&amp;lt;/th&amp;gt;
				&amp;lt;td&amp;gt;&amp;lt;input type=&quot;text&quot; name=&quot;boardTitle&quot;&amp;gt;&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th&amp;gt;작성자&amp;lt;/th&amp;gt;
				&amp;lt;td&amp;gt;
					${sessionScope.m.memberId }
					&amp;lt;input type=&quot;hidden&quot; name=&quot;boardWriter&quot; value=&quot;${sessionScope.m.memberId }&quot;&amp;gt;
				&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th&amp;gt;첨부파일&amp;lt;/th&amp;gt;
				&amp;lt;td&amp;gt;&amp;lt;input type=&quot;file&quot; name=&quot;boardFile&quot; multiple&amp;gt;&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th&amp;gt;내용&amp;lt;/th&amp;gt;
				&amp;lt;td&amp;gt;&amp;lt;textarea name=&quot;boardContent&quot;&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th colspan=&quot;2&quot;&amp;gt;&amp;lt;input type=&quot;submit&quot; value=&quot;작성하기&quot;&amp;gt;&amp;lt;/th&amp;gt;
			&amp;lt;/tr&amp;gt;
		&amp;lt;/table&amp;gt;
	&amp;lt;/form&amp;gt;
	&amp;lt;a href=&quot;/&quot;&amp;gt;메인으로&amp;lt;/a&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679388960407&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/boardWriteFrm.do&quot;)
	public String boardWriteFrm() {
		return &quot;board/boardWriteFrm&quot;;
	}
	@RequestMapping(value=&quot;/boardWrite.do&quot;)
	public String boardWrite(Board b, MultipartFile[] boardFile, HttpServletRequest request) {
		ArrayList&amp;lt;FileVO&amp;gt; fileList = new ArrayList&amp;lt;FileVO&amp;gt;();
		if(!boardFile[0].isEmpty()){
			//파일이 존재할 때
			String savePath = request.getSession().getServletContext().getRealPath(&quot;/resources/upload/board/&quot;);
			for(MultipartFile file : boardFile) {
				String filename = file.getOriginalFilename();
				String filepath = manager.upload(savePath, file);
				
				FileVO fileVO = new FileVO();
				fileVO.setFilename(filename);
				fileVO.setFilepath(filepath);
				fileList.add(fileVO);
			}
		}
		int result = service.insertBoard(b, fileList);
		if(result == fileList.size()+1) {
			return &quot;redirect:/boardList.do?reqPage=1&quot;;
		}else {
			return &quot;redirect:/&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679389002710&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int insertBoard(Board b, ArrayList&amp;lt;FileVO&amp;gt; fileList) {
		//DB작업 3번 - 1.board테이블에 insert / 2.파일에서 참조할 board_no를 조회 / 3.file_tbl테이블에 insert
		int result = dao.insertBoard(b);
		//Mybatis에서 boardNo를 넣어주었기 때문에 boardNo가 0 이 아닌 해당 게시글번호로 나온다.
		if(result &amp;gt; 0) {
			//int boardNo = dao.selectBoardNo();
			for(FileVO file : fileList) {
				file.setBoardNo(b.getBoardNo());
				result += dao.insertFile(file);
			}
		}
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679389036214&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int insertBoard(Board b) {
		int result = sqlSession.insert(&quot;board.insertBoard&quot;, b);
		return result;
	}

	public int selectBoardNo() {
		int boardNo = sqlSession.selectOne(&quot;board.selectBoardNo&quot;);
		return boardNo;
	}

	public int insertFile(FileVO file) {
		int result = sqlSession.insert(&quot;board.insertFile&quot;, file);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;boardSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679389057094&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;insert id=&quot;insertBoard&quot; parameterType=&quot;b&quot;&amp;gt;
		insert into board values
		(board_seq.nextval, #{boardTitle}, #{boardWriter}, #{boardContent}, to_char(sysdate, 'yyyy-mm-dd'))
		&amp;lt;!-- 정규화가 이루어져있어 외래키로 연결되어있을 경우 selectKey를 사용하면 별도의 select를 진행하지 않아도된다. --&amp;gt;
		&amp;lt;!-- key값을 다시 조회할건데 해당태그(현재insert)가 동작하고나면 조회할 때 --&amp;gt;
		&amp;lt;selectKey resultType=&quot;_int&quot; order=&quot;AFTER&quot; keyProperty=&quot;boardNo&quot;&amp;gt;
			&amp;lt;!-- order:insert문 이후에 실행, keyProperty: boardNo변수에 넣어줄것 --&amp;gt;
			select max(board_no) from board
		&amp;lt;/selectKey&amp;gt;
	&amp;lt;/insert&amp;gt;
	&amp;lt;!-- &amp;lt;select id=&quot;selectBoardNo&quot; resultType=&quot;_int&quot;&amp;gt;
		select max(board_no) from board
	&amp;lt;/select&amp;gt; --&amp;gt;
	&amp;lt;insert id=&quot;insertFile&quot; parameterType=&quot;f&quot;&amp;gt;
		insert into file_tbl values(file_seq.nextval, #{boardNo}, #{filename}, #{filepath})
	&amp;lt;/insert&amp;gt;
	
	&amp;lt;!--
	&amp;lt;select id=&quot;selectOneBoard&quot; parameterType=&quot;_int&quot; resultType=&quot;b&quot;&amp;gt;
		select 
			board_no as boardNo, 
			board_title as boardTitle, 
			board_writer as boardWriter,
			board_content as boardContent, 
			board_date as boardDate
		from board where board_no = ${_parameter}
	&amp;lt;/select&amp;gt;
	--&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 게시글 상세보기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679389099590&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/boardView.do&quot;)
	public String boardView(int boardNo, Model model) {
		Board b = service.selectOneBoard(boardNo);
		model.addAttribute(&quot;b&quot;, b);
		return &quot;board/boardView&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679389111094&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public Board selectOneBoard(int boardNo) {
		//1.board테이블조회
		Board b = dao.selectOneBoard(boardNo);
		//2.file테이블조회
		/*
		if(b != null) {
			ArrayList&amp;lt;FileVO&amp;gt; fileList = dao.selectFileList(boardNo);
			b.setFileList(fileList);
		}
		*/
		return b;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679389126974&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public Board selectOneBoard(int boardNo) {
		Board b = sqlSession.selectOne(&quot;board.selectOneBoard&quot;, boardNo);
		return b;
	}

	public ArrayList&amp;lt;FileVO&amp;gt; selectFileList(int boardNo) {
		List list = sqlSession.selectList(&quot;board.selectFileList&quot;, boardNo);
		return (ArrayList&amp;lt;FileVO&amp;gt;)list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;boardSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679389156150&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;!--
	&amp;lt;select id=&quot;selectOneBoard&quot; parameterType=&quot;_int&quot; resultType=&quot;b&quot;&amp;gt;
		select 
			board_no as boardNo, 
			board_title as boardTitle, 
			board_writer as boardWriter,
			board_content as boardContent, 
			board_date as boardDate
		from board where board_no = ${_parameter}
	&amp;lt;/select&amp;gt;
	--&amp;gt;
	&amp;lt;select id=&quot;selectFileList&quot; parameterType=&quot;_int&quot; resultType=&quot;f&quot;&amp;gt;
		select
			file_no as fileNo,
			board_no as boardNo,
			filename,
			filepath
		from file_tbl where board_no = #{_parameter}
	&amp;lt;/select&amp;gt;
	
	&amp;lt;select id=&quot;selectOneBoard&quot; parameterType=&quot;_int&quot; resultMap=&quot;getBoard&quot;&amp;gt;
		select * from board where board_no = ${_parameter}
	&amp;lt;/select&amp;gt;
	&amp;lt;!-- type:최종적으로 되돌려주는 type / id:연결을 위함 --&amp;gt;
	&amp;lt;!-- 사용은 할 수 있지만 효율은낮음 DB에 쓸데없는 데이터가 많아지기 때문에 --&amp;gt;
	&amp;lt;resultMap type=&quot;b&quot; id=&quot;getBoard&quot;&amp;gt;
		&amp;lt;result column=&quot;board_no&quot; property=&quot;boardNo&quot; /&amp;gt;
		&amp;lt;result column=&quot;board_title&quot; property=&quot;boardTitle&quot; /&amp;gt;
		&amp;lt;result column=&quot;board_Writer&quot; property=&quot;boardWriter&quot; /&amp;gt;
		&amp;lt;result column=&quot;board_Content&quot; property=&quot;boardContent&quot; /&amp;gt;
		&amp;lt;result column=&quot;board_date&quot; property=&quot;boardDate&quot; /&amp;gt;
		&amp;lt;collection property=&quot;fileList&quot; 
					select=&quot;selectFileList&quot;
					column=&quot;board_no&quot;
					ofType=&quot;f&quot;
					javaType=&quot;java.util.ArrayList&quot;
		/&amp;gt;
	&amp;lt;/resultMap&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 게시글 수정&lt;/p&gt;
&lt;pre id=&quot;code_1679389259942&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
   	&amp;lt;%@taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot; %&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;script src=&quot;https://code.jquery.com/jquery-3.6.0.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;게시물 수정&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;form action=&quot;/boardUpdate.do&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot; id=&quot;updateFrm&quot;&amp;gt;
		&amp;lt;table border=&quot;1&quot;&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th&amp;gt;글번호&amp;lt;/th&amp;gt;
				&amp;lt;td&amp;gt;
					${b.boardNo }
					&amp;lt;input type=&quot;hidden&quot; name=&quot;boardNo&quot; value=&quot;${b.boardNo }&quot;&amp;gt;
				&amp;lt;/td&amp;gt;
				&amp;lt;th&amp;gt;작성자&amp;lt;/th&amp;gt;
				&amp;lt;td&amp;gt;${b.boardWriter }&amp;lt;/td&amp;gt;
				&amp;lt;th&amp;gt;작성일&amp;lt;/th&amp;gt;
				&amp;lt;td&amp;gt;${b.boardDate }&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th&amp;gt;제목&amp;lt;/th&amp;gt;
				&amp;lt;td colspan=&quot;5&quot;&amp;gt;&amp;lt;input type=&quot;text&quot; name=&quot;boardTitle&quot; value=&quot;${b.boardTitle }&quot;&amp;gt;&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th&amp;gt;첨부파일&amp;lt;/th&amp;gt;
				&amp;lt;td colspan=&quot;5&quot;&amp;gt;
					&amp;lt;c:forEach items=&quot;${b.fileList }&quot; var=&quot;f&quot;&amp;gt;
					&amp;lt;p&amp;gt;
						${f.filename}
						&amp;lt;button type=&quot;button&quot; onclick=&quot;deleteFile(this, ${f.fileNo}, '${f.filepath }');&quot;&amp;gt;삭제&amp;lt;/button&amp;gt;
					&amp;lt;/p&amp;gt; 
					&amp;lt;/c:forEach&amp;gt;
				&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th&amp;gt;첨부파일 추가&amp;lt;/th&amp;gt;
				&amp;lt;td colspan=&quot;5&quot;&amp;gt;&amp;lt;input type=&quot;file&quot; name=&quot;boardFile&quot; multiple&amp;gt;&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;td colspan=&quot;6&quot; style=&quot;min-hight:300px;&quot;&amp;gt;
					&amp;lt;textarea name=&quot;boardContent&quot;&amp;gt;${b.boardContent }&amp;lt;/textarea&amp;gt;
				&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;td colspan=&quot;6&quot;&amp;gt;
					&amp;lt;input type=&quot;submit&quot; value=&quot;작성완료&quot;&amp;gt;
				&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
		&amp;lt;/table&amp;gt;
	&amp;lt;/form&amp;gt;
	&amp;lt;script&amp;gt;
		function deleteFile(obj, fileNo, filepath){
			const fileNoInput = $(&quot;&amp;lt;input&amp;gt;&quot;);
			fileNoInput.attr(&quot;name&quot;, &quot;fileNo&quot;);
			fileNoInput.val(fileNo);
			fileNoInput.hide();
			
			const filepathInput = $(&quot;&amp;lt;input&amp;gt;&quot;);
			filepathInput.attr(&quot;name&quot;, &quot;filepath&quot;);
			filepathInput.val(filepath);
			filepathInput.hide();
			
			$(&quot;#updateFrm&quot;).append(fileNoInput).append(filepathInput);
			$(obj).parent().remove();
		}
	&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679389249262&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/boardUpdateFrm.do&quot;)
	public String boardUpdateFrm(int boardNo, Model model) {
		Board b = service.selectOneBoard(boardNo);
		model.addAttribute(&quot;b&quot;, b);
		return &quot;board/boardUpdateFrm&quot;;
	}
	
	@RequestMapping(value=&quot;/boardUpdate.do&quot;)
	public String boardUpdate(Board b, int[] fileNo, String[] filepath, MultipartFile[] boardFile, HttpServletRequest request) {
		System.out.println(&quot;넘어오나&quot;);
		ArrayList&amp;lt;FileVO&amp;gt; fileList = new ArrayList&amp;lt;FileVO&amp;gt;();
		String savePath = request.getSession().getServletContext().getRealPath(&quot;/resources/upload/board/&quot;);
		if(!boardFile[0].isEmpty()) {
			for(MultipartFile file : boardFile) {
				String filename = file.getOriginalFilename();
				String newfilepath = manager.upload(savePath, file);
				FileVO fileVO = new FileVO();
				fileVO.setFilename(filename);
				fileVO.setFilepath(newfilepath);
				fileList.add(fileVO);
			}
		}//파일업로드종료
		int result = service.boardUpdate(b, fileList, fileNo);
		if(fileNo != null &amp;amp;&amp;amp; result == (fileList.size() + fileNo.length + 1)) {
			for(String delFile : filepath) {
				manager.deleteFile(savePath, delFile);
			}
			return &quot;redirect:/boardView.do?boardNo=&quot;+b.getBoardNo();
		}else if(fileNo == null &amp;amp;&amp;amp; result == fileList.size()+1){
			return &quot;redirect:/boardView.do?boardNo=&quot;+b.getBoardNo();
		}else {
			return &quot;redirect:/boardList.do?reqPage=1&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679389282526&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int boardUpdate(Board b, ArrayList&amp;lt;FileVO&amp;gt; fileList, int[] fileNo) {
		int result = dao.updateBoard(b);
		if(result &amp;gt; 0) {
			if(fileNo != null) {
				for(int no : fileNo) {
					result += dao.deleteFile(no);
				}
			}
			for(FileVO f : fileList) {
				f.setBoardNo(b.getBoardNo());
				result += dao.insertFile(f);
			}
		}
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679389334430&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int updateBoard(Board b) {
		int result = sqlSession.update(&quot;board.updateBoard&quot;, b);
		return result;
	}

	public int deleteFile(int no) {
		int result = sqlSession.delete(&quot;board.deleteFile&quot;, no);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;boardSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679389356638&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;update id=&quot;updateBoard&quot; parameterType=&quot;b&quot;&amp;gt;
		update board set board_title = #{boardTitle}, board_content = #{boardContent} where board_no = #{boardNo}
	&amp;lt;/update&amp;gt;
	&amp;lt;delete id=&quot;deleteFile&quot; parameterType=&quot;_int&quot;&amp;gt;
		delete from file_tbl where file_no = #{_parameter}
	&amp;lt;/delete&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 게시글 삭제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679389372878&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/boardDelete.do&quot;)
	public String boardDelete(int boardNo, HttpServletRequest request) {
		ArrayList&amp;lt;FileVO&amp;gt; list = service.deleteBoard(boardNo);
		if(list == null) {
			return &quot;redirect:/boardView.do?boardNo=&quot;+boardNo;
		}else {
			String savePath = request.getSession().getServletContext().getRealPath(&quot;/resources/upload/board/&quot;);
			for(FileVO file : list) {
				manager.deleteFile(savePath, file.getFilepath());
			}
			return &quot;redirect:/boardList.do?reqPage=1&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679389383750&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;FileVO&amp;gt; deleteBoard(int boardNo) {
		//삭제이후에 조회를 하면 on delete cascade 때문에 이미 지워진 상태이기 때문에 확인불가
		ArrayList&amp;lt;FileVO&amp;gt; fileList = dao.selectFileList(boardNo);
		int result = dao.deleteBoard(boardNo);
		if(result &amp;gt; 0) {
			return fileList;
		}else {
			return null;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679389393550&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int fileDelete(int boardNo) {
		int result = sqlSession.delete(&quot;board.deleteBoardFile&quot;, boardNo);
		return result;
	}

	public int deleteBoard(int boardNo) {
		int result = sqlSession.delete(&quot;board.deleteBoard&quot;, boardNo);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;boardSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679389407894&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;delete id=&quot;deleteBoardFile&quot; parameterType=&quot;_int&quot;&amp;gt;
		delete from file_tbl where board_no = #{_parameter}
	&amp;lt;/delete&amp;gt;
	&amp;lt;delete id=&quot;deleteBoard&quot; parameterType=&quot;_int&quot;&amp;gt;
		delete from board where board_no = #{_parameter}
	&amp;lt;/delete&amp;gt;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>국비수업/Spring</category>
      <author>_HYE_</author>
      <guid isPermaLink="true">https://recordev.tistory.com/73</guid>
      <comments>https://recordev.tistory.com/73#entry73comment</comments>
      <pubDate>Tue, 21 Mar 2023 13:26:19 +0900</pubDate>
    </item>
    <item>
      <title>78일차 : Mybatis</title>
      <link>https://recordev.tistory.com/72</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;20230320&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mybatis : 데이터의 입력,조회,수정,삭제를 보다 편하게 사용하기 위한 영속성 프레임워크&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Mybatis 사용을 위한 사전 Setting&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. pom.xml에 Maven Repository 에서 검색한 라이브러리 2개 추가 - 사전에 있어야하는 라이브러리가 있다&lt;/p&gt;
&lt;pre id=&quot;code_1679323785422&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- Mybatis를 사용하기 위한 라이브러리(이미 있어야하는 것 : ojdbc, commons-dbcp, spring-jdbc / 추가할것(mybatis, mybatis-spring)) --&amp;gt;
&amp;lt;!-- https://mvnrepository.com/artifact/org.mybatis/mybatis(순수Mybatis) --&amp;gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.mybatis&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;mybatis&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;3.4.6&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&amp;lt;!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring(스프링과 연동하기위해, Mybatis는 독립적으로도 사용이 가능하다 Spring에 종속적인게X) --&amp;gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.mybatis&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;mybatis-spring&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.3.2&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. servlet-context.xml에 mybatis 설정객체 추가&lt;/p&gt;
&lt;pre id=&quot;code_1679323899387&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- jdbc를 사용하지 않고 mybatis를 사용할 것  --&amp;gt;
&amp;lt;!-- Mybatis 설정 객체 --&amp;gt;
&amp;lt;beans:bean id=&quot;sqlSession&quot; class=&quot;org.mybatis.spring.SqlSessionFactoryBean&quot;&amp;gt;
    &amp;lt;beans:property name=&quot;dataSource&quot; ref=&quot;dataSource&quot; /&amp;gt;
    &amp;lt;beans:property name=&quot;configLocation&quot; value=&quot;classpath:mybatis-config.xml&quot; /&amp;gt;
    &amp;lt;beans:property name=&quot;mapperLocations&quot; value=&quot;classpath:/mapper/*SQL.xml&quot; /&amp;gt;
    &amp;lt;!-- 여기서 말하는 classpath는 scr/main/resources 폴더 --&amp;gt;
&amp;lt;/beans:bean&amp;gt;
&amp;lt;!-- 실제 DB작업을 수행하는 객체 --&amp;gt;
&amp;lt;beans:bean id=&quot;sqlSessionTemplate&quot; class=&quot;org.mybatis.spring.SqlSessionTemplate&quot;&amp;gt;
    &amp;lt;beans:constructor-arg ref=&quot;sqlSession&quot; /&amp;gt;
&amp;lt;/beans:bean&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. window - preferences - XML Catalog - User Specified Entries 추가&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;684&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clzlS1/btr4Pq2Ax3R/ckR2tM0wFIhg0lgLfxcSc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clzlS1/btr4Pq2Ax3R/ckR2tM0wFIhg0lgLfxcSc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clzlS1/btr4Pq2Ax3R/ckR2tM0wFIhg0lgLfxcSc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclzlS1%2Fbtr4Pq2Ax3R%2FckR2tM0wFIhg0lgLfxcSc1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;773&quot; height=&quot;684&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;684&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[ Config ]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Location : &lt;a href=&quot;http://mybatis.org/dtd/mybatis-3-config.dtd&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;http://mybatis.org/dtd/mybatis-3-config.dtd&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Key : -//mybatis.org//DTD&amp;nbsp;Config&amp;nbsp;3.0//EN&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[ Mapper ]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Location :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;&gt;http://mybatis.org/dtd/mybatis-3-mapper.dtd&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Key :&lt;span&gt;&amp;nbsp;&lt;/span&gt;-//mybatis.org//DTD Mapper 3.0//EN&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;4. src/main/resources에 mybatis-config와 mapper패키지추가(mapper패키지에 앞으로 작성할 SQL문이 들어갈것)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;734&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckIWPd/btr40FqQgZ3/J31eSBtcz79KQK5mhoFbb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckIWPd/btr40FqQgZ3/J31eSBtcz79KQK5mhoFbb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckIWPd/btr40FqQgZ3/J31eSBtcz79KQK5mhoFbb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckIWPd%2Fbtr40FqQgZ3%2FJ31eSBtcz79KQK5mhoFbb1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;862&quot; height=&quot;734&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;734&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brvMSX/btr41vBCwQG/0thIKCLfV7uxCJP8zVtJ70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brvMSX/btr41vBCwQG/0thIKCLfV7uxCJP8zVtJ70/img.png&quot; data-origin-width=&quot;635&quot; data-origin-height=&quot;737&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4905%; margin-right: 10px;&quot; data-widthpercent=&quot;50.07&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brvMSX/btr41vBCwQG/0thIKCLfV7uxCJP8zVtJ70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrvMSX%2Fbtr41vBCwQG%2F0thIKCLfV7uxCJP8zVtJ70%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;635&quot; height=&quot;737&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N1z4y/btr43XRCXvU/xRgUfh7TKTk8qvqsdyHOiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N1z4y/btr43XRCXvU/xRgUfh7TKTk8qvqsdyHOiK/img.png&quot; data-origin-width=&quot;628&quot; data-origin-height=&quot;731&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.3467%;&quot; data-widthpercent=&quot;49.93&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N1z4y/btr43XRCXvU/xRgUfh7TKTk8qvqsdyHOiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN1z4y%2Fbtr43XRCXvU%2FxRgUfh7TKTk8qvqsdyHOiK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;628&quot; height=&quot;731&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;XML 파일 생성 시 해줘야하는 작업&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. mybatis-config&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 앞으로 새로운 VO를 작성할 때마다 typeAlias를 작성(mapper에서 별명으로 사용하기위함)&lt;/p&gt;
&lt;pre id=&quot;code_1679324267971&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;!DOCTYPE configuration PUBLIC &quot;-//mybatis.org//DTD Config 3.0//EN&quot; &quot;http://mybatis.org/dtd/mybatis-3-config.dtd&quot; &amp;gt;
&amp;lt;configuration&amp;gt;
	&amp;lt;settings&amp;gt;
		&amp;lt;!-- null값이 발생하면 빈칸(&quot;&quot;)이 아닌 null로 처리(null일 때 빈칸으로 처리되는 기본설정이 있기 때문에) --&amp;gt;
		&amp;lt;setting name=&quot;jdbcTypeForNull&quot; value=&quot;NULL&quot; /&amp;gt;
	&amp;lt;/settings&amp;gt;
	&amp;lt;typeAliases&amp;gt;
		&amp;lt;typeAlias type=&quot;kr.or.iei.member.model.vo.Member&quot; alias=&quot;m&quot;/&amp;gt;
		&amp;lt;typeAlias type=&quot;kr.or.iei.notice.model.vo.Notice&quot; alias=&quot;n&quot;/&amp;gt;
	&amp;lt;/typeAliases&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. mapper&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- mapper생성 시 namespace를 지정 -&amp;gt; 자바에서 해당mapper를 찾을 수 있게해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 명명규칙 : beans에서 설정해준 값대로 이름을 붙여줘야한다. servlet-context에서 *SQL이라고 작성했으므로 규칙을 따라야함(앞에 무슨문자가와도 마지막은 SQL로 끝나야함, 대문자 중요)&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- [ Member ]&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller / Service / Dao 에 Component를 해주는것은 물론 Component-scan / 사용할 객체에 @Autowired해주는것은 기존과 동일 단, Dao에서 jdbcTemplate이 아닌 sqlSessionTemplate을 사용할것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DAO&lt;/p&gt;
&lt;pre id=&quot;code_1679324639621&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Repository
public class MemberDao {
	@Autowired
	private SqlSessionTemplate sqlSession;
	//private JdbcTemplate jdbc;
	//import - jdbc / rowMapper 다 지워도 된다(rowmapper는 mybatis를 사용하면 필요없기때문에 클래스도 삭제)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;index.jsp&lt;/p&gt;
&lt;pre id=&quot;code_1679324803954&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
    &amp;lt;%@taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;Spring_Mybatis&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;c:choose&amp;gt;
		&amp;lt;c:when test=&quot;${empty sessionScope.m }&quot;&amp;gt;
			&amp;lt;form action=&quot;login.do&quot; method=&quot;post&quot;&amp;gt;
				&amp;lt;fieldset&amp;gt;
					&amp;lt;legend&amp;gt;로그인&amp;lt;/legend&amp;gt;
					아이디 : &amp;lt;input type=&quot;text&quot; name=&quot;memberId&quot;&amp;gt;&amp;lt;br&amp;gt;
					비밀번호 : &amp;lt;input type=&quot;password&quot; name=&quot;memberPw&quot;&amp;gt;&amp;lt;br&amp;gt;
					&amp;lt;input type=&quot;submit&quot; value=&quot;로그인&quot;&amp;gt;
				&amp;lt;/fieldset&amp;gt;
			&amp;lt;/form&amp;gt;
			&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/joinFrm.do&quot;&amp;gt;회원가입&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
		&amp;lt;/c:when&amp;gt;
		&amp;lt;c:otherwise&amp;gt;
			&amp;lt;h2&amp;gt;[${sessionScope.m.memberName }]&amp;lt;/h2&amp;gt;
			&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/logout.do&quot;&amp;gt;로그아웃&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
			&amp;lt;form action=&quot;/searchMemberId.do&quot;&amp;gt;
				조회할 아이디 입력 : 
				&amp;lt;input type=&quot;text&quot; name=&quot;memberId&quot;&amp;gt;
				&amp;lt;input type=&quot;submit&quot; value=&quot;조회&quot;&amp;gt;
			&amp;lt;/form&amp;gt;
			&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/allMember.do&quot;&amp;gt;전체회원조회&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
			&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/mypage.do&quot;&amp;gt;마이페이지&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
			&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/noticeList.do&quot;&amp;gt;공지사항&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
			&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/deleteMember.do?memberNo=${sessionScope.m.memberNo }&quot;&amp;gt;회원탈퇴&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
		&amp;lt;/c:otherwise&amp;gt;
	&amp;lt;/c:choose&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 로그인 / 로그아웃&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679324658138&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/login.do&quot;)
	public String login(Member m, HttpSession session) {
		Member loginMember = service.selectOneMember(m);
		if(loginMember != null) {
			session.setAttribute(&quot;m&quot;, loginMember);
		}
		return &quot;redirect:/&quot;;
	}
	
	@RequestMapping(value=&quot;/logout.do&quot;)
	public String logout(HttpSession session) {
		session.invalidate();
		return &quot;redirect:/&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679324681837&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public Member selectOneMember(Member member) {
		return dao.selectOneMember(member);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679324695349&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public Member selectOneMember(Member member) {
		/*
		 	String query = &quot;select * from member_tbl where member_id = ? and member_pw = ?&quot;;
			Object[] params = {m.getMemberId(), m.getMemberPw()};
			List list = jdbc.query(query, params, new MemberRowMapper());
			return (Member)list.get(0);
		 */
		//조회결과가 하나이기 때문에 selectOne
		//selectOneMember앞의 member는 Mapper 중 namespace를 찾는 것
		//즉, mapper가 여러개 있을 텐데 namespace가 member인 Mapper를 찾아가서 id가 selectOneMember인 쿼리를 수행하라는 의미
		Member m = sqlSession.selectOne(&quot;member.selectOneMember&quot;,member); //dao코드 완료 -&amp;gt; mapper에 sql코드 작성
		return m;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;memberSQL(mapper)&lt;/p&gt;
&lt;pre id=&quot;code_1679324749021&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;!DOCTYPE mapper PUBLIC &quot;-//mybatis.org//DTD Mapper 3.0//EN&quot; &quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot; &amp;gt;
&amp;lt;mapper namespace=&quot;member&quot;&amp;gt;
	&amp;lt;!-- mapper를 만들면 cache-ref를 지워주고 mapper에 이름을 붙여준다. --&amp;gt;
  	
  	&amp;lt;!-- Member가 여러개이기 때문에 패키지까지 다 적어줘야함(kr.or.iei.member.model.vo.Member) : 다 적어주기 힘드므로 config에서 별명으로 지정 가능 --&amp;gt;
  	&amp;lt;select id=&quot;selectOneMember&quot; parameterType=&quot;m&quot; resultType=&quot;m&quot;&amp;gt;
  		&amp;lt;!-- 세미콜론(;) 찍으면 안됨 --&amp;gt;
  		&amp;lt;!-- 위치홀더에 넣어줄 값은 파라미터로 들어온 m에 들어가있음 --&amp;gt;
  		select  
  			&amp;lt;!-- 컬럼명의 별칭을 Member(VO)의 변수명으로 지정해주면 resultType의 m에 자동으로 넣어준다 --&amp;gt;
  			member_no as memberNo, 
  			member_id as memberId, 
  			member_pw as memberPw, 
  			member_name as memberName, 
  			member_phone as memberPhone, 
  			member_email as memberEmail
  		from member_tbl where member_id=#{memberId} and member_pw=#{memberPw}
  	&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 아이디 검색으로 회원조회&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679324821060&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/searchMemberId.do&quot;)
	public String searchMemberId(String memberId, Model model) {
		Member m = service.selectOneMember(memberId);
		if(m != null) {
			model.addAttribute(&quot;m&quot;, m);
			return &quot;member/searchMemberId&quot;;
		}else {
			return &quot;redirect:/&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679324834950&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public Member selectOneMember(String memberId) {
		return dao.selectOneMember(memberId);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679324846512&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public Member selectOneMember(String memberId) {
		Member m = sqlSession.selectOne(&quot;member.searchMemberId&quot;, memberId);
		return m;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;memberSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679324860055&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  	&amp;lt;select id=&quot;searchMemberId&quot; parameterType=&quot;string&quot; resultType=&quot;m&quot;&amp;gt;
  		select
  			member_no as memberNo, 
  			member_id as memberId, 
  			member_pw as memberPw, 
  			member_name as memberName, 
  			member_phone as memberPhone, 
  			member_email as memberEmail
  		from member_tbl where member_id=#{_parameter}
  		&amp;lt;!-- where에 memberId를 넣어줘도 되지만  매개변수가 vo형태가 아니라 단일갯수이면 _parameter를 적어주면된다. 문자/숫자 상관없이 하나이기만 하면 전부! --&amp;gt;
  	&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 전체회원조회&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679324910786&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/allMember.do&quot;)
	public String allMember(Model model) {
		ArrayList&amp;lt;Member&amp;gt; list = service.selectAllMmeber();
		model.addAttribute(&quot;list&quot;, list);
		return &quot;member/allMember&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679324922531&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;Member&amp;gt; selectAllMmeber() {
		return dao.selectAllMember();
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679324934398&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;Member&amp;gt; selectAllMember() {
		List list = sqlSession.selectList(&quot;member.selectAllMember&quot;);
		return (ArrayList&amp;lt;Member&amp;gt;)list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;memberSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679324965364&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  	&amp;lt;!-- 쿼리문 실행을 위한 매개변수가 없는경우 parameterType 생략 --&amp;gt;
  	&amp;lt;!-- 이미 dao에서 selectList()를 사용했으므로 list로 오는건 확정 -&amp;gt; list안에 들어가는 자료형으로 지정해주면된다 &quot;m&quot; --&amp;gt;
  	&amp;lt;select id=&quot;selectAllMember&quot; resultType=&quot;m&quot;&amp;gt;
  		select
  			member_no as memberNo, 
  			member_id as memberId, 
  			member_pw as memberPw, 
  			member_name as memberName, 
  			member_phone as memberPhone, 
  			member_email as memberEmail
  		from member_tbl
  		order by member_no
  	&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 회원가입&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679325033346&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/joinFrm.do&quot;)
	public String joinFrm() {
		return &quot;member/joinFrm&quot;;
	}
	
	@RequestMapping(value=&quot;/join.do&quot;)
	public String join(Member member) {
		int result = service.insertMember(member);
		if(result &amp;gt; 0) {
			return &quot;redirect:/&quot;;
		}else {
			return &quot;redirect:/joinFrm.do&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679325044569&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int insertMember(Member member) {
		return dao.insertMember(member);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679325054536&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int insertMember(Member member) {
		int result = sqlSession.insert(&quot;member.insertMember&quot;, member);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;memberSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679325069827&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  	&amp;lt;!-- insert/update/delete는 무조건 resultType이 int로 고정되어있으므로 명시하면 안된다. 쓰지않고 항상 int로 빠지는것 --&amp;gt;
  	&amp;lt;insert id=&quot;insertMember&quot; parameterType=&quot;m&quot; &amp;gt;
  		insert into member_tbl values(member_seq.nextval, #{memberId}, #{memberPw}, #{memberName}, #{memberPhone}, #{memberEmail})
  	&amp;lt;/insert&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 회원탈퇴&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679325087400&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/deleteMember.do&quot;)
	public String deleteMember(int memberNo) {
		int result = service.deleteMember(memberNo);
		if(result &amp;gt; 0) {
			return &quot;redirect:/logout.do&quot;;
		}else {
			return &quot;redirect:/&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679325097721&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int deleteMember(int memberNo) {
		return dao.deleteMember(memberNo);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679325106035&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int deleteMember(int memberNo) {
		int result = sqlSession.delete(&quot;member.deleteMember&quot;, memberNo);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;memberSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679325149441&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  	&amp;lt;delete id=&quot;deleteMember&quot; parameterType=&quot;_int&quot;&amp;gt;
  		delete from member_tbl where member_no = #{_parameter}
  	&amp;lt;/delete&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 마이페이지(정보수정)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679325163984&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/mypage.do&quot;)
	public String mypage() {
		return &quot;member/mypage&quot;;
	}
	@RequestMapping(value=&quot;/updateMember.do&quot;)
	public String updateMember(Member member, @SessionAttribute(required = false) Member m) {
		int result = service.updateMember(member);
		if(result &amp;gt; 0) {
			m.setMemberPw(member.getMemberPw());
			m.setMemberPhone(member.getMemberPhone());
			m.setMemberEmail(member.getMemberEmail());
			return &quot;redirect:/mypage.do&quot;;
		}else {
			return &quot;redirect:/&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679325173717&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int updateMember(Member member) {
		return dao.updateMember(member);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679325183038&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int updateMember(Member member) {
		int result = sqlSession.update(&quot;member.updateMember&quot;, member);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;memberSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679325196313&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  	&amp;lt;update id=&quot;updateMember&quot; parameterType=&quot;m&quot;&amp;gt;
  		update member_tbl set 
  			member_pw = #{memberPw}, 
  			member_phone = #{memberPhone}, 
  			member_email = #{memberEmail}
  		where member_no = #{memberNo}
  	&amp;lt;/update&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- [ Notice ]&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679325278510&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.notice.controller;

import java.util.ArrayList;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import kr.or.iei.notice.model.service.NoticeService;
import kr.or.iei.notice.model.vo.Notice;

@Controller
public class NoticeController {
	@Autowired
	private NoticeService service;
	/*
	 &amp;lt;공지사항&amp;gt;
	 1. 전체목록
	 2. 글쓰기
	 3. 상세보기
	 4. 수정
	 5. 삭제
	 */
	@RequestMapping(value=&quot;/noticeList.do&quot;)
	public String noticeList(Model model) {
		ArrayList&amp;lt;Notice&amp;gt; list = service.selectAllNotice();
		if(list != null) {
			model.addAttribute(&quot;list&quot;, list);
			return &quot;notice/noticeList&quot;;
		}else {
			return &quot;redirect:/&quot;;
		}
	}
	@RequestMapping(value=&quot;/noticeView.do&quot;)
	public String noticeView(int noticeNo, Model model) {
		Notice n = service.selectOneNotice(noticeNo);
		if(n != null) {
			model.addAttribute(&quot;n&quot;, n);
			return &quot;notice/noticeView&quot;;
		}else {
			return &quot;redirect:/noticeList.do&quot;;
		}
	}
	@RequestMapping(value=&quot;/noticeWriteFrm.do&quot;)
	public String noticeWriteFrm() {
		return &quot;notice/noticeWriteFrm&quot;;
	}
	@RequestMapping(value=&quot;/insertNotice.do&quot;)
	public String insertNotice(Notice n) {
		int result = service.insertNotice(n);
		if(result &amp;gt; 0) {
			return &quot;redirect:/noticeList.do&quot;;
		}else {
			return &quot;notice/noticeWriterFrm&quot;;
		}
	}
	@RequestMapping(value=&quot;/updateNoticeFrm.do&quot;)
	public String updateNoticeFrm(int noticeNo, Model model) {
		Notice n = service.selectOneNotice(noticeNo);
		if(n != null) {
			model.addAttribute(&quot;n&quot;, n);
			return &quot;notice/updateNoticeFrm&quot;;
		}else {
			return &quot;redirect:/noticeList.do&quot;;
		}
	}
	@RequestMapping(value=&quot;/updateNotice.do&quot;)
	public String updateNotice(Notice n) {
		int result = service.updateNotice(n);
		if(result &amp;gt; 0) {
			return &quot;redirect:/noticeView.do?noticeNo=&quot;+n.getNoticeNo();
		}else {
			return &quot;redirce:/noticeList.do&quot;;
		}
	}
	@RequestMapping(value=&quot;/deleteNotice.do&quot;)
	public String deleteNotice(int noticeNo) {
		int result = service.deleteNotice(noticeNo);
		if(result&amp;gt;0) {
			return &quot;redirect:/noticeList.do&quot;;
		}else {
			return &quot;redirect:/noticeView.do?noticeNo=&quot;+noticeNo;
		}
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679325287676&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.notice.model.service;

import java.util.ArrayList;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import kr.or.iei.notice.model.dao.NoticeDao;
import kr.or.iei.notice.model.vo.Notice;

@Service
public class NoticeService {
	@Autowired
	private NoticeDao dao;

	public ArrayList&amp;lt;Notice&amp;gt; selectAllNotice() {
		return dao.selectAllNotice();
	}

	public Notice selectOneNotice(int noticeNo) {
		return dao.selectOneNotice(noticeNo);
	}

	public int insertNotice(Notice n) {
		return dao.insertNotice(n);
	}

	public int updateNotice(Notice n) {
		return dao.updateNotice(n);
	}

	public int deleteNotice(int noticeNo) {
		return dao.deleteNotice(noticeNo);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679325294881&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.notice.model.dao;

import java.util.ArrayList;
import java.util.List;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import kr.or.iei.notice.model.vo.Notice;

@Repository
public class NoticeDao {
	@Autowired
	private SqlSessionTemplate sqlSession;

	public ArrayList&amp;lt;Notice&amp;gt; selectAllNotice() {
		List list = sqlSession.selectList(&quot;notice.selectAllNotice&quot;);
		return (ArrayList&amp;lt;Notice&amp;gt;)list;
	}

	public Notice selectOneNotice(int noticeNo) {
		Notice n = sqlSession.selectOne(&quot;notice.selectOneNotice&quot;, noticeNo);
		return n;
	}

	public int insertNotice(Notice n) {
		int result = sqlSession.insert(&quot;notice.insertNotice&quot;, n);
		return result;
	}

	public int updateNotice(Notice n) {
		int result = sqlSession.update(&quot;notice.updateNotice&quot;, n);
		return result;
	}

	public int deleteNotice(int noticeNo) {
		int result = sqlSession.delete(&quot;notice.deleteNotice&quot;, noticeNo);
		return result;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;noticeSQL&lt;/p&gt;
&lt;pre id=&quot;code_1679325311718&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;!DOCTYPE mapper PUBLIC &quot;-//mybatis.org//DTD Mapper 3.0//EN&quot; &quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot; &amp;gt;
&amp;lt;mapper namespace=&quot;notice&quot;&amp;gt;
	&amp;lt;select id=&quot;selectAllNotice&quot; resultType=&quot;n&quot;&amp;gt;
		select 
			notice_no as noticeNo,
			notice_title as noticeTitle,
			notice_writer as noticeWriter,
			notice_date as noticeDate
		from notice
		order by 1 desc
	&amp;lt;/select&amp;gt;
	&amp;lt;select id=&quot;selectOneNotice&quot; parameterType=&quot;_int&quot; resultType=&quot;n&quot;&amp;gt;
		select 
			notice_no as noticeNo,
			notice_title as noticeTitle,
			notice_writer as noticeWriter,
			notice_content as noticeContent,
			notice_date as noticeDate
		from notice where notice_no = #{_parameter}
	&amp;lt;/select&amp;gt;
	&amp;lt;insert id=&quot;insertNotice&quot; parameterType=&quot;n&quot;&amp;gt;
		insert into notice values(notice_seq.nextval, #{noticeTitle}, #{noticeWriter}, #{noticeContent}, to_char(sysdate, 'yyyy-mm-dd'))
	&amp;lt;/insert&amp;gt;
	&amp;lt;update id=&quot;updateNotice&quot; parameterType=&quot;n&quot;&amp;gt;
		update notice set notice_title = #{noticeTitle}, notice_content = #{noticeContent} where notice_no = #{noticeNo}
	&amp;lt;/update&amp;gt;
	&amp;lt;delete id=&quot;deleteNotice&quot; parameterType=&quot;_int&quot;&amp;gt;
		delete from notice where notice_no = #{_parameter}
	&amp;lt;/delete&amp;gt;
&amp;lt;/mapper&amp;gt;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>국비수업/Spring</category>
      <author>_HYE_</author>
      <guid isPermaLink="true">https://recordev.tistory.com/72</guid>
      <comments>https://recordev.tistory.com/72#entry72comment</comments>
      <pubDate>Tue, 21 Mar 2023 00:15:28 +0900</pubDate>
    </item>
    <item>
      <title>77일차 : SpringMVC - 게시판2</title>
      <link>https://recordev.tistory.com/71</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;20230317&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어제 작성했던 파일네이밍을 클래스의 메소드로 따로빼서 사용할것 (다른데에서도 똑같이 사용하기 때문에)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 업로드시 board notice 둘다 파일업로드를 한다고 가정하면&amp;nbsp;달라지는&amp;nbsp;부분은&amp;nbsp;파일이&amp;nbsp;올라가는&amp;nbsp;경로+실제파일&amp;nbsp; &lt;br /&gt;-&amp;gt;&amp;nbsp;공통적인&amp;nbsp;부분을&amp;nbsp;따로&amp;nbsp;만들어서&amp;nbsp;매개변수를&amp;nbsp;받아&amp;nbsp;달라지는&amp;nbsp;부분만&amp;nbsp;수정(모듈화)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FileManager.java&lt;/p&gt;
&lt;pre id=&quot;code_1679036546507&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Component //객체생성을 위한것 - servlet-context.xml의 component-scan과 함께 이루어져야한다.
public class FileManager {
	//파일업로드를 위한 메소드
	public String upload(String savePath, MultipartFile file) {
		String filename = file.getOriginalFilename();
		String onlyFilename = filename.substring(0, filename.lastIndexOf(&quot;.&quot;));
		String extention = filename.substring(filename.lastIndexOf(&quot;.&quot;)); 
		String filepath = null;
		int count = 0; 
		while(true) {
			if(count == 0) {
				filepath = onlyFilename+extention;				
			}else {
				filepath = onlyFilename+&quot;_&quot;+count+extention;	
			}
			File checkFile = new File(savePath+filepath);
			if(!checkFile.exists()) {
				break;
			}
			count++;
		}
		try {
			FileOutputStream fos = new FileOutputStream(savePath+filepath);
			BufferedOutputStream bos = new BufferedOutputStream(fos);
			byte[] bytes = file.getBytes();
			bos.write(bytes);
			bos.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//filepath를 return을 String으로 잡아준것
		return filepath;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- servlet-context.xml에서 component-scan을 잊지말자&lt;/p&gt;
&lt;pre id=&quot;code_1679036589761&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;context:component-scan base-package=&quot;common&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 수정된 글작성하기(INSERT)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FileManager를 사용하기위해 상단에 선언&lt;/p&gt;
&lt;pre id=&quot;code_1679036899937&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@Autowired
	private FileManager fileManager;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679036653097&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	
	@RequestMapping(value=&quot;/boardWrite.do&quot;)
	//파일업로드를 진행하기위해 request를 불러옴
	public String boardWrite(Board b, MultipartFile[] boardFile, HttpServletRequest request) {
		//파일목록을 저장할 list생성
		ArrayList&amp;lt;FileVO&amp;gt; fileList = new ArrayList&amp;lt;FileVO&amp;gt;();
		//제목,내용,작성자는 매개변수 b에 모두 들어있음
		//파일이름은 b에 들어있지X 매개변수로 받음 -&amp;gt; 여러개를 받을거기때문에 자료형은 배열형태로
		//첨부파일은 input type=&quot;file&quot;의 name으로 매개변수를 생성 -&amp;gt; 첨부파일 갯수만큼 배열길이 생성
		//첨부파일을 첨부하지 않아도 배열은 길이가 1
		//System.out.println(b);
		//System.out.println(boardFile.length);
		//첨부파일 존재유무를 구분하는 법 - 배열의 첫번째가 비어있는지 아닌지 확인
		//if(!boardFile[0].isEmpty()) {} if문은 이렇게 작성해주는게 좋다.
		if(boardFile[0].isEmpty()) {
			//첨부파일이 없는경우 진행할 로직이 없음
		}else {
			//첨부파일이 있는경우 파일업로드작업 수행
			//1. 파일업로드 경로 설정
			//getRealPath까지가 webapp
			String savePath = request.getSession().getServletContext().getRealPath(&quot;/resources/upload/board/&quot;);
			//2. 배열이므로 반복문을 이용해서 파일업로드 처리
			for(MultipartFile file : boardFile) {
				//파일명이 기존업로드한 파일명과 중복되면 기존파일을 삭제하고 새파일로 덮어쓰기됨 -&amp;gt; 파일명이 중복되지않게 처리해야 함
				//(cos라이브러리에서는 new DefaultFileRenamePolicy가 파일이름이 중복일 경우 새로운이름을 붙여줬음 name1 name2)
				String filename = file.getOriginalFilename(); //사용자가 업로드한 이름
				//이걸 그대로 업로드하면 파일명이 중복되엇을 때 문제가 발생
				//가정 : filename =&amp;gt; test.txt인데 중복인 경우 =&amp;gt; test_1.txt 확장자기준 앞을 바꿈
				String filepath = fileManager.upload(savePath, file);
				
				
				/*
				//우선 text    .txt를 분리함
				String onlyFilename = filename.substring(0, filename.lastIndexOf(&quot;.&quot;));//test 0부터 뒤에서부터 .의 위치의 숫자를세서 그만큼까지
				String extention = filename.substring(filename.lastIndexOf(&quot;.&quot;)); //.txt 매개변수를 하나만주면 그 매개변수부터 끝까지라는 의미
				//실제 업로드할 파일명
				String filepath = null;
				//파일명 중복 시 뒤에 붙일 숫자
				int count = 0; //횟수가 정해져있지 않음 &amp;gt; while문을 무한으로 돌리고 중복이아닐때 빠져나옴
				while(true) {
					if(count == 0) {
						//첫번째 검증인 경우 숫자를 붙이지X
						filepath = onlyFilename+extention;				//test.txt
					}else {
						filepath = onlyFilename+&quot;_&quot;+count+extention;	//test_1.txt
					}
					File checkFile = new File(savePath+filepath);
					if(!checkFile.exists()) {
						//checkFile이 존재하는지 물어보는 것 -&amp;gt; 중복이 아닐 때 break 
						break;
					}
					count++;
				}
				//파일명 중복체크 끝 -&amp;gt; 업로드할 파일명 확정 -&amp;gt; 파일업로드진행
				//2-2. 중복처리가 끝난 파일 업로드
				try {
					//파일업로드를 위한 주스트림생성
					FileOutputStream fos = new FileOutputStream(savePath+filepath);
					//성능향상을 위한 보조스트림 생성
					BufferedOutputStream bos = new BufferedOutputStream(fos);
					//파일업로드
					byte[] bytes = file.getBytes();
					bos.write(bytes);
					bos.close();
				} catch (FileNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} */
				
				
				
				//파일업로드 끝(1개)
				//DB에 저장하기 위해 FileVO형태의 객체를 생성해서 fileList추가
				FileVO fileVO = new FileVO();
				fileVO.setFilename(filename);
				fileVO.setFilepath(filepath);
				fileList.add(fileVO);
			}//for문 끝
		}
		//비즈니스로직(board와 file_tbl에 insert진행)
		int result = service.insertBoard(b, fileList);
		if(result == (fileList.size()+1)) {
			//insert가 총 첨부파일+1개만큼 일어남 -&amp;gt; board인서트(1번) + 첨부파일인서트(여러번)
			//result를 누계했으므로 
			return &quot;redirect:/boardList.do&quot;; //컨트롤러를 거쳐가지않으면 리스트내용이 보이지않음
		}else {
			return &quot;redirect:/&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 주석 제외 Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679036767970&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	
	@RequestMapping(value=&quot;/boardWrite.do&quot;)
	public String boardWrite(Board b, MultipartFile[] boardFile, HttpServletRequest request) {
		ArrayList&amp;lt;FileVO&amp;gt; fileList = new ArrayList&amp;lt;FileVO&amp;gt;();
		if(boardFile[0].isEmpty()) {
		}else {
			String savePath = request.getSession().getServletContext().getRealPath(&quot;/resources/upload/board/&quot;);
			for(MultipartFile file : boardFile) {
				String filename = file.getOriginalFilename(); //사용자가 업로드한 이름
				String filepath = fileManager.upload(savePath, file);	
				FileVO fileVO = new FileVO();
				fileVO.setFilename(filename);
				fileVO.setFilepath(filepath);
				fileList.add(fileVO);
			}
		}
		int result = service.insertBoard(b, fileList);
		if(result == (fileList.size()+1)) {
			return &quot;redirect:/boardList.do&quot;; 
		}else {
			return &quot;redirect:/&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service + Dao는 변화없음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 게시글 전체 목록(BoardList)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679036878490&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/boardList.do&quot;)
	public String boardList(Model model) {
		ArrayList&amp;lt;Board&amp;gt; list = service.selectBoardList();
		model.addAttribute(&quot;list&quot;, list);
		return &quot;board/boardList&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679036929738&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;Board&amp;gt; selectBoardList() {
		ArrayList&amp;lt;Board&amp;gt; list = dao.selectBoardList();
		return list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679036948242&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;Board&amp;gt; selectBoardList() {
		String query = &quot;select board_no, board_title, board_writer, board_date from board order by 1 desc&quot;;
		List list = jdbc.query(query, new BoardListRowMapper());
		return (ArrayList&amp;lt;Board&amp;gt;)list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;List를 확인할때만 사용할 RowMapper - BoardListRowMapper.java( boardContent 가 없는걸 확인)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; RowMapper는 필요한 만큼 생성하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1679036981562&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.board.model.vo;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

public class BoardListRowMapper implements RowMapper{
	
	@Override
	public Object mapRow(ResultSet rset, int rowNum) throws SQLException {
		Board b = new Board();
		b.setBoardNo(rset.getInt(&quot;board_no&quot;));
		b.setBoardTitle(rset.getString(&quot;board_title&quot;));
		b.setBoardWriter(rset.getString(&quot;board_writer&quot;));
		b.setBoardDate(rset.getString(&quot;board_date&quot;));
		return b;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화면구현 JSP&lt;/p&gt;
&lt;pre id=&quot;code_1679037061682&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
    &amp;lt;%@taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot; %&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;게시물 목록&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;c:if test=&quot;${not empty sessionScope.m}&quot;&amp;gt;
		&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/boardWriteFrm.do&quot;&amp;gt;게시글 작성하기&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
	&amp;lt;/c:if&amp;gt;
	&amp;lt;table border=&quot;1&quot;&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;th&amp;gt;글번호&amp;lt;/th&amp;gt;
			&amp;lt;th&amp;gt;제목&amp;lt;/th&amp;gt;
			&amp;lt;th&amp;gt;작성자&amp;lt;/th&amp;gt;
			&amp;lt;th&amp;gt;작성일&amp;lt;/th&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;c:forEach items=&quot;${list }&quot; var=&quot;b&quot;&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;td&amp;gt;${b.boardNo }&amp;lt;/td&amp;gt;
				&amp;lt;td&amp;gt;&amp;lt;a href=&quot;/boardView.do?boardNo=${b.boardNo}&quot;&amp;gt;${b.boardTitle }&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;
				&amp;lt;td&amp;gt;${b.boardWriter }&amp;lt;/td&amp;gt;
				&amp;lt;td&amp;gt;${b.boardDate }&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
		&amp;lt;/c:forEach&amp;gt;
	&amp;lt;/table&amp;gt;
	&amp;lt;a href=&quot;/&quot;&amp;gt;메인으로&amp;lt;/a&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 게시글 상세보기(BoardView)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679037087802&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/boardView.do&quot;)
	public String boardView(int boardNo, Model model) {
		Board b = service.selectOneBoard(boardNo);
		if(b != null) {
			model.addAttribute(&quot;b&quot;, b);
			return &quot;board/boardView&quot;;			
		}else {
			return &quot;redirect:/boardList.do&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679037117281&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public Board selectOneBoard(int boardNo) {
		//보드 조회
		Board b = dao.selectOneBoard(boardNo);
		//파일 조회
		if(b != null) {
			ArrayList&amp;lt;FileVO&amp;gt; fileList = dao.selectFileList(boardNo);
			b.setFileList(fileList);
		}
		return b;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao 1 : Board 테이블 조회&lt;/p&gt;
&lt;pre id=&quot;code_1679037150946&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public Board selectOneBoard(int boardNo) {
		String query = &quot;select * from board where board_no = ?&quot;;
		Object[] params = {boardNo};
		//이번엔 content가 있기 때문에 BoardListRowMapper는 사용할 수 없음(boardContent가 없음)
		List list = jdbc.query(query, params, new BoardRowMapper());
		if(list.isEmpty()) {
			return null;
		}else {
			return (Board)list.get(0);		
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao 2 : File_tbl 테이블 조회&lt;/p&gt;
&lt;pre id=&quot;code_1679037176530&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;FileVO&amp;gt; selectFileList(int boardNo) {
		String query = &quot;select * from file_tbl where board_no = ?&quot;;
		Object[] params = {boardNo};
		List list = jdbc.query(query, params, new FileRowMapper());
		return (ArrayList&amp;lt;FileVO&amp;gt;)list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일도 전부 조회해서 Board VO에 있는 fileList에 set으로 넣어준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화면구현 JSP&lt;/p&gt;
&lt;pre id=&quot;code_1679037255050&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
    &amp;lt;%@taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;게시물 상세보기&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;table border=&quot;1&quot;&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;th&amp;gt;글번호&amp;lt;/th&amp;gt;
			&amp;lt;td&amp;gt;${b.boardNo }&amp;lt;/td&amp;gt;
			&amp;lt;th&amp;gt;제목&amp;lt;/th&amp;gt;
			&amp;lt;td&amp;gt;${b.boardTitle }&amp;lt;/td&amp;gt;
			&amp;lt;th&amp;gt;작성자&amp;lt;/th&amp;gt;
			&amp;lt;td&amp;gt;${b.boardWriter }&amp;lt;/td&amp;gt;
			&amp;lt;th&amp;gt;작성일&amp;lt;/th&amp;gt;
			&amp;lt;td&amp;gt;${b.boardDate }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;th&amp;gt;첨부파일&amp;lt;/th&amp;gt;
			&amp;lt;td colspan=&quot;7&quot;&amp;gt;
				&amp;lt;%--첨부파일은 여러개일 수 있으므로 for문을 돌림 --%&amp;gt;
				&amp;lt;c:forEach items=&quot;${b.fileList }&quot; var=&quot;f&quot;&amp;gt;
					&amp;lt;a href=&quot;/boardFileDown.do?fileNo=${f.fileNo }&quot;&amp;gt;${f.filename }&amp;lt;/a&amp;gt;
				&amp;lt;/c:forEach&amp;gt;
			&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;th&amp;gt;내용&amp;lt;/th&amp;gt;
			&amp;lt;td colspan=&quot;7&quot;&amp;gt;${b.boardContent }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
	&amp;lt;/table&amp;gt;
	&amp;lt;c:if test=&quot;${not empty sessionScope.m &amp;amp;&amp;amp; sessionScope.m.memberId eq b.boardWriter }&quot;&amp;gt;
			&amp;lt;a href=&quot;/boardUpdateFrm.do?boardNo=${b.boardNo }&quot;&amp;gt;수정&amp;lt;/a&amp;gt;
			&amp;lt;a href=&quot;/boardDelete.do?boardNo=${b.boardNo }&quot;&amp;gt;삭제&amp;lt;/a&amp;gt;
	&amp;lt;/c:if&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 파일다운로드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679040230395&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/boardFileDown.do&quot;)
	public void boardFileDown(int fileNo, HttpServletRequest request, HttpServletResponse response) {
		//fileNo : DB에서 filename, filepath를 조회해오기위한 용도
		//request : 파일위치 찾을 때 사용
		//response : 파일다운로드 로직 구현 시 사용
		//리턴을 하지않음 - 페이지이동이 필요없으므로
		
		//filename과 filepath를 찾아오기위해서
		FileVO file = service.getFile(fileNo);
		
		//파일경로
		String root = request.getSession().getServletContext().getRealPath(&quot;/resources/upload/board/&quot;);
		String downFile = root+file.getFilepath();
		
		//파일을 읽어오기위한 주스트림생성(속도개선을위한 보조스트림생성)
		try {
			FileInputStream fis = new FileInputStream(downFile);
			BufferedInputStream bis = new BufferedInputStream(fis);
			//읽어온 파일을 사용자에게 내보낼 스트림생성
			ServletOutputStream sos = response.getOutputStream();
			BufferedOutputStream bos = new BufferedOutputStream(sos);
			
			//파일명 처리
			String resFilename = new String(file.getFilename().getBytes(&quot;UTF-8&quot;), &quot;ISO-8859-1&quot;);
			response.setContentType(&quot;application/octet-stream&quot;);//파일형식이란것을 알려줌
			response.setHeader(&quot;Content-Disposition&quot;, &quot;attachment;filename=&quot;+resFilename);//파일이름을 알려줌
			//파일전송
			while(true) {
				int read = bis.read();
				//파일을 계속 읽다가 다읽으면 종료
				if(read != -1) {
					bos.write(read);
				}else {
					break;
				}
			}
			bos.close();
			bis.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service(파일path와 name을 찾기위한 로직)&lt;/p&gt;
&lt;pre id=&quot;code_1679040795139&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public FileVO getFile(int fileNo) {
		return dao.getFile(fileNo);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1679040812370&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public FileVO getFile(int fileNo) {
		String query = &quot;select * from file_tbl where file_no = ?&quot;;
		Object[] params = {fileNo};
		List list = jdbc.query(query, params, new FileRowMapper());
		return (FileVO)list.get(0);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 게시글 삭제( deleteBoard )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679037354946&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/boardDelete.do&quot;)
	public String boardDelete(int boardNo, HttpServletRequest request) {
		//int result = service.deleteBoard(boardNo);
		//원래는 int로 받는게 맞지만 file또한 지워야 하기 때문에 file목록을 가져올것
		//DB를 삭제하고, 서버에 업로드 되어있는 파일을 지우기 위해서 파일목록을 가져옴
		ArrayList&amp;lt;FileVO&amp;gt; list = service.deleteBoard(boardNo);
		//list가 null이면 실패, 아니면 성공
		if(list == null) {
			return &quot;redirect:/boardView.do?boardNo=&quot;+boardNo;
		}else {
			//성공 시 실제 file을 삭제
			String savePath = request.getSession().getServletContext().getRealPath(&quot;/resources/upload/board/&quot;);
			for(FileVO file : list) {
				boolean deleteResult = fileManager.deleteFile(savePath, file.getFilepath());
				if(deleteResult) {
					System.out.println(&quot;파일삭제성공&quot;);
				}else {
					System.out.println(&quot;파일삭제실패&quot;);
				}
			}
			return &quot;redirect:/boardList.do&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service - 파일또한 삭제해줘야 하기 때문에 파일먼저 조회 후 게시글 삭제진행&lt;/p&gt;
&lt;pre id=&quot;code_1679037379522&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;FileVO&amp;gt; deleteBoard(int boardNo) {
		//삭제이후에 조회를 하면 on delete cascade 때문에 이미 지워진 상태이기 때문에 확인불가
		ArrayList&amp;lt;FileVO&amp;gt; fileList = dao.selectFileList(boardNo);
		int result = dao.deleteBoard(boardNo);
		if(result &amp;gt; 0) {
			return fileList;
		}else {
			return null;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao 1 : 파일목록 조회&lt;/p&gt;
&lt;pre id=&quot;code_1679037420025&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;FileVO&amp;gt; selectFileList(int boardNo) {
		String query = &quot;select * from file_tbl where board_no = ?&quot;;
		Object[] params = {boardNo};
		List list = jdbc.query(query, params, new FileRowMapper());
		return (ArrayList&amp;lt;FileVO&amp;gt;)list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao 2 : 게시글 삭제&lt;/p&gt;
&lt;pre id=&quot;code_1679037439475&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int deleteBoard(int boardNo) {
		String query = &quot;delete from board where board_no = ?&quot;;
		Object[] params = {boardNo};
		int result = jdbc.update(query, params);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 게시글 수정(BoardUpdate)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 기존 게시글 정보를 가지고 수정폼으로 이동&lt;/p&gt;
&lt;pre id=&quot;code_1679038801694&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/boardUpdateFrm.do&quot;)
	public String boardUpdateFrm(int boardNo, Model model) {
		Board b = service.selectOneBoard(boardNo);
		model.addAttribute(&quot;b&quot;, b);
		return &quot;board/BoardUpdateFrm&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정폼JSP&lt;/p&gt;
&lt;pre id=&quot;code_1679038836099&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
    &amp;lt;%@taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;script src=&quot;https://code.jquery.com/jquery-3.6.0.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;게시글 수정&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;form action=&quot;/boardUpdate.do&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot; id=&quot;updateFrm&quot;&amp;gt;
		&amp;lt;table border=&quot;1&quot;&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th&amp;gt;글번호&amp;lt;/th&amp;gt;
				&amp;lt;td&amp;gt;
					&amp;lt;input type=&quot;hidden&quot; name=&quot;boardNo&quot; value=&quot;${b.boardNo }&quot;&amp;gt;
					${b.boardNo }
				&amp;lt;/td&amp;gt; 
			&amp;lt;/tr&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th&amp;gt;제목&amp;lt;/th&amp;gt;
				&amp;lt;td&amp;gt;
					&amp;lt;input type=&quot;text&quot; name=&quot;boardTitle&quot; value=&quot;${b.boardTitle }&quot;&amp;gt;
				&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th&amp;gt;작성자&amp;lt;/th&amp;gt;
				&amp;lt;td&amp;gt;${b.boardWriter }&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th&amp;gt;작성일&amp;lt;/th&amp;gt;
				&amp;lt;td&amp;gt;${b.boardDate }&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th&amp;gt;첨부파일&amp;lt;/th&amp;gt;
				&amp;lt;td&amp;gt;
					&amp;lt;c:forEach items=&quot;${b.fileList }&quot; var=&quot;f&quot;&amp;gt;
						&amp;lt;p&amp;gt;
							${f.filename }
							&amp;lt;button type=&quot;button&quot; onclick=&quot;deleteFile(this, ${f.fileNo}, '${f.filepath }');&quot;&amp;gt;삭제&amp;lt;/button&amp;gt;
						&amp;lt;/p&amp;gt;
					&amp;lt;/c:forEach&amp;gt;
				&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th&amp;gt;첨부파일 추가&amp;lt;/th&amp;gt;
				&amp;lt;td&amp;gt;
					&amp;lt;input type=&quot;file&quot; name=&quot;boardFile&quot; multiple&amp;gt;
				&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th&amp;gt;내용&amp;lt;/th&amp;gt;
				&amp;lt;td&amp;gt;
					&amp;lt;textarea name=&quot;boardContent&quot;&amp;gt;${b.boardContent }&amp;lt;/textarea&amp;gt;
				&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;th colspan=&quot;2&quot;&amp;gt;&amp;lt;input type=&quot;submit&quot; value=&quot;수정하기&quot;&amp;gt;&amp;lt;/th&amp;gt;
			&amp;lt;/tr&amp;gt;
		&amp;lt;/table&amp;gt;	
	&amp;lt;/form&amp;gt;
	&amp;lt;script&amp;gt;
		function deleteFile(obj, fileNo, filepath){
			//화면에서 파일을 안보여주게 하기위해 obj(this)를 가져옴 -&amp;gt; p태그를 지워줄것
			//file인풋을 만들어서 form에 넣어줄것 -&amp;gt; DB삭제를 위한 fileNo / 파일삭제를 위한 filepath
			//&amp;lt;input&amp;gt;
			const fileNoInput = $(&quot;&amp;lt;input&amp;gt;&quot;);
			//&amp;lt;input name=&quot;fileNo&quot;&amp;gt;
			fileNoInput.attr(&quot;name&quot;, &quot;fileNo&quot;);
			//&amp;lt;input name=&quot;fileNo&quot; value=&quot;글번호숫자&quot;&amp;gt;
			fileNoInput.val(fileNo);
			//&amp;lt;input name=&quot;fileNo&quot; value=&quot;글번호숫자&quot; style=&quot;display:none;&quot;&amp;gt;
			fileNoInput.hide();
			
			const filepathInput = $(&quot;&amp;lt;input&amp;gt;&quot;);
			filepathInput.attr(&quot;name&quot;, &quot;filepath&quot;);
			filepathInput.val(filepath);
			filepathInput.hide();
			
			$(&quot;#updateFrm&quot;).append(fileNoInput).append(filepathInput);
			$(obj).parent().remove();
		}
	&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정 Controller&lt;/p&gt;
&lt;pre id=&quot;code_1679038876562&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/boardUpdate.do&quot;)
	public String boardUpdate(Board b, int[] fileNo, String[] filepath, MultipartFile[] boardFile, HttpServletRequest request) {
		//fileVO file로 받으면 문제점 발생 -&amp;gt; 하나만 지우면 fileVO로 받으면 되지만 여러개이기 때문에 각각 배열을 받아야함 
		//b -&amp;gt; boardNo, boardTitle, boardContent
		//fileNo : 삭제할 파일번호(DB) / filepath : 삭제할 파일이름(물리적으로 파일폴더에서삭제) 
		//boardFile : 새로올릴 파일 / request : 새파일 경로잡기위함
		//file -&amp;gt; fileNo, filepath 
		//첨부파일이 추가로 들어왔으면 INSERT
		ArrayList&amp;lt;FileVO&amp;gt; fileList = new ArrayList&amp;lt;FileVO&amp;gt;();
		String savePath = request.getSession().getServletContext().getRealPath(&quot;/resources/upload/board/&quot;);
		if(!boardFile[0].isEmpty()) {
			for(MultipartFile file : boardFile ) {
				String filename = file.getOriginalFilename();
				String upFilepath = fileManager.upload(savePath, file);
				FileVO fileVO = new FileVO();
				fileVO.setFilename(filename);
				fileVO.setFilepath(upFilepath);
				fileList.add(fileVO);
				//파일업로드 작업 완료
			}
		}
		int result = service.boardUpdate(b, fileList, fileNo);
		//업데이트 성공 조건 : result == 삭제한 파일수 + 추가한파일수 + 1
		if(fileNo != null &amp;amp;&amp;amp; (result == (fileList.size() + fileNo.length + 1))) {
			//삭제한 파일이 있는 상태에서 모든 로직을 성공 했을 때
			//실제파일 지우기
			for(String delFile : filepath) {
				boolean delResult = fileManager.deleteFile(savePath, delFile);
				if(delResult) {
					System.out.println(&quot;삭제성공&quot;);
				}else {
					System.out.println(&quot;삭제실패&quot;);
				}
			}
			return &quot;redirect:/boardView.do?boardNo=&quot;+b.getBoardNo();
		}else if(fileNo == null &amp;amp;&amp;amp; (result == fileList.size()+1)) {
			//삭제한 파일이 없는 상태에서 모든 로직을 성공 했을 때
			return &quot;redirect:/boardView.do?boardNo=&quot;+b.getBoardNo();
		}else {
			//실패
			return &quot;redirect:/boardList.do&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1679038911186&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int boardUpdate(Board b, ArrayList&amp;lt;FileVO&amp;gt; fileList, int[] fileNo) {
		//1. board테이블 수정
		int result = dao.updateBoard(b);
		if(result &amp;gt; 0) {
			//2. 기존 첨부파일 삭제
			//기존첨부파일을 삭제하지 않을 경우 -&amp;gt; 추가한 input이 없음 -&amp;gt; int[] fileNo 가 null
			if(fileNo != null) {
				//삭제할 첨부파일이 있는경우
				for(int no : fileNo) {
					result += dao.deleteFile(no);
				}
			}
			//3. 새로운 첨부파일이 있으면 추가
			for(FileVO f : fileList) {
				f.setBoardNo(b.getBoardNo());
				result += dao.insertFile(f);
			}
		}
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao 1 : 게시글 업데이트&lt;/p&gt;
&lt;pre id=&quot;code_1679038947099&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int updateBoard(Board b) {
		String query = &quot;update board set board_title=?, board_content=? where board_no =?&quot;;
		Object[] params = {b.getBoardTitle(), b.getBoardContent(), b.getBoardNo()};
		int result = jdbc.update(query, params);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao 2 : 삭제할 파일이 있으면 파일 삭제&lt;/p&gt;
&lt;pre id=&quot;code_1679038964042&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int deleteFile(int no) {
		String query = &quot;delete from file_tbl where file_no = ?&quot;;
		Object[] params = {no};
		int result = jdbc.update(query, params);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao 3 : 새로추가된 파일이 있으면 INSERT(기존 파일INSERT 이용)&lt;/p&gt;
&lt;pre id=&quot;code_1679039005659&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int insertFile(FileVO file) {
		String query = &quot;insert into file_tbl values(file_seq.nextval, ?, ?, ?)&quot;;
		Object[] params = {file.getBoardNo(), file.getFilename(), file.getFilepath()};
		int result = jdbc.update(query, params);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>국비수업/Spring</category>
      <author>_HYE_</author>
      <guid isPermaLink="true">https://recordev.tistory.com/71</guid>
      <comments>https://recordev.tistory.com/71#entry71comment</comments>
      <pubDate>Fri, 17 Mar 2023 17:03:54 +0900</pubDate>
    </item>
    <item>
      <title>76일차 : 정규화, SpringMVC - 게시판</title>
      <link>https://recordev.tistory.com/70</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;20230316&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 테이블생성을 위한 정규화이론&lt;/p&gt;
&lt;pre id=&quot;code_1678952906969&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
    1. 학생테이블이 존재
    2. 학생은 수업을 듣는다. -&amp;gt; 수업갯수는 학생마다 다름(어떻게 표현?)
       방법1)가장 원시적인 방법은 과목컬럼(SUBJECT1)을 과목마다 추가하는 것 
       -&amp;gt; 문제점 : 수업갯수가 학생마다 다르므로 몇개를 해야할지 모름
       방법2)과목을 모두 입력할 컬럼을 하나 추가
       -&amp;gt; 문제점 : 특정과목에 대한 조회/입력/수정/삭제 부분이 어려워짐
       방법3) 과목을 저장할 컬럼을 1개추가하고 ROW를 늘려준다
       REG_CLASS 컬럼에 독립적인 데이터 1개만 저장하는 경우 과목에 대한 추가,수정,삭제,조회가 수월해짐
       --&amp;gt; 제 1정규화 : 컬럼에 데이터를 독립적으로 1개씩 저장하는 형태
       -&amp;gt; 문제점 : 쓸데없이 중복된 데이터가 너무많다 / 수정 시 수정해야 하는 ROW가 너무많음
                  제1정규화가 끝나면 과목에 대한 처리는 쉬워지는 대신 중복데이터가 너무 많다
                  학생관련된 데이터의 수정/삭제 로직이 불편하다.
       -&amp;gt; 해결법 : 과목은 학생의 주정보가 아닌 서브정보 -&amp;gt; (방법4)과목관련 테이블을 만들어준다.
       방법4) 과목관련 테이블 생성 
       --&amp;gt; 제 2정규화 : 제 1정규화가 완련된 상태에서 메인주제와 관련이 없는 컬럼(REG_CLASS)을 테이블로 분리하는 것
       --&amp;gt; 관계형 데이터베이스는 제2정규화를 하지만, 비관계형 데이터베이스는 중복에대한 단점을 안고 제2정규화를 하지 않는 경우도 있음.
       -&amp;gt; 문제점 : 테이블의 특정컬럼을 업데이트 할 때 수정할 컬럼이 너무 많음(CLASS_NAME - CLASS_PRICE가 종속관계)
       -&amp;gt; 해결법 : CLASS_PRICE 를 새로운 테이블로 생성
       방법5) 과목테이블 / 금액테이블 추가
       --&amp;gt; 제 3정규화 : 제 2정규화가 완료된 상태에서 종속적인 컬럼을 테이블로 분리하는 것
*/
-- 방법1 : 과목수만큼 컬럼추가
CREATE TABLE STUDENT(
    STUDENT_ID      VARCHAR2(20),
    STUDENT_PW      VARCHAR2(20),
    STUDENT_NAME    VARCHAR2(20),
    STUDENT_PHONE   CHAR(13)
    
);

-- 방법2 : 과목전체를 작성할 컬럼 추가
CREATE TABLE STUDENT(
    STUDENT_ID      VARCHAR2(20),
    STUDENT_PW      VARCHAR2(20),
    STUDENT_NAME    VARCHAR2(20),
    STUDENT_PHONE   CHAR(13),
    REG_CLASS       VARCHAR2(1000) -- 자바, 오라클, HTML 을 전부 작성할 컬럼
);
INSERT INTO STUDENT VALUES('stu1', '1234', '학생1', '010-1234-4321', '자바, 오라클');
INSERT INTO STUDENT VALUES('stu2', '2345', '학생2', '010-4321-4321', '자바, 오라클, HTML');
SELECT * FROM STUDENT;
SELECT * FROM STUDENT WHERE REG_CLASS LIKE '%HTML%';
DROP TABLE STUDENT;

-- 방법3 : ROW수를 늘림(제 1정규화)
CREATE TABLE STUDENT(
    STUDENT_ID      VARCHAR2(20),
    STUDENT_PW      VARCHAR2(20),
    STUDENT_NAME    VARCHAR2(20),
    STUDENT_PHONE   CHAR(13),
    REG_CLASS       VARCHAR2(30)    -- 한 과목만 저장
);
-- 한과목만 저장하고 ROW를 늘림
INSERT INTO STUDENT VALUES('stu1', '1234', '학생1', '010-1234-4321', '자바');
INSERT INTO STUDENT VALUES('stu1', '1234', '학생1', '010-1234-4321', '오라클');
INSERT INTO STUDENT VALUES('stu2', '2345', '학생2', '010-4321-4321', '자바');
INSERT INTO STUDENT VALUES('stu2', '2345', '학생2', '010-4321-4321', '오라클');
INSERT INTO STUDENT VALUES('stu2', '2345', '학생2', '010-4321-4321', 'HTML');
SELECT * FROM STUDENT;

-- 방법4 : 과목테이블추가(제 2정규화)
CREATE TABLE STUDENT(
    STUDENT_ID      VARCHAR2(20),
    STUDENT_PW      VARCHAR2(20),
    STUDENT_NAME    VARCHAR2(20),
    STUDENT_PHONE   CHAR(13)
);
CREATE TABLE REG_CLASS(
    STUDENT_ID      VARCHAR2(20),
    CLASS_NAME      VARCHAR2(20),
    CLASS_PRICE     NUMBER
);
INSERT INTO STUDENT VALUES('stu1', '1234', '학생1', '010-1234-4321');
INSERT INTO STUDENT VALUES('stu2', '2345', '학생2', '010-4321-4321');

INSERT INTO REG_CLASS VALUES('stu1', '자바', 1000000);
INSERT INTO REG_CLASS VALUES('stu1', '오라클', 500000);
INSERT INTO REG_CLASS VALUES('stu2', '자바', 1000000);
INSERT INTO REG_CLASS VALUES('stu2', '오라클', 500000);
INSERT INTO REG_CLASS VALUES('stu2', 'HTML', 800000);

SELECT * FROM STUDENT;
SELECT * FROM REG_CLASS;
DROP TABLE REG_CLASS;

-- 방법5 : 과목테이블 / 금액(과목에 종속)테이블(제3정규화)
CREATE TABLE STUDENT(
    STUDENT_ID      VARCHAR2(20),
    STUDENT_PW      VARCHAR2(20),
    STUDENT_NAME    VARCHAR2(20),
    STUDENT_PHONE   CHAR(13)
);
CREATE TABLE REG_CLASS(
    STUDENT_ID      VARCHAR2(20),
    CLASS_NAME      VARCHAR2(20)
);
CREATE TABLE A_CLASS(
    CLASS_NAME      VARCHAR2(30),
    CLASS_PRICE     NUMBER
);
INSERT INTO A_CLASS VALUES('자바', 1000000);
INSERT INTO A_CLASS VALUES('오라클', 500000);
INSERT INTO A_CLASS VALUES('HTML', 800000);
SELECT * FROM A_CLASS;
INSERT INTO REG_CLASS VALUES('st1', '자바');
INSERT INTO REG_CLASS VALUES('st1', '오라클');
INSERT INTO REG_CLASS VALUES('st2', '자바');
INSERT INTO REG_CLASS VALUES('st2', '오라클');
INSERT INTO REG_CLASS VALUES('st2', 'HTML');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 게시판&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 파일 업로드가 되는 게시판&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 사전작업&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BOARD 테이블과 시퀀스&lt;/p&gt;
&lt;pre id=&quot;code_1678952310714&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE BOARD(
    BOARD_NO        NUMBER          PRIMARY KEY,
    BOARD_TITLE     VARCHAR2(100)   NOT NULL,
    BOARD_WRITER    VARCHAR2(20)    REFERENCES MEMBER_TBL(MEMBER_ID) ON DELETE CASCADE,
    BOARD_CONTENT   VARCHAR2(1000)  NOT NULL,
    BOARD_DATE      CHAR(10)
);
CREATE SEQUENCE BOARD_SEQ;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FILE_TBL 테이블과 시퀀스&lt;/p&gt;
&lt;pre id=&quot;code_1678952335782&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE FILE_TBL(
    FILE_NO     NUMBER          PRIMARY KEY,
    BOARD_NO    NUMBER          REFERENCES BOARD ON DELETE CASCADE, -- BOARD테이블의 PK참조
    FILENAME    VARCHAR2(100)   NOT NULL,
    FILEPATH    VARCHAR2(100)   NOT NULL
);
CREATE SEQUENCE FILE_SEQ;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패키지/클래스 생성&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;200&quot; data-origin-height=&quot;162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cngBn9/btr4hmrbokz/WUQMVpHTHMPqMorqSmUyXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cngBn9/btr4hmrbokz/WUQMVpHTHMPqMorqSmUyXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cngBn9/btr4hmrbokz/WUQMVpHTHMPqMorqSmUyXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcngBn9%2Fbtr4hmrbokz%2FWUQMVpHTHMPqMorqSmUyXk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;200&quot; height=&quot;162&quot; data-origin-width=&quot;200&quot; data-origin-height=&quot;162&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패키지를 새로 생성했으므로 sevlet-context에 component-scan 추가(추가해야 @AutoWired 사용가능)&lt;/p&gt;
&lt;pre id=&quot;code_1678952460839&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;context:component-scan base-package=&quot;kr.or.board&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 업로드를 위해 파일업로드용 객체 생성&lt;/p&gt;
&lt;pre id=&quot;code_1678952492158&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;!-- 파일업로드용 객체 --&amp;gt;
	&amp;lt;beans:bean id=&quot;multipartResolver&quot; class=&quot;org.springframework.web.multipart.commons.CommonsMultipartResolver&quot;&amp;gt;
		&amp;lt;beans:property name=&quot;maxUploadSize&quot; value=&quot;10485760&quot; /&amp;gt;
	&amp;lt;/beans:bean&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일업로드를 위해 라이브러리 추가 - commons-io / commons-fileupload&lt;/p&gt;
&lt;pre id=&quot;code_1678952535318&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;		&amp;lt;!-- 파일 업로드를 위해 필요한 라이브러리 추가 2개(commons-io, commons-fileupload --&amp;gt;
		&amp;lt;!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --&amp;gt;
		&amp;lt;dependency&amp;gt;
		    &amp;lt;groupId&amp;gt;commons-fileupload&amp;lt;/groupId&amp;gt;
		    &amp;lt;artifactId&amp;gt;commons-fileupload&amp;lt;/artifactId&amp;gt;
		    &amp;lt;version&amp;gt;1.5&amp;lt;/version&amp;gt;
		&amp;lt;/dependency&amp;gt;		
		&amp;lt;!-- https://mvnrepository.com/artifact/commons-io/commons-io --&amp;gt;
		&amp;lt;dependency&amp;gt;
		    &amp;lt;groupId&amp;gt;commons-io&amp;lt;/groupId&amp;gt;
		    &amp;lt;artifactId&amp;gt;commons-io&amp;lt;/artifactId&amp;gt;
		    &amp;lt;version&amp;gt;2.11.0&amp;lt;/version&amp;gt;
		&amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 글작성하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;boardWriteFrm.jsp&lt;/p&gt;
&lt;pre id=&quot;code_1678952638334&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;게시글 작성&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;%-- 첨부파일일 때, method=&quot;post&quot; / enctype=&quot;multipart/form-data&quot; 반드시 입력 --%&amp;gt;
	&amp;lt;form action=&quot;/boardWrite.do&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&amp;gt;
		&amp;lt;fieldset&amp;gt;
			제목 : &amp;lt;input type=&quot;text&quot; name=&quot;boardTitle&quot;&amp;gt;&amp;lt;br&amp;gt;
			첨부파일 : &amp;lt;input type=&quot;file&quot; name=&quot;boardFile&quot; multiple&amp;gt;&amp;lt;br&amp;gt;
			&amp;lt;%--
				보통 name은 vo의 변수명과 동일하게 만들어주지만, 첨부파일은 반드시 vo와 다르게 넣어야한다 
				file타입이라 문자열로 들어가지 않기때문에 겹쳐서 에러발생 
				multiple : 파일을 여러개 받기 위해추가 / shift로 선택가능 / 하나선택하고 또 하나선택은X
				기존에는 cos.jar 라이브러리를 사용했지만 이번엔 다른 라이브러리를 추가할것
				-&amp;gt; 라이브러리추가는 항상 pom.xml에 추가
			--%&amp;gt;
			내용 : &amp;lt;textarea name=&quot;boardContent&quot;&amp;gt;&amp;lt;/textarea&amp;gt;
			&amp;lt;input type=&quot;submit&quot; value=&quot;작성하기&quot;&amp;gt;
			&amp;lt;input type=&quot;hidden&quot; name=&quot;boardWriter&quot; value=&quot;${sessionScope.m.memberId }&quot;&amp;gt;
		&amp;lt;/fieldset&amp;gt;
	&amp;lt;/form&amp;gt;
	&amp;lt;a href=&quot;/&quot;&amp;gt;메인으로&amp;lt;/a&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1678952661261&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/boardWrite.do&quot;)
	//파일업로드를 진행하기위해 request를 불러옴
	public String boardWrite(Board b, MultipartFile[] boardFile, HttpServletRequest request) {
		//파일목록을 저장할 list생성
		ArrayList&amp;lt;FileVO&amp;gt; fileList = new ArrayList&amp;lt;FileVO&amp;gt;();
		//제목,내용,작성자는 매개변수 b에 모두 들어있음
		//파일이름은 b에 들어있지X 매개변수로 받음 -&amp;gt; 여러개를 받을거기때문에 자료형은 배열형태로
		//첨부파일은 input type=&quot;file&quot;의 name으로 매개변수를 생성 -&amp;gt; 첨부파일 갯수만큼 배열길이 생성
		//첨부파일을 첨부하지 않아도 배열은 길이가 1
		//System.out.println(b);
		//System.out.println(boardFile.length);
		//첨부파일 존재유무를 구분하는 법 - 배열의 첫번째가 비어있는지 아닌지 확인
		//if(!boardFile[0].isEmpty()) {} if문은 이렇게 작성해주는게 좋다.
		if(boardFile[0].isEmpty()) {
			//첨부파일이 없는경우 진행할 로직이 없음
		}else {
			//첨부파일이 있는경우 파일업로드작업 수행
			//1. 파일업로드 경로 설정
			//getRealPath까지가 webapp
			String savePath = request.getSession().getServletContext().getRealPath(&quot;/resources/upload/board/&quot;);
			//2. 배열이므로 반복문을 이용해서 파일업로드 처리
			for(MultipartFile file : boardFile) {
				//파일명이 기존업로드한 파일명과 중복되면 기존파일을 삭제하고 새파일로 덮어쓰기됨 -&amp;gt; 파일명이 중복되지않게 처리해야 함
				//(cos라이브러리에서는 new DefaultFileRenamePolicy가 파일이름이 중복일 경우 새로운이름을 붙여줬음 name1 name2)
				String filename = file.getOriginalFilename(); //사용자가 업로드한 이름
				//이걸 그대로 업로드하면 파일명이 중복되엇을 때 문제가 발생
				//가정 : filename =&amp;gt; test.txt인데 중복인 경우 =&amp;gt; test_1.txt 확장자기준 앞을 바꿈
				//우선 text    .txt를 분리함
				String onlyFilename = filename.substring(0, filename.lastIndexOf(&quot;.&quot;));//test 0부터 뒤에서부터 .의 위치의 숫자를세서 그만큼까지
				String extention = filename.substring(filename.lastIndexOf(&quot;.&quot;)); //.txt 매개변수를 하나만주면 그 매개변수부터 끝까지라는 의미
				//실제 업로드할 파일명
				String filepath = null;
				//파일명 중복 시 뒤에 붙일 숫자
				int count = 0; //횟수가 정해져있지 않음 &amp;gt; while문을 무한으로 돌리고 중복이아닐때 빠져나옴
				while(true) {
					if(count == 0) {
						//첫번째 검증인 경우 숫자를 붙이지X
						filepath = onlyFilename+extention;				//test.txt
					}else {
						filepath = onlyFilename+&quot;_&quot;+count+extention;	//test_1.txt
					}
					File checkFile = new File(savePath+filepath);
					if(!checkFile.exists()) {
						//checkFile이 존재하는지 물어보는 것 -&amp;gt; 중복이 아닐 때 break 
						break;
					}
					count++;
				}
				//파일명 중복체크 끝 -&amp;gt; 업로드할 파일명 확정 -&amp;gt; 파일업로드진행
				//2-2. 중복처리가 끝난 파일 업로드
				try {
					//파일업로드를 위한 주스트림생성
					FileOutputStream fos = new FileOutputStream(savePath+filepath);
					//성능향상을 위한 보조스트림 생성
					BufferedOutputStream bos = new BufferedOutputStream(fos);
					//파일업로드
					byte[] bytes = file.getBytes();
					bos.write(bytes);
					bos.close();
				} catch (FileNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				//파일업로드 끝(1개)
				//DB에 저장하기 위해 FileVO형태의 객체를 생성해서 fileList추가
				FileVO fileVO = new FileVO();
				fileVO.setFilename(filename);
				fileVO.setFilepath(filepath);
				fileList.add(fileVO);
			}//for문 끝
		}
		//비즈니스로직(board와 file_tbl에 insert진행)
		int result = service.insertBoard(b, fileList);
		if(result == (fileList.size()+1)) {
			//insert가 총 첨부파일+1개만큼 일어남 -&amp;gt; board인서트(1번) + 첨부파일인서트(여러번)
			//result를 누계했으므로 
			return &quot;board/boardList&quot;;
		}else {
			return &quot;redirect:/&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1678952679677&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int insertBoard(Board b, ArrayList&amp;lt;FileVO&amp;gt; fileList) {
		//board insert, file_tbl insert - board테이블에 먼저 insert를 해줘야한다
		int result = dao.insertBoard(b);
		if(result &amp;gt; 0) {
			//실패하면 file_tbl insert를 할 필요가 없음 - 트랜잭션관리는 나중에
			//여기서 b.getBoardNo()는 0 - 화면에서 번호를 준게 아니라 insert하면서 시퀀스로 주었기때문에
			//보드번호를 조회해와야한다.
			//file_tbl에 insert를 하기 위해서는 boardNo가 필요 -&amp;gt; 방금 insert한 boardNo를 조회 -&amp;gt; 가장 최근의 board_no
			int boardNo = dao.selectBoardNo(); //최근걸 조회할 것이므로 매개변수 필요없음!
			//insert는 list에 담긴 갯수만큼 해줘야하므로 for문 사용
			for(FileVO file : fileList) {
				file.setBoardNo(boardNo);
				//최종적으로 잘 끝났는지 확인하기위해 결과를 result에 누계
				result += dao.insertFile(file);
			}
		}
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- BOARD 테이블에 INSERT&lt;/p&gt;
&lt;pre id=&quot;code_1678952699104&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int insertBoard(Board b) {
		String query = &quot;insert into board values(board_seq.nextval, ?, ?, ?, to_char(sysdate, 'yyyy-mm-dd'))&quot;;
		Object[] params = {b.getBoardTitle(), b.getBoardWriter(), b.getBoardContent()};
		int result = jdbc.update(query, params);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- BOARD 테이블의 BOARD_NO를 찾기위한 SELECT&lt;/p&gt;
&lt;pre id=&quot;code_1678952774094&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int selectBoardNo() {
		String query =&quot;select max(board_no) from board&quot;; //max : board_no중에 가장큰걸 가져와라는 의미
		//만약에 조회결과가 1행 1열인 경우 rowMapper를 만들기 너무 귀찮음
		//List list = jdbc.query(query, rowMapper);
		//jdbc에서 제공하는 queryForObject 이용
		int boardNo = jdbc.queryForObject(query, int.class); //쿼리, 내가받을 자료형
		return boardNo;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- FILE_TBL 테이블에 INSERT&lt;/p&gt;
&lt;pre id=&quot;code_1678952791271&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int insertFile(FileVO file) {
		String query = &quot;insert into file_tbl values(file_seq.nextval, ?, ?, ?)&quot;;
		Object[] params = {file.getBoardNo(), file.getFilename(), file.getFilepath()};
		int result = jdbc.update(query, params);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>국비수업/Spring</category>
      <author>_HYE_</author>
      <guid isPermaLink="true">https://recordev.tistory.com/70</guid>
      <comments>https://recordev.tistory.com/70#entry70comment</comments>
      <pubDate>Thu, 16 Mar 2023 16:46:36 +0900</pubDate>
    </item>
    <item>
      <title>75일차 : SpringMVC - 회원, 공지사항</title>
      <link>https://recordev.tistory.com/69</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;20230315&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Member : 전체회원조회 / 로그인 / 로그아웃 / 회원가입 / 마이페이지(정보수정) / 회원탈퇴&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;index.jsp&lt;/p&gt;
&lt;pre id=&quot;code_1678883995706&quot; class=&quot;dust&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
    &amp;lt;%@taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;Spring MVC CRUD&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;c:choose&amp;gt;
		&amp;lt;c:when test=&quot;${not empty sessionScope.m }&quot;&amp;gt;
			&amp;lt;h3&amp;gt;[${sessionScope.m.memberName }]님 환영합니다.&amp;lt;/h3&amp;gt;
			&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/logout.do&quot;&amp;gt;로그아웃&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
			&amp;lt;form action=&quot;/searchMember.do&quot; method=&quot;get&quot;&amp;gt;
				조회할 회원 아이디 입력 : 
				&amp;lt;input type=&quot;text&quot; name=&quot;memberId&quot;&amp;gt;
				&amp;lt;input type=&quot;submit&quot; value=&quot;조회&quot;&amp;gt;
			&amp;lt;/form&amp;gt;
		&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/allMember.do&quot;&amp;gt;전체회원조회&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
		&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/mypage.do&quot;&amp;gt;마이페이지&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
		&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/deleteMember.do?memberNo=${sessionScope.m.memberNo }&quot;&amp;gt;회원탈퇴&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
		&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/noticeList.do&quot;&amp;gt;공지사항&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
		&amp;lt;/c:when&amp;gt;
		&amp;lt;c:otherwise&amp;gt;
			&amp;lt;form action=&quot;/login.do&quot; method=&quot;post&quot;&amp;gt;
				&amp;lt;fieldset&amp;gt;
					&amp;lt;legend&amp;gt;로그인&amp;lt;/legend&amp;gt;
					아이디 : &amp;lt;input type=&quot;text&quot; name=&quot;memberId&quot;&amp;gt;&amp;lt;br&amp;gt;
					비밀번호 : &amp;lt;input type=&quot;password&quot; name=&quot;memberPw&quot;&amp;gt;&amp;lt;br&amp;gt;
					&amp;lt;input type=&quot;submit&quot; value=&quot;로그인&quot;&amp;gt;
				&amp;lt;/fieldset&amp;gt;
			&amp;lt;/form&amp;gt;
			&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/joinFrm.do&quot;&amp;gt;회원가입&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
		&amp;lt;/c:otherwise&amp;gt;
	&amp;lt;/c:choose&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VO&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Member&lt;/p&gt;
&lt;pre id=&quot;code_1678883995723&quot; class=&quot;typescript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.member.model.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Member {
	private int memberNo;
	private String memberId;
	private String memberPw;
	private String memberName;
	private String memberPhone;
	private String memberEmail;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MemberRowMapper&lt;/p&gt;
&lt;pre id=&quot;code_1678883995725&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.member.model.vo;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

//select를 하고 while 또는  if 에서 해주던 rset.getString 작업을 해줄 것
public class MemberRowMapper implements RowMapper{

	@Override
	public Object mapRow(ResultSet rset, int rowNum) throws SQLException {
		Member m = new Member();
		m.setMemberNo(rset.getInt(&quot;member_no&quot;));
		m.setMemberId(rset.getString(&quot;member_id&quot;));
		m.setMemberPw(rset.getString(&quot;member_pw&quot;));
		m.setMemberName(rset.getString(&quot;member_name&quot;));
		m.setMemberPhone(rset.getString(&quot;member_phone&quot;));
		m.setMemberEmail(rset.getString(&quot;member_email&quot;));
		return m;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1 - 1 ) 회원가입&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller :&lt;span&gt;&amp;nbsp;&lt;/span&gt;joinFrm으로 이동하기 위한 메소드(joinFrm.do)&lt;/p&gt;
&lt;pre id=&quot;code_1678883995728&quot; class=&quot;kotlin&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/joinFrm.do&quot;)
	public String joinFrm() {
		return &quot;member/joinFrm&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;joinFrm.jsp&lt;/p&gt;
&lt;pre id=&quot;code_1678883995729&quot; class=&quot;xml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;form action=&quot;/join.do&quot; method=&quot;post&quot;&amp;gt;
		&amp;lt;fieldset&amp;gt;
			&amp;lt;legend&amp;gt;회원가입&amp;lt;/legend&amp;gt;
			아이디 : &amp;lt;input type=&quot;text&quot; name=&quot;memberId&quot;&amp;gt;&amp;lt;br&amp;gt;
			비밀번호 : &amp;lt;input type=&quot;password&quot; name=&quot;memberPw&quot;&amp;gt;&amp;lt;br&amp;gt;
			이름 : &amp;lt;input type=&quot;text&quot; name=&quot;memberName&quot;&amp;gt;&amp;lt;br&amp;gt;
			전화번호 : &amp;lt;input type=&quot;text&quot; name=&quot;memberPhone&quot; placeholder=&quot;010-0000-0000&quot;&amp;gt;&amp;lt;br&amp;gt;
			이메일 : &amp;lt;input type=&quot;text&quot; name=&quot;memberEmail&quot;&amp;gt;&amp;lt;br&amp;gt;
			&amp;lt;input type=&quot;submit&quot; value=&quot;회원가입&quot;&amp;gt;
			&amp;lt;input type=&quot;reset&quot; value=&quot;취소&quot;&amp;gt;
		&amp;lt;/fieldset&amp;gt;
	&amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller : insert를 진행하기위한 controller(join.do)&lt;/p&gt;
&lt;pre id=&quot;code_1678883995738&quot; class=&quot;kotlin&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/join.do&quot;)
	public String join(Member m) {
		//String memberId, String memberPw, String memberName, String memberPhone, String memberEmail
		//값추출할 name값과 매개변수명을 반드시 맞춰줘야한다.
		//lombok에서 기능을 지원해줘서 Member m 으로도 받을 수 있음
		//만약 jsp에서 넘겨주지 않은 값이 있으면 기본값을 받는다.(int면 0)
		int result = service.insertMember(m);
		if(result &amp;gt; 0) {
			//메인페이지로 보내주기
			//viewresolver를 거치지 않고 페이지를 이동하고 싶은 경우(다른 컨트롤러를 호출할경우)
			//(viewresolver는 WEB-INF/view/...jsp를 포함하므로)
			return &quot;redirect:/&quot;; //redirect: 를 사용하면 viewresolver를 거치지않음
		}else {
			return &quot;member/joinFrm&quot;;			
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1678883995740&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int insertMember(Member m) {
		int result = dao.insertMember(m);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1678883995741&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int insertMember(Member m) {
		String query = &quot;insert into member_tbl values(member_seq.nextval, ?, ?, ?, ?, ?)&quot;;
		Object[] params = {m.getMemberId(), m.getMemberPw(), m.getMemberName(), m.getMemberPhone(), m.getMemberEmail()};
		int result = jdbc.update(query, params);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1 - 2 ) 로그인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1678883995744&quot; class=&quot;pgsql&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/login.do&quot;)
	public String login(Member member, HttpSession session) {
		//매개변수 두개로 받아도 되고, Member로 받아도된다.(보내준 값만 값이 들어있고 나머지는 기본값(0, null)
		Member loginMember = service.selectOneMember(member);
		if(loginMember != null) {
			session.setAttribute(&quot;m&quot;, loginMember);
		}
		return &quot;redirect:/&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1678883995745&quot; class=&quot;aspectj&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public Member selectOneMember(Member member) {
		/*
		Member loginMember = dao.selectOneMember(member);
		return loginMember;
		*/
		return dao.selectOneMember(member);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1678883995746&quot; class=&quot;arduino&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public Member selectOneMember(Member member) {
		String query = &quot;select * from member_tbl where member_id = ? and member_pw = ?&quot;;
		Object[] params = {member.getMemberId(), member.getMemberPw()};
		List list = jdbc.query(query, params, new MemberRowMapper());
		if(list.isEmpty()) {
			return null;
		}else {
			Member loginMember = (Member)list.get(0);
			return loginMember;
		}		
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1 - 3 ) 로그아웃&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1678883995747&quot; class=&quot;kotlin&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/logout.do&quot;)
	public String logout(HttpSession session) {
		session.invalidate();
		return &quot;redirect:/&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1 - 4 ) 회원탈퇴&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1678883995748&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/deleteMember.do&quot;)
	public String deleteMember(int memberNo) {
		int result = service.deleteMember(memberNo);
		if(result &amp;gt; 0) {
			return &quot;redirect:/logout.do&quot;;
		}else {
			return &quot;redirect:/&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1678883995749&quot; class=&quot;aspectj&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int deleteMember(int memberNo) {
		return dao.deleteMember(memberNo);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1678883995750&quot; class=&quot;cs&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int deleteMember(int memberNo) {
		String query = &quot;delete from member_tbl where member_no = ?&quot;;
		Object[] params = {memberNo};
		int result = jdbc.update(query, params);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1 - 5 ) 전체회원조회&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1678883995751&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/allMember.do&quot;)
	public String allMember(Model model) {
		//매개변수가 없으므로 값추출할게 X 바로 비즈니스로직으로 가면된다.
		ArrayList&amp;lt;Member&amp;gt; list = service.selectAllMember();
		model.addAttribute(&quot;list&quot;, list);
		return &quot;member/allMember&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1678883995752&quot; class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;Member&amp;gt; selectAllMember() {
		ArrayList&amp;lt;Member&amp;gt; list = dao.selectAllMember();
		return list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1678883995752&quot; class=&quot;lasso&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;Member&amp;gt; selectAllMember() {
		String query = &quot;select * from member_tbl&quot;;
		//위치홀더가 없기 때문에 Object[] params = {} 생략
		List list = jdbc.query(query, new MemberRowMapper());
		return (ArrayList&amp;lt;Member&amp;gt;)list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화면구현 JSP&lt;/p&gt;
&lt;pre id=&quot;code_1678883995753&quot; class=&quot;dust&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
    &amp;lt;%@taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot; %&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;전체회원조회&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;table border=&quot;1&quot;&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;th&amp;gt;회원번호&amp;lt;/th&amp;gt;
			&amp;lt;th&amp;gt;아이디&amp;lt;/th&amp;gt;
			&amp;lt;th&amp;gt;비밀번호&amp;lt;/th&amp;gt;
			&amp;lt;th&amp;gt;이름&amp;lt;/th&amp;gt;
			&amp;lt;th&amp;gt;전화번호&amp;lt;/th&amp;gt;
			&amp;lt;th&amp;gt;이메일&amp;lt;/th&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;c:forEach items=&quot;${list}&quot; var=&quot;m&quot;&amp;gt;
			&amp;lt;tr&amp;gt;
				&amp;lt;td&amp;gt;${m.memberNo }&amp;lt;/td&amp;gt;
				&amp;lt;td&amp;gt;${m.memberId }&amp;lt;/td&amp;gt;
				&amp;lt;td&amp;gt;${m.memberPw }&amp;lt;/td&amp;gt;
				&amp;lt;td&amp;gt;${m.memberName }&amp;lt;/td&amp;gt;
				&amp;lt;td&amp;gt;${m.memberPhone }&amp;lt;/td&amp;gt;
				&amp;lt;td&amp;gt;${m.memberEmail }&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
		&amp;lt;/c:forEach&amp;gt;
	&amp;lt;/table&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1 - 6 )&amp;nbsp; 마이페이지+정보수정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- mypage이동 메소드&lt;/p&gt;
&lt;pre id=&quot;code_1678883995762&quot; class=&quot;kotlin&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/mypage.do&quot;)
	public String mypage(){
		return &quot;member/mypage&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- mypage 화면 JSP(정보수정 폼)&lt;/p&gt;
&lt;pre id=&quot;code_1678883995762&quot; class=&quot;dust&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;form action=&quot;/updateMember.do&quot; method=&quot;post&quot;&amp;gt;
		&amp;lt;fieldset&amp;gt;
			&amp;lt;legend&amp;gt;마이페이지&amp;lt;/legend&amp;gt;
			회원 번호 : &amp;lt;input type=&quot;text&quot; name=&quot;memberNo&quot; value=&quot;${sessionScope.m.memberNo }&quot; readonly&amp;gt;&amp;lt;br&amp;gt;
			아이디 : &amp;lt;input type=&quot;text&quot; name=&quot;memberId&quot; value=&quot;${sessionScope.m.memberId }&quot; readonly&amp;gt;&amp;lt;br&amp;gt;
			비밀번호 : &amp;lt;input type=&quot;text&quot; name=&quot;memberPw&quot; value=&quot;${sessionScope.m.memberPw }&quot;&amp;gt;&amp;lt;br&amp;gt;
			이름 : &amp;lt;input type=&quot;text&quot; name=&quot;memberName&quot; value=&quot;${sessionScope.m.memberName }&quot; readonly&amp;gt;&amp;lt;br&amp;gt;
			전화번호 : &amp;lt;input type=&quot;text&quot; name=&quot;memberPhone&quot; value=&quot;${sessionScope.m.memberPhone }&quot;&amp;gt;&amp;lt;br&amp;gt;
			이메일 : &amp;lt;input type=&quot;text&quot; name=&quot;memberEmail&quot; value=&quot;${sessionScope.m.memberEmail }&quot;&amp;gt;&amp;lt;br&amp;gt;
			&amp;lt;input type=&quot;submit&quot; value=&quot;정보수정&quot;&amp;gt;
		&amp;lt;/fieldset&amp;gt;
	&amp;lt;/form&amp;gt;
	&amp;lt;a href=&quot;/&quot;&amp;gt;메인페이지로&amp;lt;/a&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 정보수정 Controller&lt;/p&gt;
&lt;pre id=&quot;code_1678883995772&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/updateMember.do&quot;)
	//Member m : 변경값을 적어준 변수
	//Member member : 세션에 저장되어 있는 값을 불러올 변수 
	//@SessionAttribute(required = false) Member member
	// : 세션에서 이름이 m인 객체를 꺼내서 Member타입으로 저장(자료형 맞아야함, 세션에 저장되어있는 정보가 Member)
	// : required = false 가 없는 경우, 이름이 m인 객체가 없으면 에러발생 
	public String upadateMember(Member member, @SessionAttribute(required = false) Member m) {
		int result = service.updateMember(member);
		if(result &amp;gt; 0) {
			//세션에 m이라는 이름으로 로그인 객체를 넣어둔걸 가져옴 
			//정석방법
			//Member member = (Member)session.getAttribute(&quot;m&quot;);
			m.setMemberPw(member.getMemberPw());
			m.setMemberPhone(member.getMemberPhone());
			m.setMemberEmail(member.getMemberEmail());
			
			return &quot;member/mypage&quot;;
		}else {
			return &quot;redirect:/&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1678883995774&quot; class=&quot;aspectj&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int updateMember(Member member) {
		return dao.updateMember(member);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1678883995775&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int updateMember(Member member) {
		String query = &quot;update member_tbl set member_pw = ?, member_phone = ?, member_email = ? where member_no = ?&quot;;
		Object[] params = {member.getMemberPw(), member.getMemberPhone(), member.getMemberEmail(), member.getMemberNo()};
		int result = jdbc.update(query, params);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Notice : 공지사항리스트 / 공지사항 상세 / 공지사항작성 / 수정(작성자만) / 삭제 (작성자만)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 사전작업 : Controller / Service / Dao / VO&lt;/p&gt;
&lt;pre id=&quot;code_1678883995776&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Controller
//spring한테 객체를 만들라고 지시(context-scan과 함께 이루어져야한다.)
public class NoticeController {
	
	@Autowired //이거없이 선언만 해놓으면 안에는 null이 들어있지만 AutoWired를 사용하면 null(X)
	private NoticeService service;
	
	public NoticeController() {
		super();
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1678883995777&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
public class NoticeService {
	@Autowired
	private NoticeDao dao;

	public NoticeService() {
		super();
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1678883995778&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Repository
public class NoticeDao {
	@Autowired
	private JdbcTemplate jdbc;

	public NoticeDao() {
		super();
		// TODO Auto-generated constructor stub
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1678883995779&quot; class=&quot;typescript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.notice.model.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Notice {
	private int noticeNo;
	private String noticeTitle;
	private String noticeWriter;
	private String noticeContent;
	private String noticeDate;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1678883995781&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.notice.model.vo;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

public class NoticeRowMapper implements RowMapper{
	@Override
	public Object mapRow(ResultSet rset, int rowNum) throws SQLException {
		Notice n = new Notice();
		n.setNoticeContent(rset.getString(&quot;notice_content&quot;));
		n.setNoticeDate(rset.getString(&quot;notice_date&quot;));
		n.setNoticeNo(rset.getInt(&quot;notice_no&quot;));
		n.setNoticeTitle(rset.getString(&quot;notice_title&quot;));
		n.setNoticeWriter(rset.getString(&quot;notice_writer&quot;));
		return n;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2 - 1 ) 공지사항 리스트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1678883995783&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/noticeList.do&quot;)
	public String noticeList(Model model) {
		ArrayList&amp;lt;Notice&amp;gt; list = service.selectAllNotice();
		model.addAttribute(&quot;list&quot;, list);
		return &quot;notice/noticeList&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1678883995784&quot; class=&quot;nginx&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;Notice&amp;gt; selectAllNotice() {
		return dao.selectAllNotice();
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1678883995785&quot; class=&quot;lasso&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public ArrayList&amp;lt;Notice&amp;gt; selectAllNotice() {
		String query = &quot;select * from notice&quot;;
		List list = jdbc.query(query, new NoticeRowMapper());
		return (ArrayList&amp;lt;Notice&amp;gt;)list;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화면구현 JSP&lt;/p&gt;
&lt;pre id=&quot;code_1678883995785&quot; class=&quot;dust&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
    &amp;lt;%@taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;공지사항&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;c:if test=&quot;${not empty sessionScope.m }&quot;&amp;gt;
		&amp;lt;a href=&quot;/noticeFrm.do&quot;&amp;gt;글작성&amp;lt;/a&amp;gt;
	&amp;lt;/c:if&amp;gt;
	&amp;lt;table border=&quot;1&quot;&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;th style=&quot;width:10%&quot;&amp;gt;글번호&amp;lt;/th&amp;gt;
			&amp;lt;th style=&quot;width:50%&quot;&amp;gt;제목&amp;lt;/th&amp;gt;
			&amp;lt;th style=&quot;width:20%&quot;&amp;gt;작성자&amp;lt;/th&amp;gt;
			&amp;lt;th style=&quot;width:20%&quot;&amp;gt;작성일&amp;lt;/th&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;c:forEach items=&quot;${list }&quot; var=&quot;n&quot;&amp;gt;
			&amp;lt;tr onclick = &quot;location.href='/noticeView.do?noticeNo=${n.noticeNo}'&quot;&amp;gt;
				&amp;lt;td&amp;gt;${n.noticeNo }&amp;lt;/td&amp;gt;
				&amp;lt;td&amp;gt;${n.noticeTitle }&amp;lt;/td&amp;gt;
				&amp;lt;td&amp;gt;${n.noticeWriter }&amp;lt;/td&amp;gt;
				&amp;lt;td&amp;gt;${n.noticeDate }&amp;lt;/td&amp;gt;
			&amp;lt;/tr&amp;gt;
		&amp;lt;/c:forEach&amp;gt;
	&amp;lt;/table&amp;gt;
	&amp;lt;a href=&quot;/&quot;&amp;gt;메인으로&amp;lt;/a&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2 - 2 ) 공지사항 상세보기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1678883995795&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/noticeView.do&quot;)
	public String noticeView(int noticeNo, Model model) {
		Notice n = service.selectOneNotice(noticeNo);
		if(n != null) {
			model.addAttribute(&quot;n&quot;, n);
			return &quot;notice/noticeView&quot;;
		}else {
			return &quot;notice/noticeList&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1678883995797&quot; class=&quot;nginx&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public Notice selectOneNotice(int noticeNo) {
		return dao.selectOneNotice(noticeNo);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1678883995798&quot; class=&quot;arduino&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public Notice selectOneNotice(int noticeNo) {
		String query = &quot;select * from notice where notice_no = ?&quot;;
		Object[] params = {noticeNo};
		List list = jdbc.query(query, params, new NoticeRowMapper());
		Notice n = (Notice)list.get(0);
		return n;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화면구현 JSP&lt;/p&gt;
&lt;pre id=&quot;code_1678883995799&quot; class=&quot;dust&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
    &amp;lt;%@taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot; %&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;공지사항 상세&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;table border=&quot;1&quot;&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;th colspan=&quot;2&quot;&amp;gt;제목&amp;lt;/th&amp;gt;
			&amp;lt;td colspan=&quot;2&quot;&amp;gt;${n.noticeTitle }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;th&amp;gt;작성자&amp;lt;/th&amp;gt;
			&amp;lt;td&amp;gt;${n.noticeWriter }&amp;lt;/td&amp;gt;
			&amp;lt;th&amp;gt;작성일&amp;lt;/th&amp;gt;
			&amp;lt;td&amp;gt;${n.noticeDate }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr style=&quot;height:500px; padding: 20px;&quot;&amp;gt;
			&amp;lt;td colspan=&quot;4&quot;&amp;gt;${n.noticeContent }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
	&amp;lt;/table&amp;gt;
	&amp;lt;c:if test=&quot;${not empty sessionScope.m &amp;amp;&amp;amp; sessionScope.m.memberId.equals(n.noticeWriter)}&quot;&amp;gt;
		&amp;lt;a href=&quot;/updateNoticeFrm.do?noticeNo=${n.noticeNo }&quot;&amp;gt;수정&amp;lt;/a&amp;gt;
		&amp;lt;a href=&quot;/deleteNotice.do?noticeNo=${n.noticeNo }&quot;&amp;gt;삭제&amp;lt;/a&amp;gt;
	&amp;lt;/c:if&amp;gt;
	&amp;lt;a href=&quot;/noticeList.do&quot;&amp;gt;목록으로&amp;lt;/a&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2 - 3 ) 공지사항 작성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller - 작성폼으로 이동해주는 메소드&lt;/p&gt;
&lt;pre id=&quot;code_1678883995809&quot; class=&quot;kotlin&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/noticeFrm.do&quot;)
	public String noticeFrm(){
		return &quot;notice/noticeFrm&quot;;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공지사항 작성폼 JSP&lt;/p&gt;
&lt;pre id=&quot;code_1678883995810&quot; class=&quot;dust&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;공지사항 작성&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;form action=&quot;/insertNotice.do&quot; method=&quot;post&quot;&amp;gt;
		&amp;lt;fieldset&amp;gt;
			&amp;lt;legend&amp;gt;공지사항작성&amp;lt;/legend&amp;gt;
			&amp;lt;table border=&quot;1&quot;&amp;gt;
				&amp;lt;tr&amp;gt;	
					&amp;lt;th&amp;gt;제목&amp;lt;/th&amp;gt;
					&amp;lt;td&amp;gt;&amp;lt;input type=&quot;text&quot; name=&quot;noticeTitle&quot;&amp;gt;&amp;lt;/td&amp;gt;
				&amp;lt;/tr&amp;gt;
				&amp;lt;tr&amp;gt;
					&amp;lt;th&amp;gt;작성자&amp;lt;/th&amp;gt;
					&amp;lt;td&amp;gt;&amp;lt;input type=&quot;text&quot; name=&quot;noticeWriter&quot; value=&quot;${sessionScope.m.memberId }&quot; readonly&amp;gt;&amp;lt;/td&amp;gt;
				&amp;lt;/tr&amp;gt;
				&amp;lt;tr&amp;gt;
					&amp;lt;th colspan=&quot;2&quot;&amp;gt;내용&amp;lt;/th&amp;gt;
				&amp;lt;/tr&amp;gt;
				&amp;lt;tr&amp;gt;
					&amp;lt;td colspan=&quot;2&quot;&amp;gt;&amp;lt;textarea name=&quot;noticeContent&quot;&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;
				&amp;lt;/tr&amp;gt;
			&amp;lt;/table&amp;gt;
			&amp;lt;input type=&quot;submit&quot; value=&quot;작성하기&quot;&amp;gt;
			&amp;lt;input type=&quot;reset&quot; value=&quot;취소&quot;&amp;gt;
		&amp;lt;/fieldset&amp;gt;
	&amp;lt;/form&amp;gt;
	
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller - 공지사항 Insert&lt;/p&gt;
&lt;pre id=&quot;code_1678883995812&quot; class=&quot;kotlin&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/insertNotice.do&quot;)
	public String insertNotice(Notice n) {
		int result = service.insertNotice(n);
		if(result &amp;gt; 0) {
			//list를 가려면 controller를 통해가야 값을 넣기때문에 redirect:/noticeList.do로 먼저가야한다
			return &quot;redirect:/noticeList.do&quot;;
		}else {
			return &quot;notice/noticeFrm&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1678883995813&quot; class=&quot;aspectj&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int insertNotice(Notice n) {
		return dao.insertNotice(n);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1678883995814&quot; class=&quot;cs&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int insertNotice(Notice n) {
		String query = &quot;insert into notice values(notice_seq.nextval, ?, ?, ?, to_char(sysdate, 'yyyy-mm-dd'))&quot;;
		Object[] params = {n.getNoticeTitle(), n.getNoticeWriter(), n.getNoticeContent()};
		int result = jdbc.update(query, params);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2 - 4 ) 공지사항 수정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller - 수정입력폼으로 이동해줄 메소드&lt;/p&gt;
&lt;pre id=&quot;code_1678883995815&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/updateNoticeFrm.do&quot;)
	public String updateNoticeFrm(int noticeNo, Model model) {
		Notice n = service.selectOneNotice(noticeNo);
		if(n != null) {
			model.addAttribute(&quot;n&quot;, n);
			return &quot;notice/updateNoticeFrm&quot;;			
		}else {
			return &quot;redirect:/&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정입력폼 JSP&lt;/p&gt;
&lt;pre id=&quot;code_1678883995817&quot; class=&quot;dust&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;공지사항 수정&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;form action=&quot;/updateNotice.do&quot; method=&quot;post&quot;&amp;gt;
		&amp;lt;fieldset&amp;gt;
			&amp;lt;legend&amp;gt;공지사항수정&amp;lt;/legend&amp;gt;
			&amp;lt;table border=&quot;1&quot;&amp;gt;
				&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&quot;hidden&quot; name=&quot;noticeNo&quot; value=&quot;${n.noticeNo }&quot;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
				&amp;lt;tr&amp;gt;	
					&amp;lt;th&amp;gt;제목&amp;lt;/th&amp;gt;
					&amp;lt;td&amp;gt;&amp;lt;input type=&quot;text&quot; name=&quot;noticeTitle&quot; value=&quot;${n.noticeTitle }&quot;&amp;gt;&amp;lt;/td&amp;gt;
				&amp;lt;/tr&amp;gt;
				&amp;lt;tr&amp;gt;
					&amp;lt;th&amp;gt;작성자&amp;lt;/th&amp;gt;
					&amp;lt;td&amp;gt;&amp;lt;input type=&quot;text&quot; name=&quot;noticeWriter&quot; value=&quot;${n.noticeWriter}&quot; readonly&amp;gt;&amp;lt;/td&amp;gt;
				&amp;lt;/tr&amp;gt;
				&amp;lt;tr&amp;gt;
					&amp;lt;th colspan=&quot;2&quot;&amp;gt;내용&amp;lt;/th&amp;gt;
				&amp;lt;/tr&amp;gt;
				&amp;lt;tr&amp;gt;
					&amp;lt;td colspan=&quot;2&quot;&amp;gt;&amp;lt;textarea name=&quot;noticeContent&quot;&amp;gt;${n.noticeContent }&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;
				&amp;lt;/tr&amp;gt;
			&amp;lt;/table&amp;gt;
			&amp;lt;input type=&quot;submit&quot; value=&quot;작성하기&quot;&amp;gt;
			&amp;lt;input type=&quot;reset&quot; value=&quot;취소&quot;&amp;gt;
		&amp;lt;/fieldset&amp;gt;
	&amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller - update를 진행할 메소드&lt;/p&gt;
&lt;pre id=&quot;code_1678883995829&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/updateNotice.do&quot;)
	public String updateNotice(Notice n) {
		int result = service.updateNotice(n);
		if(result &amp;gt; 0) {
			return &quot;redirect:/noticeView.do?noticeNo=&quot;+n.getNoticeNo();
		}else {
			return &quot;redirect:/updateNoticeFrm.do&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1678883995831&quot; class=&quot;aspectj&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int updateNotice(Notice n) {
		return dao.updateNotice(n);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1678883995831&quot; class=&quot;cs&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int updateNotice(Notice n) {
		String query = &quot;update notice set notice_title = ?, notice_content = ? where notice_no = ?&quot;;
		Object[] params = {n.getNoticeTitle(), n.getNoticeContent(), n.getNoticeNo()};
		int result = jdbc.update(query, params);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2 - 5 ) 공지사항 삭제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1678883995832&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/deleteNotice.do&quot;)
	public String deleteNotice(int noticeNo) {
		int result = service.deleteNotice(noticeNo);
		if(result &amp;gt; 0) {
			return &quot;redirect:/noticeList.do&quot;;
		}else {
			return &quot;redirect:/noticeView.do?noticeNo=&quot;+noticeNo;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1678883995834&quot; class=&quot;aspectj&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int deleteNotice(int noticeNo) {
		return dao.deleteNotice(noticeNo);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1678883995834&quot; class=&quot;cs&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public int deleteNotice(int noticeNo) {
		String query = &quot;delete from notice where notice_no = ?&quot;;
		Object[] params = {noticeNo};
		int result = jdbc.update(query, params);
		return result;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>국비수업/Spring</category>
      <author>_HYE_</author>
      <guid isPermaLink="true">https://recordev.tistory.com/69</guid>
      <comments>https://recordev.tistory.com/69#entry69comment</comments>
      <pubDate>Wed, 15 Mar 2023 21:40:02 +0900</pubDate>
    </item>
    <item>
      <title>74일차 : loC, DI, springMVC</title>
      <link>https://recordev.tistory.com/68</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1. loC / DI&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;loC&amp;nbsp;:&amp;nbsp;Inversion&amp;nbsp;of&amp;nbsp;Control&amp;nbsp;제어의&amp;nbsp;역행 &lt;br /&gt;프로그램을&amp;nbsp;구동하는데&amp;nbsp;필요한&amp;nbsp;객체&amp;nbsp;생성에&amp;nbsp;대한&amp;nbsp;생성/변경등을&amp;nbsp;프로그램을&amp;nbsp;구동하는&amp;nbsp;컨테이너에서&amp;nbsp;직접관리 &lt;br /&gt;역할&amp;nbsp;-&amp;nbsp;객체의&amp;nbsp;생명주기와&amp;nbsp;의존성&amp;nbsp;관리 &lt;br /&gt;&lt;br /&gt;DI&amp;nbsp;:&amp;nbsp;의존성&amp;nbsp;주입&amp;nbsp;/&amp;nbsp;컨테이너가&amp;nbsp;빈의&amp;nbsp;설정정보를&amp;nbsp;읽어와&amp;nbsp;자동으로&amp;nbsp;해당&amp;nbsp;객체를&amp;nbsp;연결&amp;nbsp; &lt;br /&gt;장점&amp;nbsp;-&amp;nbsp;개발자가&amp;nbsp;작성해야할&amp;nbsp;코드가&amp;nbsp;단순해짐 &lt;br /&gt;&lt;br /&gt;MemberService&amp;nbsp;service&amp;nbsp;=&amp;nbsp;new&amp;nbsp;MemberService(); &lt;br /&gt;&lt;br /&gt;@Autowired &lt;br /&gt;MemberService&amp;nbsp;service;&amp;nbsp; &lt;br /&gt;스프링에서&amp;nbsp;객체를&amp;nbsp;자동적으로&amp;nbsp;저장해주게&amp;nbsp;만듬(의존성&amp;nbsp;주입) &lt;br /&gt;필요한건&amp;nbsp;한번씩만&amp;nbsp;파일로&amp;nbsp;만들어두고&amp;nbsp;서버시작때마다&amp;nbsp;사용하기때문에&amp;nbsp;개발자가&amp;nbsp;작성할&amp;nbsp;코드가&amp;nbsp;적어짐 &lt;br /&gt;&lt;br /&gt;B&amp;nbsp;class를&amp;nbsp;수정할&amp;nbsp;때&amp;nbsp;A&amp;nbsp;class에&amp;nbsp;연쇄적으로&amp;nbsp;수정해야하는게&amp;nbsp;많은&amp;nbsp;경우를&amp;nbsp;결합도가&amp;nbsp;강하다고&amp;nbsp;표현 &lt;br /&gt;(코드를&amp;nbsp;칠때는&amp;nbsp;결합도가&amp;nbsp;약할수록&amp;nbsp;좋다&amp;nbsp;-&amp;nbsp;수정사항이&amp;nbsp;적어지니까) &lt;br /&gt;결합도를&amp;nbsp;낮출&amp;nbsp;때&amp;nbsp;스프링이&amp;nbsp;좋다. &lt;br /&gt;&lt;br /&gt;WEB-INF&amp;nbsp;아래&amp;nbsp;web.xml&amp;nbsp;파일을&amp;nbsp;보면&amp;nbsp;서블릿의&amp;nbsp;생성유무에&amp;nbsp;따라&amp;nbsp;코드가&amp;nbsp;다르다 &lt;br /&gt;서블릿을&amp;nbsp;생성하면&amp;nbsp;서블릿에&amp;nbsp;대한&amp;nbsp;정보가&amp;nbsp;들어가는&amp;nbsp;것 &lt;br /&gt;&lt;br /&gt;spring&amp;nbsp;mvc&amp;nbsp;:&amp;nbsp;일반&amp;nbsp;mvc보다&amp;nbsp;구조는&amp;nbsp;복잡하지만&amp;nbsp;개발자가&amp;nbsp;작성하는&amp;nbsp;코드는&amp;nbsp;적다(나머지는&amp;nbsp;spring에서&amp;nbsp;제공하는기능을&amp;nbsp;사용) &lt;br /&gt;모든&amp;nbsp;클라이언트의&amp;nbsp;요청을&amp;nbsp;Dispatcher&amp;nbsp;Servlet으로&amp;nbsp;받음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;index.jsp&lt;/p&gt;
&lt;pre id=&quot;code_1678869558906&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;Hello Spring&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;h3&amp;gt;결합도와 응집도&amp;lt;/h3&amp;gt;
	&amp;lt;form action=&quot;/test1.do&quot; method=&quot;get&quot;&amp;gt;
		&amp;lt;input type=&quot;radio&quot; name=&quot;brand&quot; value=&quot;samsung&quot; id=&quot;samsung&quot;&amp;gt;
		&amp;lt;label for=&quot;samsung&quot;&amp;gt;SAMSUNG&amp;lt;/label&amp;gt;
		&amp;lt;input type=&quot;radio&quot; name=&quot;brand&quot; value=&quot;lg&quot; id=&quot;lg&quot;&amp;gt;
		&amp;lt;label for=&quot;lg&quot;&amp;gt;LG&amp;lt;/label&amp;gt;
		&amp;lt;input type=&quot;submit&quot; value=&quot;제출&quot;&amp;gt;
	&amp;lt;/form&amp;gt;
	&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/test2.do&quot;&amp;gt;DI 테스트&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Controller&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;test1Servlet.java&lt;/p&gt;
&lt;pre id=&quot;code_1678869636314&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.or.iei.vo.BeanFactory;
import kr.or.iei.vo.LgTV;
import kr.or.iei.vo.TV;

/**
 * Servlet implementation class Test1Servlet
 * 이클립스에서 서블릿을 사용할 때는 
 * @WebServlet(name = &quot;Abcd&quot;, urlPatterns = { &quot;/abcd.do&quot; })
 * 라고 정의가 되어있지만 Spring에는 정의가 없는대신 web.xml에 서블릿정보가 기재되어있음.  
 * 서블릿을 잘못만들어서 삭제해야하는 경우 web.xml에서 해당 서블릿 관련정보도 지워줘야한다
 */
public class Test1Servlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public Test1Servlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		/*
		SamsungTV tv = new SamsungTV();
		tv.powerOn();
		tv.powerOff();
		tv.volumUp();
		tv.volumDown();
		
		LgTV tv = new LgTV();
		tv.on();
		tv.off();
		tv.soundUp();
		tv.soundDown();
		//거의 동일한 코드를 다시 작성해줘야하기 때문에 번거로움 - 이럴 때 사용하는게 인터페이스
		*/
		//SamsungTV tv = new SamsungTV();
		//현재는 객체를 생성하는 코드만 변경해주면 된다 - 결합도를 낮추는 작업
		//LgTV tv = new LgTV();
		//부모객체를 사용해서 SamsungTV만 변경해주면된다.(다형성이용)
		//LgTV()라는 객체도 사용하고 싶지 않을 때 -&amp;gt; 사용자가 선택한걸 가져오고 싶을 때
		//TV tv = new LgTV();
		
		String brand = request.getParameter(&quot;brand&quot;);
		System.out.println(brand);
		BeanFactory factory = new BeanFactory();
		TV tv = factory.getBean(brand);
		tv.powerOn();
		tv.powerOff();
		tv.volumeUp();
		tv.volumeDown();
		
		response.sendRedirect(&quot;/&quot;);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;test2Servlet.java&lt;/p&gt;
&lt;pre id=&quot;code_1678869655282&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

import kr.or.iei.vo.Member;
import kr.or.iei.vo.MemberMgr;

/**
 * Servlet implementation class Test2Servlet
 */
public class Test2Servlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public Test2Servlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//spring 설정파일을 읽어오는 객체 생성
		AbstractApplicationContext cntx = new GenericXmlApplicationContext(&quot;memberContext.xml&quot;);
		//여러개의 bean중에 필요한 bean의 id를 가져옴 - 항상 Object로 리턴하기 때문에 형변환이 필요
		Member member1 = (Member)cntx.getBean(&quot;member1&quot;);
		
		System.out.println(member1.getName());
		System.out.println(member1.getAge());
		System.out.println(member1.getAddr());
		
		
		MemberMgr mm = (MemberMgr)cntx.getBean(&quot;mm&quot;);
		Member member3 = mm.getMember();
		System.out.println(member3.getName());
		System.out.println(member3.getAge());
		System.out.println(member3.getAddr());
		
		Member member2 = (Member)cntx.getBean(&quot;member2&quot;);
		System.out.println(member2.getName());
		System.out.println(member2.getAge()); //20
		System.out.println(member2.getAddr());
		member2.setAge(1000);
		System.out.println(member2.getAge()); //1000
		Member member22 = (Member)cntx.getBean(&quot;member2&quot;);
		// 위코드 실행마다 새로운 객체가 생성된다 - 20
		// 이미 만들어진 객체를 이용하는것이다 - 1000
		// 옵션을 줄 수 있음(옵션이 없으면 아래가 기본값) scope=&quot;prototype&quot;을 하면 계속 새로운 객체를 만듬
		System.out.println(member22.getAge()); 
		
		
		response.sendRedirect(&quot;/&quot;);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- VO&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TV ( Inteface)&lt;/p&gt;
&lt;pre id=&quot;code_1678869680018&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.vo;

public interface TV {
	public void powerOn();
	public void powerOff();
	public void volumeUp();
	public void volumeDown();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- lombok이 해주는 일&lt;/p&gt;
&lt;pre id=&quot;code_1678869764610&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

//lombok이 해주는 일 - getter/setter/생성자를 작성하지 않아도 다 만들어준다.
@Data // getter/setter
@NoArgsConstructor // 매개변수 없는 생성자
@AllArgsConstructor //모든 매개변수가 있는 생성자
//변수추가삭제의 경우 전부 수정해줘야하는데 lombok을 사용하면 모두 자동으로 생성된다.
//단, 매개변수가 일부만 있는 경우에는 직접 만들어줘야한다.
public class Member {
	private String name;
	private int age;
	private String addr;	
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- test&lt;/p&gt;
&lt;pre id=&quot;code_1678869802227&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.test;

import org.springframework.stereotype.Component;

//Component : 서버가 시작될 때 객체를 만들지말지 결정

@Component 
//component를 붙여도 s(스프링에서 클래스를만들었다는 뜻)가 생기지 않음
//WEB-INF/spring/appServlet/servlet-context.xml 에 해당 패키지 &amp;lt;context:component-scan base-package=&quot;패키지&quot; /&amp;gt; 를 작성해주어야함.
//Component와 Scan이 항상 함께 이루어져야한다.
public class TestClass2 {
	public TestClass2() {
		super();
		System.out.println(&quot;TestClass2 생성완료!&quot;);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. SpringMVC (DB연결 X)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;index.jsp&lt;/p&gt;
&lt;pre id=&quot;code_1678869896402&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;Spring MVC&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;form action=&quot;/login.do&quot; method=&quot;post&quot;&amp;gt;
		아이디 : &amp;lt;input type=&quot;text&quot; name=&quot;memberId&quot;&amp;gt;&amp;lt;br&amp;gt;
		비밀번호 : &amp;lt;input type=&quot;password&quot; name=&quot;memberPw&quot;&amp;gt;&amp;lt;br&amp;gt;
		&amp;lt;input type=&quot;submit&quot; value=&quot;로그인&quot;&amp;gt;
	&amp;lt;/form&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;form action=&quot;/search.do&quot; method=&quot;get&quot;&amp;gt;
		조회 할 아이디 : &amp;lt;input type=&quot;text&quot; name=&quot;memberId&quot;&amp;gt;
		&amp;lt;input type=&quot;submit&quot; value=&quot;조회&quot;&amp;gt;
	&amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- controller&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DispatcherServlet&lt;/p&gt;
&lt;pre id=&quot;code_1678869972507&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class DispatcherServlet
 */
public class DispatcherServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public DispatcherServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//(1) 최초요청받기
		request.setCharacterEncoding(&quot;utf-8&quot;);
		//사용자가 요청한 컨트롤러 주소 확인
		String uri = request.getRequestURI();
		System.out.println(&quot;사용자 요청 URI : &quot;+uri);
		HandlerMapping map = new HandlerMapping();
		//(2)
		Controller controller = map.getController(uri);
		//(3), (5)
		String result = controller.request(request);
		ViewResolver resolver = new ViewResolver();
		//(6)
		String view = resolver.getView(result);
		//(7)
		response.sendRedirect(view);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HandlerMapping&lt;/p&gt;
&lt;pre id=&quot;code_1678869992010&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.controller;

import java.util.HashMap;

public class HandlerMapping {
	private HashMap&amp;lt;String, Controller&amp;gt; mappings;

	public HandlerMapping() {
		super();
		mappings = new HashMap&amp;lt;String, Controller&amp;gt;();
		mappings.put(&quot;/login.do&quot;, new LoginController());
		mappings.put(&quot;/search.do&quot;, new SearchMember());
	}
	
	public Controller getController(String uri) {
		return mappings.get(uri);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LoginController&lt;/p&gt;
&lt;pre id=&quot;code_1678870011954&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.controller;

import javax.servlet.http.HttpServletRequest;

public class LoginController implements Controller{

	@Override
	public String request(HttpServletRequest request) {
		//2.값추출
		String memberId = request.getParameter(&quot;memberId&quot;);
		String memberPw = request.getParameter(&quot;memberPw&quot;);
		//3. 비즈니스로직
		//-&amp;gt; memberId : user01 이고, memberPw : 1234면 로그인 성공 아니면 실패
		if(memberId.equals(&quot;user01&quot;) &amp;amp;&amp;amp; memberPw.equals(&quot;1234&quot;)) {
			return &quot;loginSuccess&quot;;
		}else {
			return &quot;loginFail&quot;;
		}
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SearchMember&lt;/p&gt;
&lt;pre id=&quot;code_1678870034322&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.controller;

import javax.servlet.http.HttpServletRequest;

public class SearchMember implements Controller{

	@Override
	public String request(HttpServletRequest request) {
		//2. 값추출
		String memberId = request.getParameter(&quot;memberId&quot;);
		//3. 비즈니스로직
		//memberId가 user01이면 조회성공 아니면 실패
		if(memberId.equals(&quot;user01&quot;)) {
			return &quot;searchSuccess&quot;;
		}else {
			return &quot;searchFail&quot;;			
		}
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ViewResolver&lt;/p&gt;
&lt;pre id=&quot;code_1678870073314&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.controller;

public class ViewResolver {
	public String getView(String result) {
		return &quot;/view/&quot;+result+&quot;.jsp&quot;;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. SpringMVC 2(DB연결 O)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[ 프로젝트 생성 시 해줘야하는 Setting]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0. Spring Lagacy Project 생성&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EUfRd/btr43QkDRcd/6M36fPWsaGJn2ks9cyNKE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EUfRd/btr43QkDRcd/6M36fPWsaGJn2ks9cyNKE0/img.png&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;982&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4756%; margin-right: 10px;&quot; data-widthpercent=&quot;50.06&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EUfRd/btr43QkDRcd/6M36fPWsaGJn2ks9cyNKE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEUfRd%2Fbtr43QkDRcd%2F6M36fPWsaGJn2ks9cyNKE0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;904&quot; height=&quot;982&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Lazll/btr4TJnbjIn/2Vls5hckJUquBnUPoRZVN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Lazll/btr4TJnbjIn/2Vls5hckJUquBnUPoRZVN0/img.png&quot; data-origin-width=&quot;901&quot; data-origin-height=&quot;981&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.3616%;&quot; data-widthpercent=&quot;49.94&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Lazll/btr4TJnbjIn/2Vls5hckJUquBnUPoRZVN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLazll%2Fbtr4TJnbjIn%2F2Vls5hckJUquBnUPoRZVN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;901&quot; height=&quot;981&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 프로젝트우클릭 - propertice - project Facets - java version 1.8 / Runtimes - apach-tomcat 8.5 선택&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1228&quot; data-origin-height=&quot;848&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eXw874/btr41wmZaQg/9oKcKJ7hh8K7pV6358FfgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eXw874/btr41wmZaQg/9oKcKJ7hh8K7pV6358FfgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eXw874/btr41wmZaQg/9oKcKJ7hh8K7pV6358FfgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeXw874%2Fbtr41wmZaQg%2F9oKcKJ7hh8K7pV6358FfgK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1228&quot; height=&quot;848&quot; data-origin-width=&quot;1228&quot; data-origin-height=&quot;848&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 서버 add and remove 후 더블클릭해서 modules의 path 를 /로변경 -&amp;gt; 서버에 프로젝트 add시마다 해줘야한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;935&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRDXtZ/btr42TWfZeX/e0q0Rs1o7jlfqsgckqTFS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRDXtZ/btr42TWfZeX/e0q0Rs1o7jlfqsgckqTFS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRDXtZ/btr42TWfZeX/e0q0Rs1o7jlfqsgckqTFS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRDXtZ%2Fbtr42TWfZeX%2Fe0q0Rs1o7jlfqsgckqTFS0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1848&quot; height=&quot;935&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;935&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. pom.xml의 overview 설정변경&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1859&quot; data-origin-height=&quot;932&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GrW5a/btr41H9yQY6/Ck5OxqR33wouACksN40ziK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GrW5a/btr41H9yQY6/Ck5OxqR33wouACksN40ziK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GrW5a/btr41H9yQY6/Ck5OxqR33wouACksN40ziK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGrW5a%2Fbtr41H9yQY6%2FCk5OxqR33wouACksN40ziK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1859&quot; height=&quot;932&quot; data-origin-width=&quot;1859&quot; data-origin-height=&quot;932&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. jstl 라이브러리추가(경로 : webapp/WEB-INF/lib)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[ 사전 Setting ]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- pom.xml (mavenrepository에서 검색 후 추가)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;: Spring JDBC 사용을 위한 라이브러리 추가 [ Spring-jdbc / commons-dbcp ]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Spring jdbc /&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;첫번째 클릭 /&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;5.0.6ver&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;commons-dbcp /&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;두번째 클릭 /&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;최신ver&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;: Oracle 연동을 위한 ojdbc 추가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;ojdbc6 검색 / 버전 1개 / 복사&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;: lombok 추가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;nbsp;lombok /&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;첫번째 클릭&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;/ 1.18.12복사&lt;/p&gt;
&lt;pre id=&quot;code_1678785087912&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;		&amp;lt;!-- Spring JDBC 사용을 위한 라이브러리 추가 2개(spring-jdbc, commons-dbcp) --&amp;gt;
		&amp;lt;!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --&amp;gt;
		&amp;lt;dependency&amp;gt;
		    &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
		    &amp;lt;artifactId&amp;gt;spring-jdbc&amp;lt;/artifactId&amp;gt;
		    &amp;lt;version&amp;gt;5.0.6.RELEASE&amp;lt;/version&amp;gt;
		&amp;lt;/dependency&amp;gt;		
		&amp;lt;!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp --&amp;gt;
		&amp;lt;dependency&amp;gt;
		    &amp;lt;groupId&amp;gt;commons-dbcp&amp;lt;/groupId&amp;gt;
		    &amp;lt;artifactId&amp;gt;commons-dbcp&amp;lt;/artifactId&amp;gt;
		    &amp;lt;version&amp;gt;1.4&amp;lt;/version&amp;gt;
		&amp;lt;/dependency&amp;gt;		
		&amp;lt;!-- ORACLE 연동을 위한 ojdbc --&amp;gt;
		&amp;lt;!-- https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc6 --&amp;gt;
		&amp;lt;dependency&amp;gt;
		    &amp;lt;groupId&amp;gt;com.oracle.database.jdbc&amp;lt;/groupId&amp;gt;
		    &amp;lt;artifactId&amp;gt;ojdbc6&amp;lt;/artifactId&amp;gt;
		    &amp;lt;version&amp;gt;11.2.0.4&amp;lt;/version&amp;gt;
		&amp;lt;/dependency&amp;gt;
			
		&amp;lt;!-- lombok --&amp;gt;
		&amp;lt;dependency&amp;gt;
		    &amp;lt;groupId&amp;gt;org.projectlombok&amp;lt;/groupId&amp;gt;
		    &amp;lt;artifactId&amp;gt;lombok&amp;lt;/artifactId&amp;gt;
		    &amp;lt;version&amp;gt;1.18.12&amp;lt;/version&amp;gt;
		    &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;
		&amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- web.xml&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 인코딩 추가&lt;/p&gt;
&lt;pre id=&quot;code_1678785422309&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;!-- 인코딩 필터 설정 --&amp;gt;
	&amp;lt;filter&amp;gt;
		&amp;lt;filter-name&amp;gt;EncodingFilter&amp;lt;/filter-name&amp;gt;	
		&amp;lt;filter-class&amp;gt;org.springframework.web.filter.CharacterEncodingFilter&amp;lt;/filter-class&amp;gt;
		&amp;lt;init-param&amp;gt;
			&amp;lt;param-name&amp;gt;encoding&amp;lt;/param-name&amp;gt;
			&amp;lt;param-value&amp;gt;utf-8&amp;lt;/param-value&amp;gt;
		&amp;lt;/init-param&amp;gt;
	&amp;lt;/filter&amp;gt;
	&amp;lt;filter-mapping&amp;gt;
		&amp;lt;filter-name&amp;gt;EncodingFilter&amp;lt;/filter-name&amp;gt;
		&amp;lt;url-pattern&amp;gt;*.do&amp;lt;/url-pattern&amp;gt;
	&amp;lt;/filter-mapping&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 마지막 url-pattern *.do로 변경&lt;/p&gt;
&lt;pre id=&quot;code_1678785441741&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;servlet-mapping&amp;gt;
		&amp;lt;servlet-name&amp;gt;appServlet&amp;lt;/servlet-name&amp;gt;
		&amp;lt;url-pattern&amp;gt;*.do&amp;lt;/url-pattern&amp;gt;
	&amp;lt;/servlet-mapping&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- WEB-INF/spring/appServlet/servlet-context.xml&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: DB접속정보 + JDBCTemplet 추가&lt;/p&gt;
&lt;pre id=&quot;code_1678785499740&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;!-- DB 접속정보를 저장하는 객체 생성 --&amp;gt;
	&amp;lt;beans:bean id=&quot;dataSource&quot; class=&quot;org.apache.commons.dbcp.BasicDataSource&quot;&amp;gt;
		&amp;lt;beans:property name=&quot;driverClassName&quot; value=&quot;oracle.jdbc.driver.OracleDriver&quot; /&amp;gt;
		&amp;lt;beans:property name=&quot;url&quot; value=&quot;jdbc:oracle:thin:@127.0.0.1:1521:xe&quot; /&amp;gt;
		&amp;lt;beans:property name=&quot;username&quot; value=&quot;spring&quot; /&amp;gt;
		&amp;lt;beans:property name=&quot;password&quot; value=&quot;spring&quot; /&amp;gt;
	&amp;lt;/beans:bean&amp;gt;
	&amp;lt;!-- JDBCTemplet --&amp;gt;
	&amp;lt;beans:bean id=&quot;jdbcTemplet&quot; class=&quot;org.springframework.jdbc.core.JdbcTemplate&quot;&amp;gt;
		&amp;lt;beans:property name=&quot;dataSource&quot; ref=&quot;dataSource&quot;&amp;gt;&amp;lt;/beans:property&amp;gt;
	&amp;lt;/beans:bean&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 하단에 패키지 추가(패키지가 추가될때마다 해야하는 작업)&lt;/p&gt;
&lt;pre id=&quot;code_1678785512060&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;context:component-scan base-package=&quot;kr.or.iei&quot; /&amp;gt;
	&amp;lt;context:component-scan base-package=&quot;kr.or.member&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Controller / Service / Dao 사전작업&lt;/p&gt;
&lt;pre id=&quot;code_1678869249971&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Controller
public class MemberController {
	//선언만 해놓으면 안에는 null이 들어있지만 AutoWired를 사용하면 null(X)
	@Autowired
	private MemberService service;
	
	public MemberController() {
		super();
		System.out.println(&quot;MemberController 생성&quot;);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1678869277899&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
public class MemberService {
	@Autowired
	private MemberDao dao;
	
	public MemberService() {
		super();
		System.out.println(&quot;MemberService 생성&quot;);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1678869298434&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Repository
public class MemberDao {

	@Autowired
	private JdbcTemplate jdbc;
	
	public MemberDao() {
		super();
		System.out.println(&quot;MemberDao 생성&quot;);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3 - 1 ) 아이디 조회하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;index.jsp&lt;/p&gt;
&lt;pre id=&quot;code_1678785576052&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;Spring MVC CRUD&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;form action=&quot;/searchMember.do&quot; method=&quot;get&quot;&amp;gt;
		조회할 아이디 입력 : &amp;lt;input type=&quot;text&quot; name=&quot;memberId&quot;&amp;gt;
		&amp;lt;input type=&quot;submit&quot; value=&quot;조회&quot;&amp;gt;
	&amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller&lt;/p&gt;
&lt;pre id=&quot;code_1678869458171&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	@RequestMapping(value=&quot;/searchMember.do&quot;)
	public String searchMember(String memberId, Model model) {
		//searchMember.do를 처리할 컨트롤러임을 알려줘야함 : 메소드 위에 기재
		//이제 서블릿은 Spring이 만들기 때문에 메소드만 생성해줌
		//값추출은 매개변수로 받음 - name값이랑 변수명이 동일해야한다.
		//3. 비즈니스로직
		Member member = service.selectOneMember(memberId);
		//4. 결과처리
		if(member == null) {
			return &quot;member/searchFail&quot;;
		}else {
			//request.setAttribute와 같은 역할을 해줌
			model.addAttribute(&quot;member&quot;, member);
			return &quot;member/searchMember&quot;;
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service&lt;/p&gt;
&lt;pre id=&quot;code_1678869492491&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public Member selectOneMember(String memberId) {
		//트랜잭션 관리는 우선 자동으로
		Member member = dao.selectOneMember(memberId);
		return member;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dao&lt;/p&gt;
&lt;pre id=&quot;code_1678869505164&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	public Member selectOneMember(String memberId) {
		//1. preparedStatement 방식으로 query 작성
		String query = &quot;select * from member_tbl where member_id = ?&quot;;
		//2. 위치홀더가 한개라도 있는 경우(만약, 위치홀더가 0개인 경우 2번과정 생략)
		//위치홀더의 순서에 맞춰서 Object 배열에 추가
		Object[] params = {memberId};
		//3. 쿼리문 실행(select 인 경우 객체생성 - query()메소드 사용)
		//query 매개변수 3개(쿼리문, 위치홀더에 들어갈 값 배열, 결과를 처리할 객체)
		List list = jdbc.query(query, params, new MemberRowMapper());
		//조회결과는 1개이건, 여러개건 무조건 List로 반환
		if(list.isEmpty()) {
			return null;			
		}else {
			Member m = (Member)list.get(0);
			return m;
		}
	}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>국비수업/Spring</category>
      <author>_HYE_</author>
      <guid isPermaLink="true">https://recordev.tistory.com/68</guid>
      <comments>https://recordev.tistory.com/68#entry68comment</comments>
      <pubDate>Tue, 14 Mar 2023 11:55:50 +0900</pubDate>
    </item>
    <item>
      <title>73일차 : Action Tag, EL, JSTL, Filter</title>
      <link>https://recordev.tistory.com/67</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;20230313&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Action Tag&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;:&amp;nbsp;JSP&amp;nbsp;문법을&amp;nbsp;확장하는&amp;nbsp;메커니즘을&amp;nbsp;제공하는&amp;nbsp;태그 &lt;br /&gt;&amp;lt;jsp:include&amp;gt;&amp;nbsp;:&amp;nbsp;페이지에&amp;nbsp;특정페이지를&amp;nbsp;포함할&amp;nbsp;때(예를들어&amp;nbsp;페이지에&amp;nbsp;헤더푸터) &lt;br /&gt;&amp;lt;jsp:forward&amp;gt;&amp;nbsp;:&amp;nbsp;현재&amp;nbsp;페이지&amp;nbsp;접근&amp;nbsp;시&amp;nbsp;특정&amp;nbsp;페이지로&amp;nbsp;이동&amp;nbsp;시킬&amp;nbsp;때 &lt;br /&gt;(&amp;nbsp;URL이&amp;nbsp;변경되지&amp;nbsp;않아&amp;nbsp;파라미터를&amp;nbsp;보낼&amp;nbsp;때&amp;nbsp;편함)&lt;/p&gt;
&lt;pre id=&quot;code_1678884200485&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;!-- 기존방식 : 지시자 태그를 이용 --&amp;gt;
	&amp;lt;%-- &amp;lt;%@include file=&quot;/WEB-INF/views/common/header.jsp&quot; %&amp;gt; --%&amp;gt;
	&amp;lt;%-- &amp;lt;jsp:include page=&quot;/WEB-INF/views/common/header.jsp&quot;&amp;gt;&amp;lt;/jsp:include&amp;gt; --%&amp;gt; 
	&amp;lt;jsp:include page=&quot;/WEB-INF/views/common/header.jsp&quot; /&amp;gt;
	&amp;lt;!-- 위 두개 모두 같은 문법 끝이라는 의미로 /를 해주면 /jsp:include와 같은의미를 갖는다. --&amp;gt;
	&amp;lt;h1&amp;gt;index&amp;lt;/h1&amp;gt;
	&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/test1.do&quot;&amp;gt;필터테스트&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
	
	&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/jspForward.do?name=test&quot;&amp;gt;jsp:forward&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1678884250614&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class test1Servlet
 */
@WebServlet(name = &quot;test1&quot;, urlPatterns = { &quot;/test1.do&quot; })
public class test1Servlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public test1Servlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println(&quot;서블릿 시작지점&quot;);
		//1. 인코딩
		//2. 값추출
		//3. 비즈니스로직
		//4. 결과처리
		System.out.println(&quot;서블릿 끝지점&quot;);
		response.sendRedirect(&quot;/&quot;);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1678884267906&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.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;

/**
 * Servlet implementation class JspForwardServlet
 */
@WebServlet(name = &quot;JspForward&quot;, urlPatterns = { &quot;/jspForward.do&quot; })
public class JspForwardServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public JspForwardServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//1. 인코딩
		request.setCharacterEncoding(&quot;utf-8&quot;);
		//2. 값추출
		String name = request.getParameter(&quot;name&quot;);
		//3. 비즈니스로직
		//4. 결과처리
		RequestDispatcher view = request.getRequestDispatcher(&quot;/WEB-INF/views/action/forward.jsp&quot;);
		request.setAttribute(&quot;name&quot;, name);
		view.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1678884285263&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
    &amp;lt;%
    	String name = (String)request.getAttribute(&quot;name&quot;);
    %&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;%if(name != null) {%&amp;gt;
	&amp;lt;!-- 
	&amp;lt;script&amp;gt;
		location.href=&quot;/forward2.do&quot; 
	&amp;lt;/script&amp;gt;
	이 방법으로 서블릿을 하나 더 생성해서 이동하는 방법도 있지만 위방식의 경우 name파라미터를 또 보내줘야함
	태그가 나왔다가 자바코드가 나왔다가 하는 것을 태그만 사용해서 이용하는 것
	 --&amp;gt;
	&amp;lt;jsp:forward page=&quot;/WEB-INF/views/action/forward2.jsp&quot; /&amp;gt;
	&amp;lt;!-- include처럼 추가한게 아닌 이동한 것이므로 아래 forward name은나오지않고 forward2로 페이지이동 --&amp;gt;
	&amp;lt;%} %&amp;gt;
	&amp;lt;h1&amp;gt;forward&amp;lt;/h1&amp;gt;
	&amp;lt;h2&amp;gt;&amp;lt;%= name %&amp;gt;&amp;lt;/h2&amp;gt;
	&amp;lt;!-- web-inf에 있는 jsp는 반드시 서블릿을 통해 이동해야함 : 이과정을 생략해주는게 action:forward --&amp;gt;
	&amp;lt;!-- action태그를 이용하면 바로 이동이 가능하다. --&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1678884297543&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
    &amp;lt;!-- 주소창은 Servlet주소가 여전히 유지(jspFoward.do?name=test) 
    forward방식으로 이동하면 forward2에서도 name=test라는 파라미터를 이용 가능 --&amp;gt;
    &amp;lt;%
    	String name = (String)request.getAttribute(&quot;name&quot;);
    %&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;forward2&amp;lt;/h1&amp;gt;
	&amp;lt;h3&amp;gt;&amp;lt;%=name %&amp;gt;&amp;lt;/h3&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. EL&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: &amp;lt;%=%&amp;gt;,&amp;nbsp;out.print()를&amp;nbsp;좀더&amp;nbsp;간결하게&amp;nbsp;사용하는&amp;nbsp;방법&amp;nbsp;${value}의&amp;nbsp;형식으로&amp;nbsp;표현&lt;/p&gt;
&lt;pre id=&quot;code_1678884352900&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;h2&amp;gt;EL(Expression Language)&amp;lt;/h2&amp;gt;
	&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/eLTest1.do&quot;&amp;gt;1. EL test1(기본문법)&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
	&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/eLTest2.do&quot;&amp;gt;2. EL test2(VO)&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
	&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/eLTest3.do&quot;&amp;gt;3. EL test3(list, array)&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
	&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/eLTest4.do&quot;&amp;gt;4. EL test4(연산)&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
	&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/eLTest5.do&quot;&amp;gt;5. EL test5(내장객체)&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2 - 1 ) 기본문법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Servlet&lt;/p&gt;
&lt;pre id=&quot;code_1678884385010&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.controller;

import java.io.IOException;

import javax.security.auth.message.callback.PrivateKeyCallback.Request;
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;

/**
 * Servlet implementation class ELTest1Servlet
 */
@WebServlet(name = &quot;ELTest1&quot;, urlPatterns = { &quot;/eLTest1.do&quot; })
public class ELTest1Servlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ELTest1Servlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//1. 인코딩
		request.setCharacterEncoding(&quot;utf-8&quot;);
		//2. 값추출
		//3. 비즈니스로직
		//4. 결과처리
		RequestDispatcher view = request.getRequestDispatcher(&quot;/WEB-INF/views/el/elTest1.jsp&quot;);
		request.setAttribute(&quot;name&quot;, &quot;유저1&quot;);
		request.setAttribute(&quot;age&quot;, 20);
		request.setAttribute(&quot;addr&quot;, &quot;서울시 영등포구&quot;);
		view.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSP&lt;/p&gt;
&lt;pre id=&quot;code_1678884411343&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h2&amp;gt;이름 : ${name}&amp;lt;/h2&amp;gt;
	&amp;lt;h2&amp;gt;나이 : ${age}&amp;lt;/h2&amp;gt;
	&amp;lt;h2&amp;gt;주소 : ${addr}&amp;lt;/h2&amp;gt;
	&amp;lt;h2&amp;gt;전화번호 : ${phone}&amp;lt;/h2&amp;gt;
	&amp;lt;!-- 기존문법과 달리 phone이 null이 아니고 공백으로 나온다 --&amp;gt;
	&amp;lt;!-- 위에 변수를 선언하지 않아도 사용이 가능하다. --&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2 - 2 ) VO&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Servlet&lt;/p&gt;
&lt;pre id=&quot;code_1678884466870&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.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;

/**
 * Servlet implementation class ELTest2Servlet
 */
@WebServlet(name = &quot;ELTest2&quot;, urlPatterns = { &quot;/eLTest2.do&quot; })
public class ELTest2Servlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ELTest2Servlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//1. 인코딩
		request.setCharacterEncoding(&quot;utf-8&quot;);
		//2. 값추출
		//3. 비즈니스로직
		Member m = new Member(&quot;유저2&quot;, 30, &quot;서울시 강남구&quot;);
		//4. 결과처리
		RequestDispatcher view = request.getRequestDispatcher(&quot;/WEB-INF/views/el/elTest2.jsp&quot;);
		request.setAttribute(&quot;m&quot;, m);
		view.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSP&lt;/p&gt;
&lt;pre id=&quot;code_1678884478976&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h3&amp;gt;이름 : ${m.name }&amp;lt;/h3&amp;gt; 
	&amp;lt;!-- 적는건 name으로 적지만 getName()을 알아서 호출하고 있는 것 --&amp;gt;
	&amp;lt;h3&amp;gt;나이 : ${m.age }&amp;lt;/h3&amp;gt;
	&amp;lt;h3&amp;gt;주소 : ${m.addr }&amp;lt;/h3&amp;gt;
	&amp;lt;h3&amp;gt;${m.test }&amp;lt;/h3&amp;gt; 
	&amp;lt;!-- Member에 test라는게 없으므로 에러발생 --&amp;gt;
	&amp;lt;!-- 단, Member에 getTest메소드만 만들어도 사용가능 : 변수를 가져오는게 아닌 getter를 가져오는 것 --&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2 - 3 ) List, Array&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Servlet&lt;/p&gt;
&lt;pre id=&quot;code_1678884505730&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.controller;

import java.io.IOException;
import java.util.ArrayList;

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;

/**
 * Servlet implementation class ELTest3Servlet
 */
@WebServlet(name = &quot;ELTest3&quot;, urlPatterns = { &quot;/eLTest3.do&quot; })
public class ELTest3Servlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ELTest3Servlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//1. 인코딩
		request.setCharacterEncoding(&quot;utf-8&quot;);
		//2. 값추출
		//3. 비즈니스로직
		int[] numArr = {100,200,300};
		ArrayList&amp;lt;Integer&amp;gt; numList = new ArrayList&amp;lt;Integer&amp;gt;();
		numList.add(10);
		numList.add(20);
		numList.add(30);
		
		ArrayList&amp;lt;Member&amp;gt; memberList = new ArrayList&amp;lt;Member&amp;gt;();
		Member m1 = new Member(&quot;유저1&quot;, 30, &quot;서울&quot;);
		Member m2 = new Member(&quot;유저2&quot;, 40, &quot;인천&quot;);
		memberList.add(m1);
		memberList.add(m2);
		//4. 결과처리
		RequestDispatcher view = request.getRequestDispatcher(&quot;/WEB-INF/views/el/elTest3.jsp&quot;);
		request.setAttribute(&quot;numArr&quot;, numArr);
		request.setAttribute(&quot;numList&quot;, numList);
		request.setAttribute(&quot;memberList&quot;, memberList);
		view.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSP&lt;/p&gt;
&lt;pre id=&quot;code_1678884517709&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h2&amp;gt;배열 사용 방법&amp;lt;/h2&amp;gt;
	&amp;lt;p&amp;gt;${numArr[0] }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;${numArr[1] }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;${numArr[2] }&amp;lt;/p&amp;gt;
	&amp;lt;h2&amp;gt;리스트 사용 방법 1&amp;lt;/h2&amp;gt;
	&amp;lt;p&amp;gt;${numList[0] }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;${numList[1] }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;${numList[2] }&amp;lt;/p&amp;gt;
	&amp;lt;h2&amp;gt;리스트 사용 방법 2&amp;lt;/h2&amp;gt;
	&amp;lt;p&amp;gt;${memberList[0].name }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;${memberList[0].age }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;${memberList[0].addr }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;${memberList[1].name }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;${memberList[1].age }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;${memberList[1].addr }&amp;lt;/p&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2 - 4 ) 연산&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Servlet&lt;/p&gt;
&lt;pre id=&quot;code_1678884621662&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.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;

/**
 * Servlet implementation class ELTest4Servlet
 */
@WebServlet(name = &quot;ELTest4&quot;, urlPatterns = { &quot;/eLTest4.do&quot; })
public class ELTest4Servlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ELTest4Servlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//1. 인코딩
		request.setCharacterEncoding(&quot;utf-8&quot;);
		//2. 값추출
		//3. 비즈니스로직
		//4. 결과처리
		RequestDispatcher view = request.getRequestDispatcher(&quot;/WEB-INF/views/el/elTest4.jsp&quot;);
		request.setAttribute(&quot;num1&quot;, 10);
		request.setAttribute(&quot;num2&quot;, 20);
		request.setAttribute(&quot;str&quot;, &quot;abc&quot;);
		view.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSP&lt;/p&gt;
&lt;pre id=&quot;code_1678884636682&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;EL 연산&amp;lt;/h1&amp;gt;
	&amp;lt;ul&amp;gt;
		&amp;lt;li&amp;gt;${num1 }&amp;lt;/li&amp;gt;
		&amp;lt;li&amp;gt;${num2 }&amp;lt;/li&amp;gt;
		&amp;lt;li&amp;gt;${str }&amp;lt;/li&amp;gt;
		&amp;lt;li&amp;gt;${str1 }&amp;lt;/li&amp;gt;
	&amp;lt;/ul&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;table border=&quot;1&quot;&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;th&amp;gt;표현식&amp;lt;/th&amp;gt;
			&amp;lt;th&amp;gt;결과&amp;lt;/th&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;\${num1 }+\${num2 }&amp;lt;/td&amp;gt; &amp;lt;!-- 화면은 10+20 으로 만들어질것 \를사용하면 el로 사용하지 말라는 의미 --&amp;gt;
			&amp;lt;td&amp;gt;${num1 }+${num2 }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;\${num1 - num2 }&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;${num1 - num2 }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;\${num1 * num2 }&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;${num1 * num2 }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;\${num1 / num2 }&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;${num1 / num2 }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;\${num1 % num2 }&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;${num1 % num2 }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;\${num1 &amp;gt; num2 }&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;${num1 gt num2 }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;\${num1 &amp;lt; num2 }&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;${num1 lt num2 }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;\${num1 &amp;gt;= num2 }&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;${num1 ge num2 }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;\${num1 &amp;lt;= num2 }&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;${num1 le num2 }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;		
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;\${num1 == num2 }&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;${num1 eq num2 }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;\${num1 != num2 }&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;${num1 ne num2 }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;	
			&amp;lt;td&amp;gt;\${str == &quot;abc&quot; }&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;${str eq &quot;abc&quot; }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;\${str == null }&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;${empty str }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;\${str == null }&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;${not empty str }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;\${str1 == null }&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;${empty str }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;\${str1 == null }&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;${not empty str }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
	&amp;lt;/table&amp;gt;
	&amp;lt;%--
		&amp;gt;	 	-&amp;gt;	 	 gt(greater)
		&amp;lt;	 	-&amp;gt;   	 lt(little)
		&amp;gt;=	 	-&amp;gt;	 	 get(greater or equal)
		&amp;lt;=	 	-&amp;gt;	 	 le(little or equal)
		==	 	-&amp;gt;	 	 eq(equal)
		!=	 	-&amp;gt;	  	 ne(not equal)
	 --%&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2 - 5 ) 내장객체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Servlet&lt;/p&gt;
&lt;pre id=&quot;code_1678884650960&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.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 javax.servlet.http.HttpSession;

/**
 * Servlet implementation class ELTest5Servlet
 */
@WebServlet(name = &quot;ELTest5&quot;, urlPatterns = { &quot;/eLTest5.do&quot; })
public class ELTest5Servlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ELTest5Servlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//1. 인코딩
		request.setCharacterEncoding(&quot;utf-8&quot;);
		//2. 값추출
		Member m1 = new Member(&quot;유저1&quot;, 20, &quot;서울&quot;);
		Member m2 = new Member(&quot;유저2&quot;, 30, &quot;부산&quot;);
		//3. 비즈니스로직
		//4. 결과처리
		RequestDispatcher view = request.getRequestDispatcher(&quot;/WEB-INF/views/el/elTest5.jsp&quot;);
		request.setAttribute(&quot;m&quot;, m1);
		HttpSession session = request.getSession();
		session.setAttribute(&quot;m&quot;, m2);
		view.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSP&lt;/p&gt;
&lt;pre id=&quot;code_1678884665925&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;request data&amp;lt;/h1&amp;gt;
	&amp;lt;p&amp;gt;${requestScope.m.name }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;${requestScope.m.age }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;${requestScope.m.addr }&amp;lt;/p&amp;gt;
	&amp;lt;h2&amp;gt;session data&amp;lt;/h2&amp;gt;
	&amp;lt;p&amp;gt;${sessionScope.m.name }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;${sessionScope.m.age }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;${sessionScope.m.addr }&amp;lt;/p&amp;gt;
	&amp;lt;%-- key값이 겹칠 경우 session에 있는 데이터는 가져오지 않음 requestScope / sessionScope 명시 
	session보다 request에서 더 많이 가져오므로 기본적으로 명시하지 않을 경우 request로 가져온다
	request는 생략해도 되지만, session은 key값이 겹치지 않더라도 명시해주는게 좋음(사용에는 문제가 없지만 코드를 봤을 때 구분이 안되므로) --%&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. JSTL&amp;nbsp;: 사용하는 코드의 집합을 태그화 하여 표준으로 제공한것 &lt;br /&gt;1.&amp;nbsp;라이브러리등록&amp;nbsp;jstl &lt;br /&gt;2.&amp;nbsp;선언&amp;lt;%@taglib&amp;nbsp;uri=&quot;링크&quot;&amp;nbsp;@&amp;gt; &lt;br /&gt;3.&amp;nbsp;사용&amp;nbsp;&amp;lt;c:if&amp;nbsp;~~&amp;nbsp;/&amp;gt; &lt;br /&gt;&lt;br /&gt;core&amp;nbsp;tag&amp;nbsp;:&amp;nbsp;변수와&amp;nbsp;url,&amp;nbsp;조건문,&amp;nbsp;반목문과&amp;nbsp;관련된&amp;nbsp;문법제공 &lt;br /&gt;&lt;br /&gt;&amp;lt;c:set&amp;gt;&amp;nbsp;:&amp;nbsp;변수를&amp;nbsp;선언하고&amp;nbsp;그&amp;nbsp;변수에&amp;nbsp;초기앖을&amp;nbsp;대입하는&amp;nbsp;기능의&amp;nbsp;태그(자바변수선언과&amp;nbsp;유사) &lt;br /&gt;int&amp;nbsp;num&amp;nbsp;=&amp;nbsp;100&amp;nbsp;/&amp;nbsp;&amp;lt;c:set&amp;nbsp;var=&quot;num&quot;&amp;nbsp;value=&quot;100&quot;&amp;nbsp;scope=&quot;request&quot;&amp;nbsp;/&amp;gt; &lt;br /&gt;&lt;br /&gt;&amp;lt;c:out&amp;gt;&amp;nbsp;:&amp;nbsp;데이터를&amp;nbsp;출력할&amp;nbsp;때&amp;nbsp;사용&amp;nbsp; &lt;br /&gt;&amp;lt;c:out&amp;nbsp;value=&quot;야호&quot;&amp;gt; &lt;br /&gt;&lt;br /&gt;&amp;lt;c:if&amp;gt;&amp;nbsp;:&amp;nbsp;if문&amp;nbsp;조건식은&amp;nbsp;test라는&amp;nbsp;속성의&amp;nbsp;값으로&amp;nbsp;지정 &lt;br /&gt;&amp;lt;c:if&amp;nbsp;test=&quot;${num1&amp;gt;num2}&quot;&amp;gt;&amp;nbsp;야호&amp;nbsp;&amp;lt;/c:if&amp;gt; &lt;br /&gt;&lt;br /&gt;&amp;lt;c:choose&amp;gt;&amp;nbsp;:&amp;nbsp;switch&amp;nbsp;/&amp;nbsp;if~else&amp;nbsp;if&amp;nbsp;문&amp;nbsp; &lt;br /&gt;&amp;lt;c:when&amp;nbsp;test=&quot;조건&quot;&amp;gt;&amp;lt;/c:when&amp;gt;&amp;nbsp;과&amp;nbsp;&amp;lt;c:otherwise&amp;gt;&amp;lt;/c:otherwise&amp;gt;함께사용 &lt;br /&gt;(c:otherwise는&amp;nbsp;else) &lt;br /&gt;&lt;br /&gt;&amp;lt;c:forEach&amp;gt;&amp;nbsp;:&amp;nbsp;forEach문 &lt;br /&gt;items&amp;nbsp;:&amp;nbsp;반복할&amp;nbsp;객체명&amp;nbsp;/&amp;nbsp;var&amp;nbsp;:&amp;nbsp;반복횟수에&amp;nbsp;해당하는&amp;nbsp;변수명&amp;nbsp;/&amp;nbsp;step&amp;nbsp;:&amp;nbsp;반복할&amp;nbsp;횟수번호 &lt;br /&gt;&lt;br /&gt;&amp;lt;c:forTokens&amp;gt;&amp;nbsp;:&amp;nbsp;구분자를&amp;nbsp;통해&amp;nbsp;토큰을&amp;nbsp;분리해서&amp;nbsp;반복처리&amp;nbsp; &lt;br /&gt;items&amp;nbsp;:&amp;nbsp;토큰을&amp;nbsp;포함하는&amp;nbsp;문자열&amp;nbsp;/&amp;nbsp;delims&amp;nbsp;토큰구분자 &lt;br /&gt;&lt;br /&gt;&amp;lt;c:url&amp;gt;&amp;nbsp;:&amp;nbsp;url경로를&amp;nbsp;생성&lt;/p&gt;
&lt;pre id=&quot;code_1678884727759&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	&amp;lt;h2&amp;gt;JSTL(JSP Standard Tag Library)&amp;lt;/h2&amp;gt;
	&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/jstlTest1.do&quot;&amp;gt;1. JSTL 기본사용법&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
	&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/jstlTest2.do&quot;&amp;gt;2. JSTL if&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
	&amp;lt;h3&amp;gt;3. JSTL choose&amp;lt;/h3&amp;gt;
	&amp;lt;form action=&quot;/jstlTest3.do&quot;&amp;gt;
		&amp;lt;input type=&quot;text&quot; name=&quot;num&quot;&amp;gt;
		&amp;lt;input type=&quot;submit&quot; value=&quot;전송&quot;&amp;gt;
	&amp;lt;/form&amp;gt;
	&amp;lt;h3&amp;gt;&amp;lt;a href=&quot;/jstlTest4.do&quot;&amp;gt;4. JSTL forEach&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3 - 1 ) 기본사용법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Servlet&lt;/p&gt;
&lt;pre id=&quot;code_1678884759565&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.controller;

import java.io.IOException;

import javax.security.auth.message.callback.PrivateKeyCallback.Request;
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;

/**
 * Servlet implementation class JstlTest1Servlet
 */
@WebServlet(name = &quot;JstlTest1&quot;, urlPatterns = { &quot;/jstlTest1.do&quot; })
public class JstlTest1Servlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public JstlTest1Servlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		RequestDispatcher view = request.getRequestDispatcher(&quot;/WEB-INF/views/jstl/jstlTest1.jsp&quot;);
		view.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSP&lt;/p&gt;
&lt;pre id=&quot;code_1678884791090&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
    &amp;lt;%@ taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot; %&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;JSTL 기본문법&amp;lt;/h1&amp;gt;
	&amp;lt;h3&amp;gt;1. 변수를 선언(기본 변수 선언으로 해당페이지에서만 사용 가능)&amp;lt;/h3&amp;gt;
	&amp;lt;%-- 
	&amp;lt;%
		int num = 10;
	%&amp;gt; 
	위 코드를 core tag를 사용해서 선언
	--%&amp;gt;
	&amp;lt;c:set var=&quot;num&quot; value=&quot;10&quot; /&amp;gt;
	&amp;lt;c:set var=&quot;str&quot; value=&quot;안녕&quot; /&amp;gt;
	&amp;lt;%-- page &amp;lt; request &amp;lt; session &amp;lt; application 
	페이지 내에서만 사용할 수 있는 pageScope에 생성된다. --%&amp;gt;
	&amp;lt;p&amp;gt;request: ${requestScope.num }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;session: ${sessionScope.num }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;page : ${pageScope.num }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;page : ${pageScope.str }&amp;lt;/p&amp;gt;
	
	&amp;lt;h3&amp;gt;2. 변수 선언(영역 지정)&amp;lt;/h3&amp;gt;
	&amp;lt;%--scope를 지정해서 원하는 영역에 변수를 만들 수 도 있다. --%&amp;gt;
	&amp;lt;c:set var=&quot;num1&quot; value=&quot;200&quot; scope=&quot;request&quot; /&amp;gt;
	&amp;lt;c:set var=&quot;num1&quot; value=&quot;300&quot; scope=&quot;session&quot; /&amp;gt;
	&amp;lt;p&amp;gt; request : ${requestScope.num1 }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt; session : ${sessionScope.num1 }&amp;lt;/p&amp;gt;
	
	&amp;lt;h3&amp;gt;3. 변수 삭제&amp;lt;/h3&amp;gt;
	&amp;lt;c:remove var=&quot;num1&quot; scope=&quot;session&quot; /&amp;gt;
	&amp;lt;%--num1이라는 변수가 request에도 session에도 있으므로 어느영역에 있는 num1를 삭제할 지 지정해 주어야함 --%&amp;gt;
	&amp;lt;p&amp;gt; request : ${requestScope.num1 }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt; session : ${sessionScope.num1 }&amp;lt;/p&amp;gt;
	
	&amp;lt;h3&amp;gt;4. core를 이용한 출력&amp;lt;/h3&amp;gt;
	&amp;lt;p&amp;gt;EL : ${num1 }&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;core : &amp;lt;c:out value=&quot;${num1 }&quot; /&amp;gt;&amp;lt;/p&amp;gt;
	&amp;lt;%-- coreTag는 기본값설정이 가능하다 --%&amp;gt;
	&amp;lt;p&amp;gt;core(session) : &amp;lt;c:out value=&quot;${sessionScope.num1 }&quot; default=&quot;값없음&quot; /&amp;gt;
	&amp;lt;c:set var=&quot;test&quot; value=&quot;&amp;lt;b&amp;gt;진한글씨&amp;lt;/b&amp;gt;&quot; /&amp;gt;
	&amp;lt;p&amp;gt;EL : ${pageScope.test }&amp;lt;/p&amp;gt; 
	&amp;lt;%--그냥 출력 시에는 EL이 쉽지만 아래처럼 태그포함출력이라거나 설정을 주고싶을 때는 c:out태그를 사용 --%&amp;gt;
	&amp;lt;p&amp;gt;core1 : &amp;lt;c:out value=&quot;${pageScope.test }&quot; escapeXml=&quot;true&quot; /&amp;gt;&amp;lt;/p&amp;gt;
	&amp;lt;p&amp;gt;core2 : &amp;lt;c:out value=&quot;${pageScope.test }&quot; escapeXml=&quot;false&quot; /&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3 - 2 ) if&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Servlet&lt;/p&gt;
&lt;pre id=&quot;code_1678884866978&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.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;

/**
 * Servlet implementation class JstlTest2Servlet
 */
@WebServlet(name = &quot;JstlTest2&quot;, urlPatterns = { &quot;/jstlTest2.do&quot; })
public class JstlTest2Servlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public JstlTest2Servlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		RequestDispatcher view = request.getRequestDispatcher(&quot;/WEB-INF/views/jstl/jstlTest2.jsp&quot;);
		request.setAttribute(&quot;num&quot;, 100);
		view.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSP&lt;/p&gt;
&lt;pre id=&quot;code_1678884891214&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
    &amp;lt;%@ taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot; %&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;c:if&amp;lt;/h1&amp;gt;
	&amp;lt;c:if test=&quot;${num%2 eq 0 }&quot;&amp;gt;
	&amp;lt;h3&amp;gt;짝수&amp;lt;/h3&amp;gt;
	&amp;lt;/c:if&amp;gt;
	&amp;lt;c:if test=&quot;${num%2 eq 1 }&quot;&amp;gt;
	&amp;lt;h3&amp;gt;홀수&amp;lt;/h3&amp;gt;
	&amp;lt;/c:if&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3 - 3 ) choose : switch/if~else if와 유사&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Servlet&lt;/p&gt;
&lt;pre id=&quot;code_1678884926774&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.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;

/**
 * Servlet implementation class JstlTest3Servlet
 */
@WebServlet(name = &quot;JstlTest3&quot;, urlPatterns = { &quot;/jstlTest3.do&quot; })
public class JstlTest3Servlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public JstlTest3Servlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//1. 인코딩
		request.setCharacterEncoding(&quot;utf-8&quot;);
		//2. 값추출
		int num = Integer.parseInt(request.getParameter(&quot;num&quot;));
		//3. 비즈니스로직
		//4. 결과처리
		RequestDispatcher view = request.getRequestDispatcher(&quot;/WEB-INF/views/jstl/jstlTest3.jsp&quot;);
		request.setAttribute(&quot;num&quot;, num);
		view.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSP&lt;/p&gt;
&lt;pre id=&quot;code_1678884944658&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
    &amp;lt;%@ taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot; %&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;c:choose&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;c:choose&amp;gt;
		&amp;lt;c:when test=&quot;${num%3 == 0 &amp;amp;&amp;amp; num%4 == 0}&quot;&amp;gt;
			&amp;lt;h1&amp;gt;3의 배수이면서 4의배수입니다.&amp;lt;/h1&amp;gt;
		&amp;lt;/c:when&amp;gt;
		&amp;lt;c:when test=&quot;${num%4 == 0 }&quot;&amp;gt;
			&amp;lt;h1&amp;gt;4의 배수입니다.&amp;lt;/h1&amp;gt;
		&amp;lt;/c:when&amp;gt;
		&amp;lt;c:when test=&quot;${num%3 == 0 }&quot;&amp;gt;
			&amp;lt;h1&amp;gt;3의 배수입니다.&amp;lt;/h1&amp;gt;
		&amp;lt;/c:when&amp;gt;
		&amp;lt;c:otherwise&amp;gt;
			&amp;lt;h1&amp;gt;3의 배수도 4의 배수도 아닙니다.&amp;lt;/h1&amp;gt;
		&amp;lt;/c:otherwise&amp;gt;
		&amp;lt;%--else if의 경우에는 c:when을 한번더 입력 / else의 경우 c:otherwise사용 --%&amp;gt;
	&amp;lt;/c:choose&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3 - 4 ) forEach&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Servlet&lt;/p&gt;
&lt;pre id=&quot;code_1678884988435&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.controller;

import java.io.IOException;
import java.util.ArrayList;

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;

/**
 * Servlet implementation class JstlTest4Servlet
 */
@WebServlet(name = &quot;JstlTest4&quot;, urlPatterns = { &quot;/jstlTest4.do&quot; })
public class JstlTest4Servlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public JstlTest4Servlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//1. 인코딩
		request.setCharacterEncoding(&quot;utf-8&quot;);
		//2. 값추출
		//3. 비즈니스로직
		ArrayList&amp;lt;Member&amp;gt; list = new ArrayList&amp;lt;Member&amp;gt;();
		Member m1 = new Member(&quot;유저1&quot;, 20, &quot;서울&quot;);
		Member m2 = new Member(&quot;유저2&quot;, 30, &quot;인천&quot;);
		Member m3 = new Member(&quot;유저3&quot;, 40, &quot;경기&quot;);
		list.add(m1);
		list.add(m2);
		list.add(m3);
		//4. 결과처리
		RequestDispatcher view = request.getRequestDispatcher(&quot;/WEB-INF/views/jstl/jstlTest4.jsp&quot;);
		request.setAttribute(&quot;list&quot;, list);
		view.forward(request, response);;
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSP&lt;/p&gt;
&lt;pre id=&quot;code_1678885008098&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
    &amp;lt;%@ taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h1&amp;gt;c:forEach&amp;lt;/h1&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;h3&amp;gt;1. 리스트 순회 반복&amp;lt;/h3&amp;gt;
	&amp;lt;table border=&quot;1&quot;&amp;gt;
		&amp;lt;tr style=&quot;background-color: #ccc&quot;&amp;gt;
			&amp;lt;th&amp;gt;순서&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;이름&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;나이&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;주소&amp;lt;/th&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;%-- for(Member m : list) // items=&quot;list&quot;로 넣지않도록 주의 저렇게하면 list라는 문자열이 들어간 것 --%&amp;gt;
		&amp;lt;c:forEach items=&quot;${list }&quot; var=&quot;m&quot; varStatus=&quot;i&quot;&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;${i.index }&amp;lt;/td&amp;gt; &amp;lt;%--index는 0부터시작 count는 1부터시작 --%&amp;gt;
			&amp;lt;td&amp;gt;${m.name }&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;${m.age }&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;${m.addr }&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;/c:forEach&amp;gt;
	&amp;lt;/table&amp;gt;
	&amp;lt;hr&amp;gt;
	&amp;lt;h3&amp;gt;2. 반복회차 지정하는 반복문&amp;lt;/h3&amp;gt;
	&amp;lt;ul&amp;gt;
		&amp;lt;c:forEach begin=&quot;1&quot; end=&quot;10&quot; step=&quot;1&quot; varStatus=&quot;i&quot;&amp;gt;
			&amp;lt;li&amp;gt;${i.count }_번째 반복&amp;lt;/li&amp;gt;
		&amp;lt;/c:forEach&amp;gt;
	&amp;lt;/ul&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. Filter&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트와&amp;nbsp;서버사이에서&amp;nbsp;request&amp;nbsp;/&amp;nbsp;response객체를&amp;nbsp;필터가&amp;nbsp;먼저&amp;nbsp;받아&amp;nbsp;공통적으로&amp;nbsp;필요한&amp;nbsp;부분을&amp;nbsp;처리 &lt;br /&gt;인코딩&amp;nbsp;같은거&amp;nbsp;할때(공통적임)&amp;nbsp;Filter에&amp;nbsp;추가해두면&amp;nbsp;좋음&lt;/p&gt;
&lt;pre id=&quot;code_1678885051513&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package common;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class EncodingFilter implements Filter{

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		System.out.println(&quot;필터 종료&quot;);
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// TODO Auto-generated method stub
		System.out.println(&quot;서블린 가기 전&quot;);
		request.setCharacterEncoding(&quot;utf-8&quot;);
		System.out.println(&quot;인코딩 완료&quot;);
		chain.doFilter(request, response);//서블릿 수행코드
		System.out.println(&quot;서블릿 종료 후&quot;);
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		System.out.println(&quot;초기화 완료&quot;);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;web.xml&lt;/p&gt;
&lt;pre id=&quot;code_1678953187306&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;web-app xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xmlns=&quot;http://xmlns.jcp.org/xml/ns/javaee&quot; xsi:schemaLocation=&quot;http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd&quot; id=&quot;WebApp_ID&quot; version=&quot;3.1&quot;&amp;gt;
  &amp;lt;display-name&amp;gt;08_etcProject&amp;lt;/display-name&amp;gt;
  &amp;lt;welcome-file-list&amp;gt;
    &amp;lt;welcome-file&amp;gt;index.jsp&amp;lt;/welcome-file&amp;gt;
  &amp;lt;/welcome-file-list&amp;gt;
  &amp;lt;filter&amp;gt;
	  &amp;lt;filter-name&amp;gt;EncodingFilter&amp;lt;/filter-name&amp;gt;
	   //패키지경로 반드시
	  &amp;lt;filter-class&amp;gt;common.EncodingFilter&amp;lt;/filter-class&amp;gt;
  &amp;lt;/filter&amp;gt;
&amp;lt;/web-app&amp;gt;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>국비수업/Server</category>
      <author>_HYE_</author>
      <guid isPermaLink="true">https://recordev.tistory.com/67</guid>
      <comments>https://recordev.tistory.com/67#entry67comment</comments>
      <pubDate>Tue, 14 Mar 2023 11:54:29 +0900</pubDate>
    </item>
    <item>
      <title>61일차 : Editor, GitHub</title>
      <link>https://recordev.tistory.com/65</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;20230223&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Editor - summernote&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공지사항 작성폼에 summernote에디터추가하기&lt;/p&gt;
&lt;pre id=&quot;code_1678885571709&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
&amp;lt;title&amp;gt;Insert title here&amp;lt;/title&amp;gt;
&amp;lt;style&amp;gt;
	#noticeWrite td, #noticeWrite th{
		border: 1px solid #ccc;
	}
&amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;!-- textarea에 텍스트에디터만들기 --&amp;gt;
	&amp;lt;%@include file=&quot;/WEB-INF/views/common/header.jsp&quot; %&amp;gt;
	&amp;lt;script src=&quot;/summernote/summernote-lite.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src=&quot;/summernote/lang/summernote-ko-KR.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;link rel=&quot;stylesheet&quot; href=&quot;/summernote/summernote-lite.css&quot;&amp;gt;
	&amp;lt;div class=&quot;page-content&quot;&amp;gt;
		&amp;lt;div class=&quot;page-title&quot;&amp;gt;공지사항 작성&amp;lt;/div&amp;gt;
		&amp;lt;form action=&quot;/noticeWrite.do&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&amp;gt;
		&amp;lt;!-- 
			첨부파일이 존재하는 경우 
			일단 양이 많기때문에 method = post
			파일이 포함되는 경우 enctype=&quot;multipart/form-data
			이 양식을 반드시 지켜줘야한다. 
		--&amp;gt;
			&amp;lt;table class=&quot;tbl&quot; id=&quot;noticeWrite&quot;&amp;gt;
				&amp;lt;tr class=&quot;tr-1&quot;&amp;gt;
					&amp;lt;th class=&quot;td-3&quot;&amp;gt;제목
					&amp;lt;td colspan=&quot;3&quot;&amp;gt;
						&amp;lt;input type=&quot;text&quot; name=&quot;noticeTitle&quot; class=&quot;input-form&quot;&amp;gt;
					&amp;lt;/td&amp;gt;
				&amp;lt;/tr&amp;gt;
				&amp;lt;tr class=&quot;tr-1&quot;&amp;gt;
					&amp;lt;th class=&quot;td-3&quot;&amp;gt;작성자
					&amp;lt;td&amp;gt;
						&amp;lt;%=m.getMemberId() %&amp;gt;
						&amp;lt;input type=&quot;hidden&quot; name=&quot;noticeWriter&quot; value=&quot;&amp;lt;%=m.getMemberId() %&amp;gt;&quot;&amp;gt;
					&amp;lt;/td&amp;gt;
					&amp;lt;th class=&quot;td-3&quot;&amp;gt;첨부파일&amp;lt;/th&amp;gt;
					&amp;lt;td&amp;gt;&amp;lt;input type=&quot;file&quot; name=&quot;upfile&quot;&amp;gt;&amp;lt;/td&amp;gt;
				&amp;lt;/tr&amp;gt;
				&amp;lt;tr class=&quot;tr-1&quot;&amp;gt;
					&amp;lt;td colspan=&quot;4&quot; style=&quot;text-align:left&quot;&amp;gt;
						&amp;lt;textarea id=&quot;noticeContent&quot; name=&quot;noticeContent&quot; class=&quot;input-form&quot;&amp;gt;&amp;lt;/textarea&amp;gt;
					&amp;lt;/td&amp;gt;
				&amp;lt;/tr&amp;gt;
				&amp;lt;tr class=&quot;tr-1&quot;&amp;gt;
					&amp;lt;td colspan=&quot;4&quot;&amp;gt;
						&amp;lt;button type=&quot;submit&quot; class=&quot;btn bc4 bs4&quot;&amp;gt;공지사항작성&amp;lt;/button&amp;gt;
					&amp;lt;/td&amp;gt;
				&amp;lt;/tr&amp;gt;
			&amp;lt;/table&amp;gt;
		&amp;lt;/form&amp;gt;
	&amp;lt;/div&amp;gt;
	&amp;lt;script&amp;gt;
      $(&quot;#noticeContent&quot;).summernote({
         height : 400,
         lang : &quot;ko-KR&quot;,
         callbacks : {
        	 onImageUpload : function(files){
        		 uploadImage(files[0], this);
        		 //이미지는 files에 들어가고 this는 이 에디터를 의미
        	 }
         }
      });
      function uploadImage(file, editor){
    	  //file : 업로드용 / editor는 &amp;lt;img src=&amp;gt;로 보여주기 위해
    	  //ajax를 통해에서 서버에 이미지를 업로드 -&amp;gt; 업로드된 이미지의 경로를 받아오는 역할
    	  //받아온 이후 -&amp;gt; editor에 이미지 경로를 전달에서 화면에 표현
    	  
    	  //&amp;lt;form method=&quot;post&quot; enctyle=&quot;multipart/form-data&quot;&amp;gt;태그의 역할을 해줌
    	  const form = new FormData();
    	  
    	  /*
    	  &amp;lt;form&amp;gt;
    	  	&amp;lt;input type=&quot;file&quot; name=&quot;file&quot;&amp;gt;
    	  &amp;lt;/form&amp;gt;
    	  */
    	  form.append(&quot;file&quot;, file);
    	  $.ajax({
    		 url : &quot;/uploadImage.do&quot;,
    		 type : &quot;post&quot;,//파일업로드를 하려면 반드시 post
    		 data : form,
    		 processData : false,
    		 contentType : false,
    		 success : function(data){
    			 //console.log(data); 이미지경로를 data로 받아옴
    			 $(editor).summernote(&quot;insertImage&quot;, data); //알아서 img태그로 집어넣음
    			 //&amp;lt;p&amp;gt;&amp;lt;img style=&quot;width: 740.99px;&quot; src=&quot;/upload/editor/flower11.png&quot;&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;기절&amp;lt;/p&amp;gt;
    			 //데이터베이스의 본문에 위형식으로 들어감 -&amp;gt; 태그가 포함되므로 본문데이터를 넉넉하게 주어야함
    		 }
    	  });
    	  //자바에서 ajax가 데이터를 받을 땐 기본적으로 문자열로 전송받음
    	  //processData : 전송하는 데이터를 기본적으로 문자열로 전송 
    	  //              -&amp;gt; 파일전송을 위해서 기본값인 문자열전송을 제거
    	  //contentType : enctype=&quot;application/x-www-form-urlencoded;charset=UTF-8&quot;
    	  //		      -&amp;gt; 파일 전송을 위해서 encType 기본값을 제거
    	  //이 두 설정이 빠지면 ajax로 파일업로드가 불가능하다
      }
   &amp;lt;/script&amp;gt;
	&amp;lt;%@include file=&quot;/WEB-INF/views/common/footer.jsp&quot; %&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 upload를 위한 서블릿&lt;/p&gt;
&lt;pre id=&quot;code_1678885633205&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package kr.or.iei.notice.cotroller;

import java.io.IOException;
import java.io.PrintWriter;

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 com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;

/**
 * Servlet implementation class UploadImageServlet
 */
@WebServlet(name = &quot;UploadImage&quot;, urlPatterns = { &quot;/uploadImage.do&quot; })
public class UploadImageServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public UploadImageServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//1. 인코딩
		request.setCharacterEncoding(&quot;utf-8&quot;);
		//2. 값추출
		//2-1. 업로드경로
		String root = getServletContext().getRealPath(&quot;/&quot;);
		String saveDirectory = root+&quot;upload/editor&quot;;
		//2-2. 최대사이즈 지정
		int maxSize = 10*1024*1024;//10MB
		//2-3. request -&amp;gt; MutipartRequest로 변환(파일업로드가 될때)
		MultipartRequest mRequest = new MultipartRequest(request, saveDirectory, maxSize, &quot;utf-8&quot;, new DefaultFileRenamePolicy());
		String filepath = mRequest.getFilesystemName(&quot;file&quot;);
		//3. 비즈니스로직 - DB에 파일업로드를 하지 않으므로 로직없음
		//4. 결과처리
		//업로드된 파일경로를 되돌려주면 끝
		response.setCharacterEncoding(&quot;utf-8&quot;);//파일명이 한글일 수 도 있으므로
		PrintWriter out = response.getWriter();
		out.print(&quot;/upload/editor/&quot;+filepath);//이게 되돌아간다
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;git &lt;br /&gt;로컬저장소 &lt;br /&gt;&amp;nbsp;파일이&amp;nbsp;생기거나,&amp;nbsp;수정되거나,&amp;nbsp;삭제가&amp;nbsp;발생하면&amp;nbsp;저장여부알림이&amp;nbsp;뜸 &lt;br /&gt;github &lt;br /&gt;원격저장소 &lt;br /&gt;&lt;br /&gt;VCS(Version&amp;nbsp;Control&amp;nbsp;System) &lt;br /&gt;&lt;br /&gt;undo&amp;nbsp;commit&amp;nbsp;-&amp;gt;&amp;nbsp;커밋된걸&amp;nbsp;취소 &lt;br /&gt;Revert&amp;nbsp;-&amp;gt;&amp;nbsp;삭제된&amp;nbsp;파일&amp;nbsp;복구(안하는게&amp;nbsp;좋음) &lt;br /&gt;&lt;br /&gt;branch&amp;nbsp;-&amp;gt;&amp;nbsp;폴더를&amp;nbsp;복사한것과&amp;nbsp;비슷한상태&amp;nbsp;물리적으로&amp;nbsp;2개는&amp;nbsp;아님(git이&amp;nbsp;논리적으로&amp;nbsp;관리) &lt;br /&gt;원본폴더&amp;nbsp;-&amp;nbsp;main &lt;br /&gt;branch폴더&amp;nbsp;-&amp;nbsp;br1&amp;nbsp;-&amp;nbsp;br인&amp;nbsp;상태에서&amp;nbsp;생성수정삭제한&amp;nbsp;작업은&amp;nbsp;main에&amp;nbsp;영향을&amp;nbsp;미치지&amp;nbsp;안흠 &lt;br /&gt;&lt;br /&gt;서로&amp;nbsp;같은폴더에서&amp;nbsp;다른작업을&amp;nbsp;하다가&amp;nbsp;합치는&amp;nbsp;작업이&amp;nbsp;가능하다(merge) &lt;br /&gt;&lt;br /&gt;원본파일이&amp;nbsp;있는&amp;nbsp;상태에서&amp;nbsp;branch에서&amp;nbsp;사용하고&amp;nbsp;잘되엇을&amp;nbsp;때&amp;nbsp;merge &lt;br /&gt;&lt;br /&gt;다른컴퓨터랑&amp;nbsp;연동&amp;nbsp;:&amp;nbsp; &lt;br /&gt;1.&amp;nbsp;&amp;lt;&amp;gt;code에서&amp;nbsp;https&amp;nbsp;url을&amp;nbsp;따옴 &lt;br /&gt;2.&amp;nbsp;clone&amp;nbsp;a&amp;nbsp;repository&amp;nbsp;의&amp;nbsp;URL에&amp;nbsp;url입력&amp;nbsp;후&amp;nbsp;경로&amp;nbsp;잡아주고&amp;nbsp;생성 &lt;br /&gt;3.&amp;nbsp;2번째&amp;nbsp;피시에서&amp;nbsp;작업하고&amp;nbsp;push로&amp;nbsp;깃에&amp;nbsp;올리고 &lt;br /&gt;4.&amp;nbsp;1번째&amp;nbsp;피시에서&amp;nbsp;2피시작업물을&amp;nbsp;받을때는&amp;nbsp;pull로&amp;nbsp;받음&amp;nbsp; &lt;br /&gt;&lt;br /&gt;혼자&amp;nbsp;git사용시&amp;nbsp;문제가&amp;nbsp;별로&amp;nbsp;없는이유 &lt;br /&gt;1.&amp;nbsp;개발환경이&amp;nbsp;크게&amp;nbsp;다르지않음 &lt;br /&gt;2.&amp;nbsp;동시에&amp;nbsp;작업하는&amp;nbsp;일이&amp;nbsp;없음 &lt;br /&gt;&amp;nbsp;-&amp;nbsp;동시에&amp;nbsp;작업&amp;nbsp;시&amp;nbsp;수정파일이&amp;nbsp;같은데&amp;nbsp;push가&amp;nbsp;동시에&amp;nbsp;들어가게되면,&amp;nbsp;에러발생(git충돌) &lt;br /&gt;&lt;br /&gt;- 팀GIT 작업순서1.&amp;nbsp;pull&amp;nbsp;[ctrl&amp;nbsp;+&amp;nbsp;&amp;nbsp;shift&amp;nbsp;+&amp;nbsp;p] &lt;br /&gt;2.&amp;nbsp;개인&amp;nbsp;작업&amp;nbsp;브랜치&amp;nbsp;생성 &lt;br /&gt;3.&amp;nbsp;개발작업&amp;nbsp;(작업중인&amp;nbsp;브랜치명은&amp;nbsp;이클립스&amp;nbsp;프로젝트&amp;nbsp;폴더명&amp;nbsp;우측에서&amp;nbsp;확인) &lt;br /&gt;4.&amp;nbsp;개발&amp;nbsp;완료&amp;nbsp;후&amp;nbsp;commit&amp;nbsp;(개인&amp;nbsp;브랜치) &lt;br /&gt;5.&amp;nbsp;master&amp;nbsp;branch로&amp;nbsp;변경6-1&amp;nbsp;master&amp;nbsp;branch에서&amp;nbsp;변경사항이&amp;nbsp;없는경우 &lt;br /&gt;&amp;nbsp;-&amp;gt;&amp;nbsp;개인&amp;nbsp;브랜치&amp;nbsp;merge &lt;br /&gt;&amp;nbsp;-&amp;gt;&amp;nbsp;후&amp;nbsp;변경사항&amp;nbsp;매인에서&amp;nbsp;push &lt;br /&gt;6-2&amp;nbsp;master&amp;nbsp;branch에서&amp;nbsp;변경사항이&amp;nbsp;있는경우. &lt;br /&gt;&amp;nbsp;-&amp;gt;&amp;nbsp;개인&amp;nbsp;브랜치로&amp;nbsp;변경 &lt;br /&gt;&amp;nbsp;-&amp;gt;&amp;nbsp;개인&amp;nbsp;브랜치에서&amp;nbsp;메인브랜치&amp;nbsp;변경사항&amp;nbsp;merge; &lt;br /&gt;6-2-1&amp;nbsp;충돌이&amp;nbsp;없는경우 &lt;br /&gt;&amp;nbsp;-&amp;gt;&amp;nbsp;master&amp;nbsp;branch에서&amp;nbsp;개인브랜치&amp;nbsp;merge; &lt;br /&gt;&amp;nbsp;-&amp;gt;&amp;nbsp;merge&amp;nbsp;후&amp;nbsp;push&amp;nbsp;(master&amp;nbsp;branch에서); &lt;br /&gt;6-2-2&amp;nbsp;충돌&amp;nbsp;있는경우 &lt;br /&gt;&amp;nbsp;-&amp;gt;&amp;nbsp;개인&amp;nbsp;브랜치에서&amp;nbsp;충돌이&amp;nbsp;발생 &lt;br /&gt;&amp;nbsp;-&amp;gt;&amp;nbsp;충돌&amp;nbsp;해결... &lt;br /&gt;7.&amp;nbsp;6과정&amp;nbsp;종료&amp;nbsp;후&amp;nbsp;5번부터&amp;nbsp;다시&amp;nbsp;개발&amp;nbsp;시작.&lt;/p&gt;</description>
      <category>국비수업/Server</category>
      <author>_HYE_</author>
      <guid isPermaLink="true">https://recordev.tistory.com/65</guid>
      <comments>https://recordev.tistory.com/65#entry65comment</comments>
      <pubDate>Thu, 23 Feb 2023 14:34:20 +0900</pubDate>
    </item>
  </channel>
</rss>