JSP 프로그램 예: 등록 및 로그인 양식

⚡ 스마트 요약

여기 JSP 프로그램 예제는 회원가입 양식, 로그인 및 로그아웃 양식, 양식 처리 페이지라는 세 가지 모듈을 구축하며, 각 모듈은 JSP 뷰를 서블릿 컨트롤러에 연결하여 초보자도 MVC 구조를 쉽게 이해할 수 있도록 합니다.

  • 🔘 등록 절차: Register_1.jsp는 6개의 필드를 수집하여 guru_register 서블릿으로 전송하고, 모든 필드가 채워진 경우에만 성공 페이지로 이동합니다.
  • ☑️ 로그인 및 로그아웃: Register_3.jsp는 자격 증명을 guru_login에 전송하고, Register_4.jsp는 사용자에게 인사를 건네고 로그아웃을 위해 로그인 페이지로 연결해 줍니다.
  • ✅ MVC 역할: JSP 페이지는 뷰 역할을 하고, 서블릿은 컨트롤러 역할을 하며, RequestDispatcher는 이들 사이에서 요청을 전달합니다.
  • 🧪 양식 처리: getParameter(), getParameterValues(), getParameterNames() 및 getInputStream() 메서드는 JSP 또는 서블릿 내부에서 제출된 데이터를 읽습니다.
  • 🛠️ GET 방식과 POST 방식 비교 GET은 인코딩된 값을 추가합니다. URL 또한 길이 제한이 있습니다. POST 요청은 요청 본문에 값을 전달하므로 비밀번호 전송에 적합합니다.
  • ⚠️ 버전 참고: 이 코드 목록은 javax.servlet을 가져오므로 Tomcat 9 이하 버전에서 실행됩니다. Tomcat 10 이상 버전에서는 jakarta.servlet 패키지가 필요합니다.

JSP 회원가입 및 로그인 폼 프로그램 예제

이 예제들은 JSP를 사용하여 샘플 프로그램을 개발하는 방법과 그 주변에 MVC 아키텍처를 구현하는 방법을 보여줍니다. 세 가지 모듈이 순서대로 구축됩니다.

  • 입학 등록 양식
  • 로그인 및 로그아웃 양식
  • JSP 양식

JSP에서 회원가입 양식을 만드는 방법

회원가입 양식에는 이름, 사용자 이름, 비밀번호, 주소, 연락처 등 모든 세부 정보를 입력하는 칸이 있습니다.

이 양식은 애플리케이션에 등록하는 데 도움이 됩니다. 사용자의 모든 정보를 입력받아 저장합니다. 데이터베이스 또는 캐시.

이 예시에서는 “Guru 등록 양식에는 다음과 같은 항목이 있습니다.

  1. 이름
  2. 성
  3. ID / Username
  4. 비밀번호
  5. 주소
  6. 전화 연락처

이 모든 세부 정보를 입력한 후에는 제출 버튼이 있습니다. 이 버튼을 클릭하면 모든 세부 정보가 서블릿으로 전송됩니다.

예 1: Register_1.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Guru Registration Form</title>
</head>
<body>
<h1>Guru Register Form</h1>
<form action="guru_register" method="post">
			<table style="with: 50%">
				<tr>
					<td>First Name</td>
					<td><input type="text" name="first_name" /></td>
				</tr>
				<tr>
					<td>Last Name</td>
					<td><input type="text" name="last_name" /></td>
				</tr>
				<tr>
					<td>UserName</td>
					<td><input type="text" name="username" /></td>
				</tr>
					<tr>
					<td>Password</td>
					<td><input type="password" name="password" /></td>
				</tr>
				<tr>
					<td>Address</td>
					<td><input type="text" name="address" /></td>
				</tr>
				<tr>
					<td>Contact No</td>
					<td><input type="text" name="contact" /></td>
				</tr></table>
			<input type="submit" value="Submit" /></form>
</body>
</html>

코드 설명:

Code 11 라인 : 여기서는 요청을 보낼 서블릿, 즉 액션을 지정하는 폼을 사용하고 있으며, 해당 서블릿의 이름은 guru_register.java입니다. 요청은 POST 메서드를 통해 처리됩니다.

Code 14-16행: 여기서는 입력 유형을 텍스트로, 이름을 first_name으로 설정합니다.

Code 18-20행: 여기서는 입력 유형을 텍스트로, 이름을 last_name으로 설정합니다.

Code 22-24행: 여기서는 입력 유형을 텍스트로, 이름을 사용자 이름으로 지정합니다.

Code 26-28행: 여기서는 입력 유형을 비밀번호로 설정하고(이렇게 하면 입력하는 동안 비밀번호가 숨겨집니다), 이름을 비밀번호로 사용합니다.

Code 30-32행: 여기서는 입력 유형을 텍스트로, 이름을 주소로 가정합니다.

Code 34-36행: 여기서는 입력 유형을 텍스트로, 이름을 연락처로 가정합니다.

Code 37 라인 : 여기서는 '제출'이라는 값을 가진 '제출' 유형의 버튼을 사용합니다. 이 버튼을 클릭하면 해당 guru_register 서블릿으로 이동하여 요청에 포함된 모든 매개변수 값을 전달합니다.

참고 : 테이블 속성은 다음과 같습니다. Code 12번째 줄은 다음과 같습니다. style="with: 50%"올바른 CSS 속성은 다음과 같습니다. width따라서 목록은 게시된 그대로 재현되지만, 사용자의 사본에서 해당 오타가 수정될 때까지 표의 크기는 조정되지 않습니다.

예 2 : Guru_register.java

package demotest;

import java.io.IOException;

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

/**
 * Servlet implementation class guru_register
 */
public class guru_register extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    
     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String first_name = request.getParameter("first_name");
		String last_name = request.getParameter("last_name");
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		String address = request.getParameter("address");
		String contact = request.getParameter("contact");
		
		if(first_name.isEmpty() || last_name.isEmpty() || username.isEmpty() || 
				password.isEmpty() || address.isEmpty() || contact.isEmpty())
		{
			RequestDispatcher req = request.getRequestDispatcher("register_1.jsp");
			req.include(request, response);
		}
		else
		{
			RequestDispatcher req = request.getRequestDispatcher("register_2.jsp");
			req.forward(request, response);
		}
	}

}

코드 설명:

Code 14 라인 : 여기서는 HttpServlet을 상속하는 guru_register 서블릿을 정의합니다.

Code 18 라인 : 이것은 doPost() 메서드이며, 위의 JSP 양식에서 메서드 속성을 POST로 지정했을 때 호출됩니다.

Code 20-25행: 여기서는 request.getParameter를 사용하여 요청에서 first_name, last_name, username, password, address 및 contact 값을 가져옵니다.

Code 27-32행: 여기서는 if 조건을 사용하여 요청에서 가져온 매개변수 중 하나라도 비어 있는지 확인합니다. 매개변수 중 하나라도 비어 있으면 (first_name.isEmpty() || last_name.isEmpty() || username.isEmpty() || password.isEmpty() || address.isEmpty() || contact.isEmpty()) 조건으로 제어가 이동하고, 요청 객체에서 RequestDispatcher 객체를 가져와 register_1.jsp로 요청을 다시 보냅니다. 또한 요청 및 응답 객체를 포함합니다.

Code 33-37행: 이 분기는 모든 매개변수가 비어 있지 않을 때 실행됩니다. 요청 객체에서 RequestDispatcher 객체를 가져와 register_2.jsp로 요청을 전달합니다. 여기서는 요청 및 응답 객체를 전달합니다.

두 분야 간의 차이점은 중요합니다. include() register_1.jsp를 실행하고 서블릿으로 제어권을 반환합니다. forward() register_2.jsp로 요청을 전달하고 응답을 받지 않습니다.

예 3: Register_2.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Guru Success Page</title>
</head>
<body>
           <a><b>Welcome User!!!!</b></a>
</body>
</html>

코드 설명:

Code 10 라인 : 여기에 환영 메시지를 표시합니다. 이 JSP 페이지는 모든 매개변수가 입력되면 호출됩니다.

위 코드를 실행하면 다음과 같은 출력이 나옵니다.

출력:

회원가입 페이지에는 아래 그림과 같이 레이블이 지정된 6개의 입력란과 하나의 제출 버튼이 표시됩니다.

Guru 이름, 성, 사용자 이름, 비밀번호, 주소 및 연락처 입력란이 있는 JSP 형식의 회원가입 양식

모든 필드를 입력하고 제출 버튼을 클릭하면 guru_register는 register_2.jsp로 이동하고 성공 페이지가 나타납니다.

회원가입 후 표시되는 Register_2.jsp 성공 페이지(사용자 환영 메시지 포함)

register_1.jsp를 클릭하면 이름, 성, 사용자 이름, 비밀번호, 주소 및 연락처를 입력하는 양식이 나타납니다. 모든 정보를 입력하고 제출 버튼을 클릭하면 "사용자님 환영합니다"라는 메시지가 표시됩니다.

JSP에서 로그인 및 로그아웃 폼을 만드는 방법

회원가입 양식처럼, 이제 로그인 및 로그아웃 양식을 만들어 보겠습니다.

이 예시에서는 "사용자 이름"과 "비밀번호"라는 두 개의 입력란과 제출 버튼이 있는 로그인 양식을 사용했습니다.

제출 버튼을 클릭하면 로그아웃 버튼이 포함된 환영 메시지가 나타납니다.

로그아웃 버튼을 클릭하면 로그인 화면으로 돌아갑니다.

예 1: Register_3.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Guru Login Form</title>
</head>
<body>
<form action="guru_login" method="post">
		<table style="with: 50%">

			<tr>
				<td>UserName</td>
				<td><input type="text" name="username" /></td>
			</tr>
				<tr>
				<td>Password</td>
				<td><input type="password" name="password" /></td>
			</tr>
		</table>
		<input type="submit" value="Login" /></form>
</body>
</html>

코드 설명:

Code 10 라인 : 여기서는 액션이 ​​guru_login.java 서블릿인 폼을 예로 들고 있습니다. 데이터 전달 방식은 POST입니다.

Code 13-16행: 여기서는 텍스트 유형의 입력 필드 "사용자 이름"을 예로 들어 보겠습니다.

Code 17-20행: 여기서는 "password"라는 입력 필드를 예로 들고 있는데, 이 필드의 유형은 비밀번호입니다.

Code 22 라인 : 여기서는 "로그인" 값을 가진 "제출" 버튼을 예로 들어 보겠습니다. 이 버튼을 클릭하면 제어권이 guru_login 서블릿으로 이동하고, 해당 서블릿에서는 요청 객체를 사용하여 두 필드를 모두 읽어옵니다.

예 2 : Guru_login.java (서블릿)

package demotest;

import java.io.IOException;

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

/**
 * Servlet implementation class guru_login
 */
public class guru_login extends HttpServlet {

    public guru_login() {
        super();
        // TODO Auto-generated constructor stub
    }

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		if(username.isEmpty() || password.isEmpty() )
		{
			RequestDispatcher req = request.getRequestDispatcher("register_3.jsp");
			req.include(request, response);
		}
		else
		{
			RequestDispatcher req = request.getRequestDispatcher("register_4.jsp");
			req.forward(request, response);
		}
	}

}

코드 설명:

Code 5-9행: 여기서는 필요한 클래스들을 코드로 불러오고 있습니다.

Code 14 라인 : 여기서는 HttpServlet을 상속하는 guru_login 서블릿을 선언합니다.

Code 21 라인 : 폼에서 POST 메서드를 사용하기 때문에 여기서는 doPost() 메서드를 사용합니다.

Code 23-24행: 여기서는 요청 객체를 사용하여 매개변수, 즉 사용자 이름과 비밀번호를 읽습니다.

Code 25-29행: 이와 같이 사용자 이름과 비밀번호가 비어 있는지 확인하는 "if" 조건을 사용합니다. 둘 중 하나라도 비어 있으면 요청 및 응답 객체와 함께 register_3.jsp로 제어를 되돌려 보내는 RequestDispatcher 객체를 얻습니다.

Code 30-34행: 이 분기는 두 객체가 모두 비어 있지 않은 경우에 실행되며, 요청 및 응답 객체와 함께 register_4.jsp로 요청을 전달합니다.

예 3: Register_4.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Guru Logged In</title>
</head>
<body>
	<table style="with: 50%">
	<tr><td>
	<% String username = request.getParameter("username"); %>
<a>Welcome   <% out.println(username); %> User!!!! You have logged in.</a></td></tr>
<tr></tr><tr><td></td><td></td><td><a href="register_3.jsp"><b>Logout</b></a></td></tr>
</table>
</body>
</html>

코드 설명:

Code 12 라인 : 여기서는 요청 객체에서 "username" 매개변수를 가져와 문자열 객체 username에 저장합니다. forward() 함수는 원래 요청과 그 매개변수를 그대로 유지하기 때문에 이러한 방식이 가능합니다.

Code 13 라인 : 여기에 사용자 이름이 포함된 환영 메시지가 있습니다.

Code 14 라인 : 여기에 로그아웃 링크가 있습니다. 이 링크를 클릭하면 사용자는 register_3.jsp 페이지로 돌아갑니다.

위 코드를 실행하면 다음과 같은 출력이 나옵니다.

출력:

register_3.jsp를 열면 두 개의 자격 증명 입력란과 로그인 버튼이 표시됩니다.

Guru JSP 페이지에 사용자 이름과 비밀번호 입력란 및 로그인 버튼이 있는 로그인 폼을 표시합니다.

로그인 버튼을 클릭하면 아래와 같은 메시지와 함께 로그아웃 링크가 표시됩니다.

Register_4.jsp 환영 화면은 로그인한 사용자에게 로그아웃 링크를 제공합니다.

로그아웃 링크를 클릭하면 여기에 표시된 로그인 페이지로 돌아갑니다.

사용자가 로그아웃을 클릭한 후 브라우저에 로그인 페이지가 다시 표시됩니다.

참고 : 이 예제는 빈 값만 비교하므로 비어 있지 않은 모든 사용자 이름이 허용됩니다. 실제 운영 환경에서는 자격 증명을 저장소와 대조하여 검증하고 비밀번호를 해시 처리하여 평문으로 저장해서는 안 됩니다.

getParameter()를 사용한 JSP 양식 처리

웹 처리에서 입력을 수집하는 일반적인 방법은 폼을 사용하는 것입니다. 웹 서버로 정보를 전송하고 서버 측에서 해당 정보를 다시 읽어와야 합니다.

웹 서버에 정보를 보내고 받는 데 일반적으로 사용되는 두 가지 방법이 있습니다.

GET 방법:

  • 이는 브라우저에서 웹 서버로 정보를 전달하는 기본 방법입니다.
  • 인코딩된 정보를 페이지에 추가하여 전송합니다. URL? 문자로 구분됩니다.
  • 또한 크기 제한도 있습니다. 일반적으로 요청당 약 1024자 정도가 권장되지만, 실제 최대치는 HTTP 사양보다는 브라우저와 서버에 의해 결정됩니다.
  • GET 메서드를 통해 비밀번호나 민감한 정보를 전송하는 것은 피해야 합니다.

게시 방법:

  • POST 방식은 서버로 정보를 전송하는 데 있어 더 안정적인 방법입니다.
  • 주소 표시줄에 정보를 표시하는 대신 별도의 메시지 본문에 정보를 담아 보냅니다.
  • 물음표(?) 뒤에는 값이 나타나지 않기 때문입니다. URL이러한 정보는 브라우저 기록이나 서버 접속 로그에 저장되지 않습니다.
  • 민감한 정보를 전송할 때 흔히 사용됩니다.

JSP는 다음 메서드를 사용하여 폼 데이터 처리를 수행합니다.

  1. getParameter(): 단일 폼 매개변수의 값을 가져오는 데 사용됩니다.
  2. getParameterValues(): 매개변수의 여러 값을 반환하는 데 사용됩니다.
  3. getParameterNames(): 모든 매개변수의 이름을 가져오는 데 사용됩니다.
  4. getInputStream(): 클라이언트가 보낸 바이너리 데이터를 읽는 데 사용됩니다.

예:

이 예시에서는 "사용자 이름"과 "비밀번호"라는 두 개의 입력란과 제출 버튼이 있는 양식을 사용했습니다.

Action_form.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Guru Form</title>
</head>
<body>
<form action="action_form_process.jsp" method="GET">
UserName: <input type="text" name="username">
<br />
Password: <input type="text" name="password" />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Action_form_process.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>

<h1>Form Processing</h1>

<p><b>Welcome User:</b>
   <%= request.getParameter("username")%>
</p>

</body>
</html>

코드 설명: Action_form.jsp

Code 10 라인 : 여기서는 다른 것에 의해 동작이 처리되는 형태를 정의했습니다. JSPaction 속성에는 GET 메서드를 통해 폼을 제출할 JSP 페이지를 추가합니다.

여기서는 GET 메서드를 사용하여 사용자 이름과 비밀번호와 같은 정보를 전달합니다.

Code 11-14행: 여기서는 사용자 이름과 비밀번호와 같은 텍스트 필드를 사용하고 있으며, 사용자로부터 입력을 받고 있습니다.

이 입력값은 getParameter 메서드를 사용하여 가져올 수 있습니다. 또한, 필드 값을 action_form_process.jsp로 전달하는 제출 버튼도 있습니다.

Action_form_process.jsp

Code 14 라인 : 여기서는 request 객체의 getParameter 메서드를 사용하여 action_form.jsp의 입력 필드 값을 가져옵니다.

위 코드를 실행하면 다음과 같은 출력이 나타납니다.

출력:

Action_form.jsp는 먼저 아래와 같이 두 개의 입력란으로 구성된 양식을 렌더링합니다.

Action_form.jsp는 사용자 이름과 비밀번호 입력란과 제출 버튼을 표시합니다.

제출 후 action_form_process.jsp는 getParameter()를 통해 읽어온 사용자 이름을 출력합니다.

Action_form_process.jsp 출력 페이지에는 "양식 처리 중" 제목과 환영 메시지가 표시됩니다.

action_form.jsp를 실행하면 사용자 이름과 비밀번호 두 개의 입력란과 제출 버튼이 있는 폼이 나타납니다. 사용자 이름과 비밀번호를 입력하고 제출 버튼을 클릭하면 다음 페이지에서 요청이 처리되고, 환영 메시지와 함께 폼 처리 페이지가 표시됩니다.

버전 참고: 위의 두 서블릿 모두 javax.servlet을 가져오는데, 이는 Tomcat 9 이하 버전에서는 올바른 동작입니다. 하지만 Jakarta EE 9에서는 API 이름이 변경되었으므로 Tomcat 10 이상 버전에서는 모든 javax.servlet 가져오기가 jakarta.servlet으로 바뀌어야 합니다. 그렇지 않으면 Apache Tomcat Migration Tool for Jakarta EE를 사용하여 애플리케이션을 변환해야 합니다.

자주 묻는 질문

이 코드는 API가 javax.servlet에 있는 Tomcat 9 이하 버전을 대상으로 합니다. Jakarta EE 9에서 네임스페이스 이름이 변경되었으므로 Tomcat 10 이상 버전에서는 jakarta.servlet을 임포트하고 다시 컴파일하거나 Tomcat 마이그레이션 도구를 실행해야 합니다.

절대 평문으로 저장하지 마세요. 데이터베이스에 저장하기 전에 BCrypt나 Argon2 같은 느리고 솔트가 포함된 알고리즘으로 해싱하고, 로그인 시 해시값을 비교하세요. 샘플 서블릿은 빈 값만 확인하므로 해싱을 추가해야 합니다.

include() 함수는 대상 리소스를 실행하고 호출하는 서블릿으로 제어권을 반환하므로 두 출력이 모두 나타납니다. forward() 함수는 전체 요청을 대상에 전달하고 다시 돌아오지 않으므로 서블릿이 먼저 응답을 커밋하지 않았어야 합니다.

JSP 페이지는 뷰이고, 서블릿은 매개변수를 읽고 어디로 이동할지 결정하는 컨트롤러이며, 데이터베이스 또는 빈 레이어는 모델을 제공합니다. RequestDispatcher는 컨트롤러와 뷰를 연결하는 역할을 합니다.

AI 비서는 유효성 검사 분기를 작성하고, getParameter()에서 누락된 null 검사를 찾아내고, 해싱 라이브러리를 제안하고, 스택 트레이스를 설명할 수 있습니다. trac예. 모든 제안을 초안으로 취급하세요. 서블릿 API 버전을 확인하고 생성된 코드를 테스트한 후 배포하세요.ping 그것.

Copilot은 doPost 스텁, 매개변수 읽기, 디스패처 호출과 같은 반복적인 상용구 코드를 처리하는 데 유용합니다. 하지만 종종 오래된 javax.servlet 임포트를 기본값으로 사용하므로 네임스페이스, 유효성 검사 로직 및 에스케이프를 확인해야 합니다.ping 사용자가 입력한 내용과 관계없이 모든 것을 생성합니다.

서블릿에 JDBC 레이어를 추가합니다. 풀링된 연결을 열고, 삽입 또는 자격 증명 조회를 위해 PreparedStatement를 사용하며, finally 블록에서 리소스를 닫습니다. SQL 쿼리는 JSP에서 제외하여 뷰가 프레젠테이션 전용으로 유지되도록 합니다.

guru_login은 필드가 비어 있는지 여부만 검사하기 때문입니다. 사용자 이름이나 비밀번호가 비어 있으면 리디렉션 대신 로그인 페이지로 다시 이동하는데, 이는 실제 인증이라기보다는 매우 단순한 유효성 검사 역할만 합니다.

이 게시물을 요약하면 다음과 같습니다.