Problem solving/쉽게 배우는 JSP 웹 프로그래밍

[쉽게 배우는 JSP 웹 프로그래밍] 8장 연습문제

공부좀하시졍 2020. 10. 21. 03:39

2020/10/21 - [Problem solving/쉽게 배우는 JSP 웹 프로그래밍] - [쉽게 배우는 JSP 웹 프로그래밍] 7장 연습문제

1. 유효성 검사란 무엇인가?

유효성 검사는 사용자가 폼 페이지에서 입력한 데이터 값이 서버로 전송되기 전에 특정 규칙에 맞게 입력되었는지 검증하는 것을 말한다.

 

2. 유효성 검사를 위한 두 가지 처리 기법을 간단히 설명하시오.

기본 유효성 검사는 사용자가 폼 페이지의 입력 항목에 입력한 데이터 값이 있는지 없는지 확인하고 데이터 길이, 숫자 등 기본적인 것이 맞는지 검사한다.

데이터 형식 유효성 검사는 사용자가 폼 페이지의 입력 항목에 입력한 데이터 값이 특정 형태에 적합한지 검사하기 위해 정규 표현식을 사용하는 방법으로 기본 유효성 검사보다 복잡하다.

 

3. 유효성 검사를 위한 핸들러 함수와 폼 페이지를 작성하는 기법을 설명하시오.

1) input 태그의 type 속성 값이 submit인 경우 onclick 속성을 이용하여 핸들러 함수를 설정 또는 form태그의 onsubmit 속성 값에 설정한다.

2) 자바스크립트를 이용하여 <script>..</script> 내에 핸들러 함수를 작성한다.

3) 폼 페이지에서 입력된 데이터 값을 핸들러 함수로 가져오기 위해 form 태그의 name 속성 또는 forms 객체를 이용한다.

<script type="text/javascript">
function 핸들러 함수(){
    var str = document.폼 이름.입력항목 이름.value;
	...
}

<form name="폼 이름">
    ...
    <input type="submit" onclick="핸들러 함수()">
</form>

4. 비밀번호가 아이디를 포함하지 않도록 다음 조건에 맞게 JSP 애플리케이션을 만들고 실행 결과를 확인하시오.

validation01.jsp

<%@ page contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>Validation</title>
</head>
<script type="text/javascript">
	function checkLogin() {
		var form = document.loginForm;
		if (form.id.value == "") {
			alert("아이디를 입력해주세요.");
			form.id.focus();
			return false;
		} else if (form.passwd.value == "") {
			alert("비밀번호를 입력해주세요");
			form.passwd.focus();
			return false;
		} else if (form.passwd.value.indexOf(form.id.value) != -1) {
			alert("비밀번호는 ID를 포함할 수 없습니다.");
			form.passwd.focus();
			return false;
		}
		form.submit();
	}
</script>
<body>
	<form name="loginForm" action="validation_process.jsp" method="post">
		<p> 아 이 디 : <input type="text" name="id">
		<p> 비밀번호 : <input type="text" name="passwd">
		<p> <input type="button" value="전송" onclick="checkLogin()">
	</form>
</body>
</html>

validation_process.jsp

<%@ page contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>Validation</title>
</head>
<body>
	<h3>입력에 성공했습니다!</h3>
	<%
		request.setCharacterEncoding("utf-8");
		String id = request.getParameter("id");
		String passwd = request.getParameter("passwd");
	%>
	<p> 아이디 : <%=id %>
	<p> 비밀번호: <%=passwd %>
</body>
</html>

 

5. 비밀번호로 동일한 영문이나 숫자를 3개 이상 사용하지 않도록 다음 조건에 맞게 JSP 애플리케이션을 만들고 실행 결과를 확인하시오.

validation02.jsp

<%@ page contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>Validation</title>
</head>
<script type="text/javascript">
	function checkLogin() {
		var form = document.loginForm; 
		var passwd = form.passwd.value;
		var passwdCheck = form.passwdCheck.value;
		
		if (/(\w)\1\1/.test(passwd)) {
			alert("영문, 숫자는 3자 이상 연속 입력할 수 없습니다.");
			form.passwd.focus();
			return false;
		}  else if (passwd != passwdCheck) {
			alert("비밀번호를 다시 확인해주세요!");
			form.passwdCheck.focus();
			return false;
		}
		form.submit();
	}
</script>
<body>
	<form name="loginForm" method="post">
		<p> 아 이 디 : <input type="text" name="id">
		<p> 비밀번호 : <input type="text" name="passwd">
		<p> 비밀번호 확인 : <input type="text" name="passwdCheck">
		<p> <input type="button" value="전송" onclick="checkLogin()">
	</form>
</body>
</html>

 

6. 비밀번호가 영문, 숫자, 특수기호를 조합한 8자 이상이 되도록 다음 조건에 맞게 JSP 애플리케이션을 만들고 실행 결과를 확인하시오.

validation03.jsp

<%@ page contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>Validation</title>
</head>
<script type="text/javascript">
	function checkLogin() {
		var form = document.loginForm; 
		var passwd = form.passwd.value;
		var passwdCheck = form.passwdCheck.value;
		var regExpPasswd = /^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,}$/;
		
		if (!regExpPasswd.test(passwd)) {
			alert("영문+숫자+특수기호 8자리 이상으로 구성하여야 합니다.");
			form.passwd.focus();
			return false;
		}  else if (passwd != passwdCheck) {
			alert("비밀번호를 다시 확인해주세요!");
			form.passwdCheck.focus();
			return false;
		}
		form.submit();
	}
</script>
<body>
	<form name="loginForm" method="post">
		<p> 아 이 디 : <input type="text" name="id">
		<p> 비밀번호 : <input type="text" name="passwd">
		<p> 비밀번호 확인 : <input type="text" name="passwdCheck">
		<p> <input type="button" value="전송" onclick="checkLogin()">
	</form>
</body>
</html>

 

7. 다음 조건에 맞게 도서 웹 쇼핑몰을 위한 웹 애플리케이션을 만들고 실행 결과를 확인하시오.

BookRepository.java

package dao;

import java.util.ArrayList;
import dto.Book;

public class BookRepository {
	private ArrayList<Book> listOfBooks = new ArrayList<Book>();
	private static BookRepository instance = new BookRepository();
	
	public static BookRepository getInstance() {
		return instance;
	}
	
	public BookRepository() {
		Book book1 = new Book("B1234", "HTML5+CSS3", 15000);
		book1.setAuthor("황재호");
		book1.setDescription("워드나 PPT 문서를 만들 수 있나요? 그러면 문제 없습니다. 지금 바로 웹페이지 제작에 도전해보세요. 지금 당장 컴퓨터가 없어도 괜찮습니다. 코드와 실행 화면이 바로 보여서 눈으로만 읽어도 어떻게 작동하는지 쉽게 파악할 수 있는 것은 기본이고, 중간중간 퀴즈를 추가하여 재미있게 게임하듯 복습할 수 있다. 또한 이제 막 입문하여 도움을 구할 곳이 없는 분들을 고려하여, 궁금해할 내용을 알아서 질문하고, 팁으로 친절하게 답해준다. 각 장의 끝에는 앞에서 배운 내용을 자연스럽게 복습할 수 있는 프로젝트도 있다.");
		book1.setPublisher("한빛미디어");
		book1.setCategory("Hello Coding");
		book1.setUnitsInStock(1000);
		book1.setTotalPages(365);
		book1.setReleaseDate("05/2019");
		book1.setCondition("E-Book");
		book1.setFilename("B1234.png");
		
		Book book2 = new Book("B1235", "쉽게 배우는 자바 프로그래밍", 27000);
		book2.setAuthor("우종중");
		book2.setDescription("객체 지향의 핵심과 자바의 현대적 기능을 충실히 다루면서도 초보자가 쉽게 학습할 수 있게 구성했습니다. 시각화 도구를 활용한  개념 설명과 군더더기 없는 핵심 코드를 통해 개념과 구현을 한 흐름으로 학습할 수 있습니다. 또한 ‘기초 체력을 다지는 예제 → 셀프 테스트 → 생각을 논리적으로 정리하며 한 단계씩 풀어 가는 도전 과제 → 스토리가 가미된 흥미로운 프로그래밍 문제’ 등을 통해 프로그래밍 실력을 차근차근 끌어올릴 수 있습니다.");
		book2.setPublisher("한빛미디어");
		book2.setCategory("IT모바일");
		book2.setUnitsInStock(1000);
		book2.setTotalPages(692);
		book2.setReleaseDate("08/2017");
		book2.setCondition("New");
		book2.setFilename("B1235.png");
		
		Book book3 = new Book("B1236", "스프링4 입문", 27000);
		book3.setAuthor("하세가와 유이치, 오오노 와타루, 토키 코헤이(권은철, 전민수)");
		book3.setDescription("스프링은 단순히 사용 방법만 익히는 것보다 아키텍처를 어떻게 이해하고 설계하는지가 더 중요합니다. 예제를 복사해 붙여넣는식으로는 실제 개발에서 스프링을 제대로 활용할 수 없습니다. 이 책에서는 웹 애플리케이션의 기초를 다지고 스프링 코어를 살펴보며 클라우드 네이티브 입문까지 다룹니다. 이제 막 실무에 뛰어든 웹 애플리케이션 초급자나 개발 경험은 있지만 스프링은 사용해본 적 없는 분을 대상으로 가능한 한 쉽게 설명합니다. ");
		book3.setPublisher("한빛미디어");
		book3.setCategory("IT모바일");
		book3.setUnitsInStock(1000);
		book3.setTotalPages(520);
		book3.setReleaseDate("11/2017");
		book3.setCondition("Old");
		book3.setFilename("B1236.png");
		
		listOfBooks.add(book1);
		listOfBooks.add(book2);
		listOfBooks.add(book3);
	}
	
	public ArrayList<Book> getAllBooks() {
		return listOfBooks;
	}
	
	public Book getBookById(String bookId) {
		Book bookById = null;
		
		for (int i = 0; i < listOfBooks.size(); i++) {
			Book book = listOfBooks.get(i);
			if (book != null && book.getBookId() != null && book.getBookId().contentEquals(bookId)) {
				bookById = book;
				break;
			}
		}
		return bookById;
	}
	
	public void addBook(Book book) {
		listOfBooks.add(book);
	}
}

Book.java

package dto;

public class Book {
	private String bookId; //도서 아이디
	private String name; //도서명
	private Integer unitPrice; //가격
	private String author; //저자
	private String description; //설명
	private String publisher; //출판사
	private String category; //분류
	private long unitsInStock; //재고 수
	private long totalPages; //페이지 수
	private String releaseDate; //출판일(월/년)
	private String condition; //신규 도서 or 중고 도서 or E-book
	private String filename; //이미지 파일명
	
	public Book() {
		super();
	}

	public Book(String bookId, String name, Integer unitPrice) {
		this.bookId = bookId;
		this.name = name;
		this.unitPrice = unitPrice;
	}

	public String getBookId() {
		return bookId;
	}

	public void setBookId(String bookId) {
		this.bookId = bookId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getUnitPrice() {
		return unitPrice;
	}

	public void setUnitPrice(Integer unitPrice) {
		this.unitPrice = unitPrice;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public String getPublisher() {
		return publisher;
	}

	public void setPublisher(String publisher) {
		this.publisher = publisher;
	}

	public String getCategory() {
		return category;
	}

	public void setCategory(String category) {
		this.category = category;
	}

	public long getUnitsInStock() {
		return unitsInStock;
	}

	public void setUnitsInStock(long unitsInStock) {
		this.unitsInStock = unitsInStock;
	}

	public long getTotalPages() {
		return totalPages;
	}

	public void setTotalPages(long totalPages) {
		this.totalPages = totalPages;
	}

	public String getReleaseDate() {
		return releaseDate;
	}

	public void setReleaseDate(String releaseDate) {
		this.releaseDate = releaseDate;
	}

	public String getCondition() {
		return condition;
	}

	public void setCondition(String condition) {
		this.condition = condition;
	}
	
	public String getFilename() {
		return filename;
	}
	
	public void setFilename(String filename) {
		this.filename = filename;
	}
	
}

addBook.jsp

<%@ page contentType="text/html; charset=utf-8"%>
<html>
<head>
<link rel = "stylesheet" href = "./resources/css/bootstrap.min.css" />
<script type="text/javascript" src="./resources/js/validation.js"></script>
<title>도서 등록</title>
</head>
<body>
	<jsp:include page="menu.jsp" />
	<div class="jumbotron">
		<div class="container">
			<h1 class="display-3">도서 등록</h1>
		</div>
	</div>
	<div class="container">
		<form name="newProduct" action="./processAddBook.jsp" class="form-horizontal" method="post" enctype="multipart/form-data">
			<div class="form-group row">
				<label class="col-sm-2">도서 코드</label>
				<div class="col-sm-3">
					<input type="text" id="bookId" name="bookId" class="form-control">
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">도서명</label>
				<div class="col-sm-3">
					<input type="text" id="name" name="name" class="form-control">
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">가격</label>
				<div class="col-sm-3">
					<input type="text" id="unitPrice" name="unitPrice" class="form-control" >
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">저자</label>
				<div class="col-sm-3">
					<input type="text" name="author" class="form-control" >
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">출판사</label>
				<div class="col-sm-3">
					<input type="text" name="publisher" class="form-control" >
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">출판일</label>
				<div class="col-sm-3">
					<input type="text" name="releaseDate" class="form-control" >
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">총페이지 수</label>
				<div class="col-sm-3">
					<input type="text" name="totalPages" class="form-control" >
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">상세정보</label>
				<div class="col-sm-7">
					<textarea name="description" cols="50" rows="2" class="form-control"></textarea>
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">분류</label>
				<div class="col-sm-3">
					<input type="text" name="category" class="form-control" >
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">재고수</label>
				<div class="col-sm-3">
					<input type="text" id="unitsInStock" name="unitsInStock" class="form-control" >
				</div>
			</div>
			<div class="form-group row">
				<label class="col-sm-2">상태</label>
				<div class="col-sm-5">
					<input type="radio" name="condition" value="NEW" > 신규도서
					<input type="radio" name="condition" value="Old" > 중고도서
					<input type="radio" name="condition" value="E-Book" > E-Book
				</div>
			</div>
				<div class="form-group row">
				<label class="col-sm-2">이미지</label>
				<div class="col-sm-5">
					<input type="file" name="bookImage" value="form-control" >
				</div>
			</div>
			<div class="form-group row">
				<div class="col-sm-offset-2 col-sm-10">
					<input type="button" class="btn btn-primary" value="등록" onclick="CheckAddBook()">
				</div>
			</div>
		</form>
	</div>
</body>
</html>

book.jsp

<%@ page contentType="text/html; charset=utf-8"%>
<%@ page import="dto.Book" %>
<%@ page import="dao.BookRepository" %>

<html>
<head>
<link rel = "stylesheet" href = "./resources/css/bootstrap.min.css" />
<title>도서 정보</title>
<style>
	.image {
 		float: left;
 	}
</style>
</head>
<body>
	<jsp:include page="menu.jsp" />
	<div class="jumbotron">
		<div class="container">
			<h1 class="display-3">도서 정보</h1>
		</div>
	</div>
	<%
		String id = request.getParameter("id");
		BookRepository dao = BookRepository.getInstance();
		Book book = dao.getBookById(id);
	%>
	<div class="container">
		<div class="image">
			<img src="./resources/images/<%=book.getFilename() %>" style="width: 100%"/>
		</div>
		<div class="row">
			<div class="col-md-10">
				<h3><%=book.getName() %></h3>
				<p><%=book.getDescription() %>
				<p> <b>도서 코드 : </b><span class="badge badge-danger">
					<%=book.getBookId() %></span>
					<p> <b>출판사</b> : <%=book.getPublisher() %>
					<p> <b>저자</b> : <%=book.getAuthor() %>
					<p> <b>재고 수</b> : <%=book.getUnitsInStock() %>
					<p> <b>총 페이지수</b> : <%=book.getTotalPages() %>
					<p> <b>출판일</b> : <%=book.getReleaseDate() %>
					<h4><%=book.getUnitPrice() %>원</h4>
					<p> <a href="#" class="btn btn-info"> 도서 주문 &raquo;</a>
					<a href="./books.jsp" class="btn btn-secondary"> 도서 목록&raquo;</a>
			</div>
		</div>
		<hr>
	</div>
	<jsp:include page="footer.jsp" />
</body>
</html>

books.jsp

<%@ page contentType="text/html; charset=utf-8"%>
<%@ page import="java.util.ArrayList" %>
<%@ page import="dto.Book" %>
<%@ page import="dao.BookRepository" %>

<html>
<head>
<link rel = "stylesheet" href = "./resources/css/bootstrap.min.css" />
<title>도서 목록</title>
<style>
	.txt_post {
		overflow: hidden;
    	text-overflow: ellipsis;
    	display: -webkit-box;
    	-webkit-line-clamp: 2; /* 라인수 */
    	-webkit-box-orient: vertical;
    	word-wrap:break-word; 
    	line-height: 1.2em;
    	height: 2.4em;
 	}
 	
 	.image {
 		float: left;
 		width: 20%;
 	}
 	.post {
 		display: inline-block;
 		width: 50%;
 	}
 	.button {
 		float: right;
 		width: 30%;
 	}
</style>
</head>
<body>
	<jsp:include page="menu.jsp" />
	<div class="jumbotron">
		<div class="container">
			<h1 class="display-3">도서 목록</h1>
		</div>
	</div>
	<%
		BookRepository dao = BookRepository.getInstance();
		ArrayList<Book> listOfBooks = dao.getAllBooks();

	%>
	<div class="container">
		<div class="row" align="left">
			<%
				for (int i = 0; i < listOfBooks.size();i++) {
					Book book = listOfBooks.get(i);
			%>
			<div>
				<div class="image">
					<img src="./resources/images/<%=book.getFilename() %>" style="width: 50%">
				</div>
				<div class="post" >
					<p><b>[<%=book.getCategory() %>]</b>
					<b><%=book.getName() %></b> </p>
					<p class="txt_post"><%=book.getDescription() %>
					<p><%=book.getAuthor() %>|<%=book.getPublisher() %>|<%=book.getUnitPrice() %>원
				</div>
				<div class="button">
					<a href="./book.jsp?id=<%=book.getBookId() %>"
						class="btn btn-secondary" role="button"> 상세 정보 &raquo;</a>
				</div>
				<hr>
			<%
				}
			%>
			</div>	
		</div>
	</div>
	<jsp:include page="footer.jsp" />
</body>
</html>

footer.jsp

<footer class="container">
	<p>&copy; BookMarket</p>
</footer>

menu.jsp

<nav class = "navbar navbar-expand navbar-dark bg-dark">
	<div class = "container">
		<div class = "navbar-header">
			<a class = "navbar-brand" href="./books.jsp">Home</a>
		</div>
	</div>
</nav>

processAddBook.jsp

<%@ page contentType="text/html; charset=utf-8"%>
<%@ page import="com.oreilly.servlet.*" %>
<%@ page import="com.oreilly.servlet.multipart.*" %>
<%@ page import="java.util.*" %>
<%@ page import="dto.Book"%>
<%@ page import="dao.BookRepository"%>

<%
	request.setCharacterEncoding("UTF-8");
	String filename = "";
	String realFolder = "C:\\upload"; //웹 애플리케이션상의 절대 경로
	int maxSize = 5 * 1024 * 1024; //최대 업로드될 파일의 크기 5MB
	String encType ="utf-8";

	MultipartRequest multi = new MultipartRequest(request, realFolder, maxSize, encType, new DefaultFileRenamePolicy());
	
	String bookId = multi.getParameter("bookId");
	String name = multi.getParameter("name");
	String unitPrice = multi.getParameter("unitPrice");
	String author = multi.getParameter("author");
	String description = multi.getParameter("description");
	String publisher = multi.getParameter("publisher");
	String category = multi.getParameter("category");
	String unitsInStock = multi.getParameter("unitsInStock");
	String totalPages = multi.getParameter("totalPages");
	String releaseDate = multi.getParameter("releaseDate");
	String condition = multi.getParameter("condition");
	
	Integer price;
	
	if (unitPrice.isEmpty())
		price = 0;
	else
		price = Integer.valueOf(unitPrice);
		
	long stock;
	
	if (unitsInStock.isEmpty())
		stock = 0;
	else 
		stock = Long.valueOf(unitsInStock);
	
	long pages;
	
	if (totalPages.isEmpty())
		pages = 0;
	else
		pages = Long.valueOf(totalPages);
	
	Enumeration files = multi.getFileNames();
	String fname = (String) files.nextElement();
	String fileName = multi.getFilesystemName(fname);
	
	BookRepository dao = BookRepository.getInstance();
	
	Book newBook = new Book();
	newBook.setBookId(bookId);
	newBook.setName(name);
	newBook.setUnitPrice(price);
	newBook.setAuthor(author);
	newBook.setDescription(description);
	newBook.setPublisher(publisher);
	newBook.setCategory(category);
	newBook.setUnitsInStock(stock);
	newBook.setTotalPages(pages);
	newBook.setReleaseDate(releaseDate);
	newBook.setCondition(condition);
	newBook.setFilename(fileName);
	
	dao.addBook(newBook);
	
	response.sendRedirect("books.jsp");
%>

welcome.jsp

<%@ page contentType="text/html; charset=utf-8" %>
<html>
<head>
<meta charset="EUC-KR">
<link rel = "stylesheet" href = "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<title>Welcome</title>
</head>
<body>
	<%@ include file="menu.jsp" %>
	<%! 
		String str1 = "도서 웹 쇼핑몰";
	%>
	
	<div class = "jumbotron">
		<div class = "container">
			<h1 class = "display-3">
				<b><%= str1 %></b>
			</h1>
		</div>
	</div>
	<%@ include file="footer.jsp" %>
	
</body>
</html>

validation.js

function CheckAddBook() {
	var bookId = document.getElementById("bookId");
	var name = document.getElementById("name");
	var unitPrice = document.getElementById("unitPrice");
	var unitsInStock = document.getElementById("unitsInStock");
	
	//상품 아이디 체크
	if (!check(/^ISBN[0-9]{4,11}$/, bookId, "[도서코드]\nISBN와 숫자를 조합하여 5~12자까지 입력하세요\n첫 글자는 반드시 ISBN으로 시작하세요"))
		return false;
	//상품명 체크
	if(name.value.length <4 || name.value.length > 12) {
		alert("[도서명]\n최소 4자에서 최대 12자까지 입력하세요");
		name.select();
		name.focus();
		return false;
	}
	//상품 가격 체크
	if (unitPrice.value.length == 0 || isNaN(unitPrice.value)) {
		alert("[가격]\n숫자만 입력하세요");
		unitPrice.select();
		unitPrice.focus();
		return false;
	}
	
	if (unitPrice.value < 0) {
		alert("[가격]\n음수는 입력할 수 없습니다");
		unitPrice.select();
		unitPrice.focus();
		return false;
	}
	
	//재고 수 체크
	if (isNaN(unitsInStock.value)) {
		alert("[재고 수]\n숫자만 입력하세요");
		unitsInStock.select();
		unitsInStock.focus();
		return false;
	}
	
	function check(regExp, e, msg) {
		if (regExp.test(e.value)) {
			return true;
		}
		alert(msg);
		e.select();
		e.focus();
		return false;
	}
	document.newBook.submit();
}

WebContent/resources 폴더 안에 css, images, js폴더를 만들어 각각 bootsrap.min.css, 업로드할 이미지, validation.js를 넣어주었다.