공부의 기록/자바 풀 스택 : 수업내용정리

자바 풀 스택 1/13 오전 기록 036-1

파티피플지선 2025. 1. 13. 13:10

9:15 경 학원 도착

 

 

<9:30 1교시>

 

지난주에 했던거 코딩 엉망이었네, 다시 코딩한거 올림

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <p>p1</p>
    <p>p2</p>
    <p>p3</p>
    <p>p4</p>
    <p>p5</p>
    <button id="changeBtn">change</button>
    <button id="changeBtn2">change2</button>
    <script>
        //위 버튼을 눌렀을 때 모든 p 요소의 innerText를 Changed!로 변경
        document.querySelector("#changeBtn").addEventListener("click", ()=>{
            //모든 p 요소의 참조값을 배열에 담긴체로 리턴받기
            const ps= document.querySelectorAll("p");
            for(let i=0; i<ps.length; i++){
                ps[i].innerText="Changed";
            }
        });
    </script>
    <!-- jquery 로딩 하기-->
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
    <script>
     $("#changeBtn2").on("click", ()=>{
        $("p").text("changed");
    });
    </script>

</body>
</html>

 

 

 

 

 

$( 선택자 ) 의 의미

문자열로 선택자(selector)를 전달하면 해당 문서 객체가 모두 찾아져서 jquery의 기능이 추가된 아주 특별한 [ ] 배열에 담긴 채로 리턴됨.

 

그래서 $(선택자).동작().동작() 이런식으로 작성을 하게 되면 전달된 선택자 모두에 대해 행동이 진행됨.

연속적으로 진행될 수 있는 이유는 선택자.동작.동작.동작을 할 수 있는 이유는 함수를 호출한 위치도 jquery가 적용된 독특한 배열이 계속 리턴되기 때문.

 

$("p").text("hi").css("color", "red")

라는 명령어에 대해서 살펴볼 때

$("p")는 모든 p 요소를 담은, jquery가 적용된 배열을 리턴

$("p").text("hi")는 모든 p요소의 innertext를 hi로 바꾼 모든 p요소를 담은, jquery가 적용된 배열을 리턴

$("p").text("hi").css("color", "red")는 모든 p요소의 innertext를 빨간색 글씨로 바꾼 모든 p요소를 담은, jquery 가 적용된 배열을 리턴

 

그래서 연속된 동작을 작성하는 게 가능하다!!

 

단, jquery로 선택자를 전달해서 id나 class가 없는 특정 방에 있는 요소만 .동작으로 변경하는 것은 불가능하다.

 

$("p")[0].text("hello")라는 동작은 불가.(왜냐하면 $("p")[0]이 전달하는게 그 p요소의 html 한 줄임)

$("p")[0].innerText="hello"; 형태로 작성해야 변경 가능.

 

 

$("p").first().text("hi")

첫번째 p요소만 변경된다.

 

+ .동작의 결과값이 무엇을 리턴해주냐에 따라 연속된 .동작이 불가능해질 수 있음.

 

예를 들어 .동작의 결과가 jquery 기능이 합쳐진 배열이 아닌 다른 값을 리턴하는 상황이면 그 이후에 .동작을 적용할 수 없음 ( val() 동작은 선택된 선택자의 값을 읽어와서 리턴하기 때문에 이 이후로 jquery의 특별한 배열이 아니기 때문에 추가 동작을 작성할 수가 없다)

 

let b= $("p").val("hello")

에서 b에 리턴되는 값은 jquery 기능이 합쳐진 배열이다.

let a= $("p").val()

에서 a에 리턴되는 값은 읽어온 문자열이다.

 

 

$("p").first().text()

를 입력하면 innerText를 읽어와서 문자열을 리턴한다.

같은 동작이지만 값을 전달하며 동작하느냐 동작만 하느냐에 따라 리턴하는 값이 달라서,

jquery 배열을 리턴하는지 문자열을 리턴하는지에 따라 이후 동작 가능 여부가 달라진다.

 

새로운 요소를 추가하고 싶으면 $( <만들고싶은요소선택자>)를 추가하면 만들어진다.

콘솔창에서 새로운 요소를 추가해서 만들면 페이지에는 나타나진 않지만 메모리상에만 존재한다. 

이메모리 상에 존재하는 애를 html에 추가하고 싶으면 

$("만들고싶은요소선택자").text("새로운요소").appendTo("body")하면 body의 자식요소로 들어감.

 

 

 

<10:30 2교시>

추가 버튼을 누르면 리스트가 추가되는 페이지 만들기

후후 개쩔어버렸다...ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

 

 

 $("#addBtn").on("이벤트명", 콜백함수()=>{})

 

 

이클립스로 넘어감

지난 시간에 했던 쿠키 이어서

 

서버가 클라이언트 웹브라우저에  저장시켜놓는 정보는 local storage 말고, session storage, indexedDB, Cookies 등을  이용해서 저장할 수 있다. local storage를 많이 쓴다. 

 

쿠키가 심어지면 클라이언트가 동작을 추가로 하지 않아도 쿠키를 읽어옴.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<div class="container">
		<h1>쿠키테스트</h1>
		<p>
			클라이언트의 웹브라우저에 특정 key 값으로 문자열을 저장할 수 있다.
			저장할 수 있는 문자열은 Base64인코딩 형식의 64가지 문자열을 저장할 수 있다. 
		</p>
		<form action="cookie_save.jsp" method="post">
			<label for="msg">웹브라우저(client side)에 저장할 문자열</label>
			<input type="text" name="msg" id="msg" />
			<button type="submit">저장</button>
			
		</form>
	</div>
</body>
</html>

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
	//HttpServletRequest 객체를 이용해서 요청과 함께 전달된 쿠키 읽어내기
	Cookie[] cooks = request.getCookies();
	//반복문 돌면서
	for(Cookie tmp:cooks){
		//쿠키의 키값을 읽어온다.
		String key=tmp.getName();
		//해당 키값으로 저장된 value 값을 읽어온다.
		String value=tmp.getValue();
		
		System.out.println("key: "+key+"value: "+value);
	}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<div class="container">
		<h1>저장된 쿠키 목록</h1>
		<table>
			<thead>
				<th>key</th>
			 	<th>value</th>
			</thead>
			<tbody>
				<%for(Cookie tmp:cooks){%>
					<tr>
						<td><%=tmp.getName() %></td>
						<td><%=tmp.getValue() %></td>
					</tr>
				<% }%>
			</tbody>			
		</table>
		<a href="cookie_form.jsp">다시 테스트</a>
	</div>
</body>
</html>

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	//HttpServletRequest 객체를 이용해서 요청과 함께 전달된 쿠키 읽어내기
	Cookie[] cooks=request.getCookies();
	//"savedMsg"라는 키값으로저장된 문자열을 저장할 변수
	String savedMsg=null;
	for(Cookie tmp:cooks){
		String key=tmp.getName();
		//만일 우리가 찾는 키값이라면
		if(key.equals("savedMsg")){
			//해당 키값으로 저장된 value를 읽어온다.
			savedMsg=tmp.getValue();
		}
	}
%>


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<p>savedMsg라는 키값으로 저장된 문자열: <%= savedMsg %></p>
	<%--EL을 활용하면 아래와 같다 --%>
	
	<p>savedMsg라는 키값으로 저장된 문자열 : ${cookie.savedMsg.value}</p>
	<a href="cookie_form.jsp">다시 테스트</a>
	<br />
	<a href="cookie_delete.jsp">쿠키 삭제</a>
</body>
</html>

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	//폼 전송되는 문자열 읽어오기
	String msg=request.getParameter("msg");
	//1. 쿠키 객체 생성
	Cookie cookie=new Cookie("savedMsg", msg);
	//2. 쿠키 유지 시간 설정(초단위)
	cookie.setMaxAge(60);//60초로 테스트
	//3. 응답할 때 쿠키도 같이 응답하도록 HttpServletResponse를 객체에 담는다
	response.addCookie(cookie);
	//4. 응답할 때 쿠키가 자동으로 응답되고 클라이언트의 웹 브라우저에 저장된다.
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<p>웹 브라우저에 savedMsg라는 키값으로 "<%=msg %>"를 저장했습니다.</p>
	<a href="cookie_read.jsp">저장된 문자열 확인해보기</a>
	<br />
	<a href="cookie_read2.jsp">저장된 문자열 확인해보기2</a>
</body>
</html>

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<%
	
	//가상의 로그인 페이지
	String id=request.getParameter("id");
	String pwd=request.getParameter("pwd");
	//체크박스를 체크한 상태로 로그인 버튼을 누르면 null 이 아니다. (체크하지 않으면 null)
	String isSave=request.getParameter("isSave");
	if(isSave != null){
		//아이디 비밀번호를 쿠키로 응답하고 1주일 동안 유지되도록 한다.
		Cookie cook1=new Cookie("savedId", id);
		Cookie cook2=new Cookie("savedPwd", pwd);
		cook1.setMaxAge(60);
		cook2.setMaxAge(60);
		response.addCookie(cook1);
		response.addCookie(cook2);
	}else{
		//특정 키값으로 저장된 쿠키값 삭제하기 (value 에는 아무 값이나 넣어도 상관없다)
		Cookie cook1=new Cookie("savedId", "");
		Cookie cook2=new Cookie("savedPwd", null);
		cook1.setMaxAge(0);
		cook2.setMaxAge(0);
		response.addCookie(cook1);
		response.addCookie(cook2);
	}	
%>
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<p><%=id %>님 로그인 되었습니다</p>
	<a href="loginform.jsp">다시 테스트</a>
</body>
</html>

//지난시간까지의 백업 다시 함

 

 

오늘 새롭게 하는거 : 파일 업로드 기능

enctype이란 것이 새롭게 등장하는데, 왜냐하면 그냥 문자열이 아니고 파일의 확장자까지 전달해줘야 하기 때문에

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<%--
		[파일 업로드 폼 구성하는 방법]
		method="post"
		enctype="multipart/form-data"
		input type="file"
	 --%>
	 <div class="container">
	 	<h3>파일업로드 폼</h3>	
	 	<form action="file/upload" method="post" enctype="multipart/form-data">
	 		<input type="text" name= "title" placeholder="설명 입력..."/>
	 		<br />
	 		<input type="file" name="myfile" />
	 		<br />	 	
	 		<button type="submit">업로드</button>
	 	</form>
	 </div>
</body>
</html>

 

 

upload서블릿 만들러 가서

package test.servlet;

import java.io.IOException;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@WebServlet("/file/upload")
public class UploadServlet extends HttpServlet{
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
	}
}

doPost 메소드를 오버라이드

 

 

<11:30 3교시>

웹앱에 빈 폴더 upload를 만들어 놓고, 여기에 인터넷 페이지에서 업로드 된 파일들을 저장할 예정이다.

 

package test.servlet;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.MultipartConfig;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Part;
@WebServlet("/file/upload")
@MultipartConfig(
		fileSizeThreshold = 1024*1024*5,//메모리 임계값 (메모리를 효율적으로 쓰기 위한 값, 이 값을 넘어가면 파일로 전환함)
		maxFileSize=1024*1024*50, //최대 파일 사이즈 1킬로바이트(=1024바이트)*1킬로바이트*50 =50메가 바이트
		maxRequestSize=1024*1024*60//최대 요청 사이즈 
		)
public class UploadServlet extends HttpServlet{
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//업로드될 실제 경로 얻어내기
		String uploadPath=getServletContext().getRealPath("/upload");
		File uploadDir=new File(uploadPath);
		//만일 upload 폴더가 존재하지 않으면
		if(!uploadDir.exists()) {
			uploadDir.mkdir();//실제로 폴더 만들기
		}
		
		String title=req.getParameter("title");
		//파일 데이터 처리는 좀 다르다
		Part filePart = req.getPart("myfile");
		if(filePart !=null) {
			//파일 이름 얻어내기
			String fileName=filePart.getSubmittedFileName();
			//저장할 파일의 경로 구성
			String filePath=uploadPath+File.separator+ fileName;
			//파일 저장
			InputStream is=filePart.getInputStream();
			Files.copy(is, Paths.get(filePath));
			System.out.println(fileName);
		}
		System.out.println(title);
		
		
		//jsp 페이지로 응답을 위임하기(리다이렉트는 컨텍스트 경로가 필요하지만 포워드 이동은 필요 없다)
		RequestDispatcher rd=req.getRequestDispatcher("/file/upload.jsp");
		rd.forward(req, resp);
	}
	
}

 

 

MultipartConfig() 소괄호 안에서 Ctrl 스페이스 눌러서 작성

 

파일을 저장했을 때 원본파일명과 추가로 중복 저장된 파일명을 관리해주는 폴더가 따로 필요하다.

그렇게 하면 똑같은 파일을 여러번 올려도 에러가 나지 않는다.

 

package test.servlet;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.UUID;

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.MultipartConfig;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Part;
@WebServlet("/file/upload")
@MultipartConfig(
		fileSizeThreshold = 1024*1024*5,//메모리 임계값 (메모리를 효율적으로 쓰기 위한 값, 이 값을 넘어가면 파일로 전환함)
		maxFileSize=1024*1024*50, //최대 파일 사이즈 1킬로바이트(=1024바이트)*1킬로바이트*50 =50메가 바이트
		maxRequestSize=1024*1024*60//최대 요청 사이즈 
		)
public class UploadServlet extends HttpServlet{
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//업로드될 실제 경로 얻어내기
		String uploadPath=getServletContext().getRealPath("/upload");
		File uploadDir=new File(uploadPath);
		//만일 upload 폴더가 존재하지 않으면
		if(!uploadDir.exists()) {
			uploadDir.mkdir();//실제로 폴더 만들기
		}
		
		String title=req.getParameter("title");
		
		//파일명이 겹치지 않게 저장하기 위한 랜덤한 문자열을 얻어내기
		String uid=UUID.randomUUID().toString();
		System.out.println(uid);
		String origFileName=null;
		String saveFileName=null;
		
		//파일 데이터 처리는 좀 다르다
		Part filePart = req.getPart("myfile");
		if(filePart !=null) {
			//파일 이름 얻어내기
			origFileName=filePart.getSubmittedFileName();
			//저장될 파일의 이름 구성하기
			saveFileName=uid+origFileName;
			//저장할 파일의 경로 구성
			String filePath=uploadPath+File.separator+ saveFileName;
			//파일 저장
			InputStream is=filePart.getInputStream();
			Files.copy(is, Paths.get(filePath));
		}
		
		//파일의 크기 얻어내기(큰 정수이기 때문에 long type 사용)
		long fileSize=filePart.getSize();
		
		
		//jsp 페이지로 응답을 위임하기(리다이렉트는 컨텍스트 경로가 필요하지만 포워드 이동은 필요 없다)
		RequestDispatcher rd=req.getRequestDispatcher("/file/upload.jsp");
		rd.forward(req, resp);
	}
	
}

 

 

File 클래스의 separator 값을 이용해야 리눅스 환경인지 윈도우 환경인지에 관계 없이 슬래시 역슬래시가 알아서 구분되어서 나옴.(리눅스에서는 슬래시, 윈도우에서는 역슬래시)

 

 

 

<12:30 4교시>

upload 폴더에다 저장하려고 했는데 이클립스 워크스페이스 안의 upload 폴더에는 저장이 안되었다.

이것은 업로드했던 파일들이 metadata 폴더안에서 생성된 upload된 것을 볼 수 있다.

 

 

이 코딩 때문에 독특한 자료의 form인데도 크게 방식이 다르지 않게 get 해올 수 있다.

 

3교시 때 한거 여기다 다시 백업

 

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<div class="container">
		<h1>인덱스 페이지</h1>
		<ul>
			<li><a href="test_cookie/cookie_form.jsp">쿠키 테스트</a></li>
			<li><a href="file/upload_form.jsp">파일 업로드 테스트</a></li>
		</ul>
	</div>
</body>
</html>

 

 

uploadform.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<%--
		[파일 업로드 폼 구성하는 방법]
		method="post"
		enctype="multipart/form-data"
		input type="file"
	 --%>
	 <div class="container">
	 	<h3>파일업로드 폼</h3>	
	 	<form action="${pageContext.request.contextPath}/file/upload" method="post" enctype="multipart/form-data">
	 		<input type="text" name= "title" placeholder="설명 입력..."/>
	 		<br />
	 		<input type="file" name="myfile" />
	 		<br />	 	
	 		<button type="submit">업로드</button>
	 	</form>
	 </div>
</body>
</html>

 

 

uploadservlet.java

package test.servlet;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.UUID;

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.MultipartConfig;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Part;
@WebServlet("/file/upload")
@MultipartConfig(
		fileSizeThreshold = 1024*1024*5,//메모리 임계값 (메모리를 효율적으로 쓰기 위한 값, 이 값을 넘어가면 파일로 전환함)
		maxFileSize=1024*1024*50, //최대 파일 사이즈 1킬로바이트(=1024바이트)*1킬로바이트*50 =50메가 바이트
		maxRequestSize=1024*1024*60//최대 요청 사이즈 
		)
public class UploadServlet extends HttpServlet{
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//업로드될 실제 경로 얻어내기
		String uploadPath=getServletContext().getRealPath("/upload");
		File uploadDir=new File(uploadPath);
		//만일 upload 폴더가 존재하지 않으면
		if(!uploadDir.exists()) {
			uploadDir.mkdir();//실제로 폴더 만들기
		}
		
		String title=req.getParameter("title");
		
		//파일명이 겹치지 않게 저장하기 위한 랜덤한 문자열을 얻어내기
		String uid=UUID.randomUUID().toString();
		System.out.println(uid);
		String origFileName=null;
		String saveFileName=null;
		
		//파일 데이터 처리는 좀 다르다
		Part filePart = req.getPart("myfile");
		if(filePart !=null) {
			//파일 이름 얻어내기
			origFileName=filePart.getSubmittedFileName();
			//저장될 파일의 이름 구성하기
			saveFileName=uid+origFileName;
			//저장할 파일의 경로 구성
			String filePath=uploadPath+File.separator+ saveFileName;
            /*
             *업로드된 파일은 임시 폴더에 임시 파일로 저장된다.
             *해당 파일에서 byte 알갱이들을 읽어들일 수 있는 InputStream객체를 얻어내어
              */
			//파일 저장
			InputStream is=filePart.getInputStream();
            //원하는 목적지에 copy 해야한다.
			Files.copy(is, Paths.get(filePath));
		}
		
		//파일의 크기 얻어내기(큰 정수이기 때문에 long type 사용)
		long fileSize=filePart.getSize();
		
		//응답에 필요한 데이터를 request 영역에 담기
		req.setAttribute("title", title);
		req.setAttribute("origFileName", origFileName);
		req.setAttribute("saveFileName",saveFileName );
		req.setAttribute("fileSize", fileSize);
		req.setAttribute("uploadPath", uploadPath);
		//나중에 이걸 리눅스에 올릴 때 uploadPath 확인할 필요가 있어서
		
		//jsp 페이지로 응답을 위임하기(리다이렉트는 컨텍스트 경로가 필요하지만 포워드 이동은 필요 없다)
		RequestDispatcher rd=req.getRequestDispatcher("/file/upload.jsp");
		rd.forward(req, resp);
	}
	
}

 

 

upload.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<div class="container">
		<h1>업로드 결과 페이지</h1>
		<p>파일을 업로드했습니다.</p>
		<p>title : <strong> ${requestScope.title }</strong></p>
		<p>origFileName: <strong>${origFileName}</strong></p>
		<p>saveFileName: <strong>${saveFileName}</strong></p>
		<p>fileSize : <strong>${fileSize}</strong></p>
		<p>uploadPah: <strong>${uploadPath}</strong></p>
	</div>
</body>
</html>

 

 

백업한거 종이에 손코딩 중