안녕하세요.
이번 글에서는
클라이언트가 JSP를 통해
전송한 문자열에 한글이 있는 경우,
받았을 때 한글이 깨지지 않고
올바르게 출력시키는 코드에 대해
알아보겠습니다.
오류 확인
해결 방법을 설명하기 전에
먼저 폼에서 한글이 입력되었을 때,
어떤 결과가 나오는지 제 코드를 통해서 알아보겠습니다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.util.Calendar"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="registerCheck.js"></script>
<!-- Daum에서 제공하는 API -->
<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
</head>
<body>
<form name=form1 action="./login" method="POST">
<table align="center" width="600" height="250" border="1">
<tr align="center" style="background-color:rgb(134, 176, 224); color:rgb(10, 10, 10)">
<th colspan="2">회원 기본 정보</th>
</tr>
<tr>
<td align="center" style="background-color:rgb(162, 166, 170); color:rgb(10, 10, 10)"><b>아이디:</b></td>
<td>
<p>
<input type="text" size="13" name="userid" minlength="4" maxlength="12" required>
<label for="userid">4~12자의 영문 대소문자와 숫자로만 입력</label>
</p>
</td>
</tr>
<tr>
<td align="center" style="background-color:rgb(162, 166, 170); color:rgb(10, 10, 10)"><b>비밀번호:</b></td>
<td>
<p>
<input type="password" size="13" name="password" minlength="4" maxlength="12" required>
<label for="password">4~12자의 영문 대소문자와 숫자로만 입력</label>
</p>
</td>
</tr>
<tr>
<td align="center" style="background-color:rgb(162, 166, 170); color:rgb(10, 10, 10)"><b>비밀번호 확인:</b></td>
<td>
<p>
<input type="password" size="13" name="passwordRe" minlength="4" maxlength="12" required>
</p>
</td>
</tr>
<tr>
<td align="center" style="background-color:rgb(162, 166, 170); color:rgb(10, 10, 10)"><b>메일 주소:</b></td>
<td>
<p>
<input id="mail" type="text" name="mailAddress" required>
<label for="mailAddress">예) id@domain.com</label>
</p>
</td>
</tr>
<tr>
<td align="center" style="background-color:rgb(162, 166, 170); color:rgb(10, 10, 10)"><b>이름:</b></td>
<td>
<p>
<input type="text" name="name" required>
<label for="name">2~4자로 입력</label>
</p>
</td>
</tr>
<tr>
<td align="center" style="background-color:rgb(162, 166, 170); color:rgb(10, 10, 10)"><b>주소:</b></td>
<td>
<p>
<input type="text" name="address1" placeholder="우편번호" readonly required>
<button type="button" onclick="searchAddress()">우편번호 찾기</button> <br>
<input type="text" name="address2" placeholder="주소" readonly required><br>
<input type="text" name="address3" placeholder="상세주소" required><br>
</p>
</td>
</tr>
<tr align="center" style="background-color:rgb(134, 176, 224); color:rgb(10, 10, 10)">
<th colspan="2">개인 신상 정보</th>
</tr>
<tr>
<td align="center" style="background-color:rgb(162, 166, 170); color:rgb(10, 10, 10)"><b>주민등록번호:</b></td>
<td>
<p>
<input type="text" name="specificNum" minlength="13" maxlength="13" required>
<button type="button" onclick="specificNumCheck()">확인</button>
<label for="specificNum">예) 1234561234567</label>
</p>
</td>
</tr>
<tr>
<td align="center" style="background-color:rgb(162, 166, 170); color:rgb(10, 10, 10)"><b>생일:</b></td>
<td>
<p>
<input type="text" size="5" name="year" minlength="4" maxlength="4" required>
<label for="year">년 </label>
<select name="month">
<option value="1">1</option><option value="2">2</option><option value="3">3</option>
<option value="4">4</option><option value="5">5</option><option value="6">6</option>
<option value="7">7</option><option value="8">8</option><option value="9">9</option>
<option value="10">10</option><option value="11">11</option><option value="12">12</option>
</select>
<label for="month">월 </label>
<select name="day">
<option value="1">1</option><option value="2">2</option><option value="3">3</option>
<option value="4">4</option><option value="5">5</option><option value="6">6</option>
<option value="7">7</option><option value="8">8</option><option value="9">9</option>
<option value="10">10</option><option value="11">11</option><option value="12">12</option>
<option value="13">13</option><option value="14">14</option><option value="15">15</option>
<option value="16">16</option><option value="17">17</option><option value="18">18</option>
<option value="19">19</option><option value="20">20</option><option value="21">21</option>
<option value="22">22</option><option value="23">23</option><option value="24">24</option>
<option value="25">25</option><option value="26">26</option><option value="27">27</option>
<option value="28">28</option><option value="29">29</option><option value="30">30</option>
<option value="31">31</option>
</select>
<label for="day">일 </label>
</p>
</td>
</tr>
<tr>
<td align="center" style="background-color:rgb(162, 166, 170); color:rgb(10, 10, 10)"><b>관심 분야:</b></td>
<td>
<p>
<input id="computer" type="checkbox" name="favorite" value="computer">
<label for="computer">컴퓨터</label>
<input type="checkbox" name="favorite" value="Internet">인터넷
<input type="checkbox" name="favorite" value="trip">여행
<input type="checkbox" name="favorite" value="movie">영화감상
<input type="checkbox" name="favorite" value="music">음악감상
</p>
</td>
</tr>
<tr>
<td align="center" style="background-color:rgb(162, 166, 170); color:rgb(10, 10, 10)"><b>자기 소개:</b></td>
<td>
<p>
<textarea rows="8" cols="50" name="intro">
</textarea>
</p>
</td>
</tr>
</table>
<p align="center">
<button type="submit" onclick="registerCheck()">회원가입</button>
<button type="reset" value="reset">다시 입력</button>
</p>
</form>
</body>
</html>
접은 부분의 코드는 제가 회원가입을 위해 작성했던 JSP 코드입니다.
여기에 있는 폼을 작성한 뒤에 회원가입 버튼을 누르면
Servlet에서 받아와 화면이 넘어가고 회원가입한 회원의
정보가 출력되도록 프로그램을 작성하였습니다.
아래는 회원 정보를 받아서 출력하는 Servlet 파일의 코드입니다.
package login;
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;
@WebServlet("/LoginData")
public class LoginData extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userId, password, email, name;
String address1, address2, address3;
String specificNum, year, month, day;
String []favorite;
String intro;
PrintWriter out = response.getWriter();
userId = request.getParameter("userid");
password = request.getParameter("password");
email = request.getParameter("mailAddress");
name = request.getParameter("name");
address1 = request.getParameter("address1");
address2 = request.getParameter("address2");
address3 = request.getParameter("address3");
specificNum = request.getParameter("specificNum");
year = request.getParameter("year");
month = request.getParameter("month");
day = request.getParameter("day");
favorite = request.getParameterValues("favorite");
intro = request.getParameter("intro");
out.println("<HTML>");
out.println("<HEAD><TITLE>회원가입 완료</TITLE>");
out.println("<style>");
out.println("table { width: 50%; margin: auto; border-collapse: collapse; }");
out.println("td, th { border: 1px solid black; padding: 8px; text-align: left; }");
out.println("th { background-color: #f2f2f2; }");
out.println("th:nth-child(1), td:nth-child(1) { width: 20%; }"); // 항목 열의 너비
out.println("th:nth-child(2), td:nth-child(2) { width: 80%; }"); // 값 열의 너비
out.println("</style>");
out.println("</HEAD>");
out.println("<BODY><center>");
out.println("<H2>회원가입 완료</H2>");
out.println("<HR>");
out.println("<p style='color: #9933ff;'><strong>환영합니다.</strong></p>");
out.println("<p><img src='다운로드1.jpg'></p>");
out.println("<table>");
out.println("<tr><th>항목</th><th>회원 정보</th></tr>");
out.println("<tr><td>아이디</td><td>" + userId + "</td></tr>");
out.println("<tr><td>비밀번호</td><td>" + password + "</td></tr>");
out.println("<tr><td>이메일</td><td>" + email + "</td></tr>");
out.println("<tr><td>이름</td><td>" + name + "</td></tr>");
out.println("<tr><td>주소</td><td><p>" + "우편번호 : " + address1 + "<br>" +
"주소 : " + address2 + "<br>" + "상세 주소 : " + address3 + "</p></td></tr>");
out.println("<tr><td>주민번호</td><td>" + specificNum.substring(0, 6) + " - " + specificNum.substring(6) + "</td></tr>");
out.println("<tr><td>생년월일</td><td>" + year + "년 " + month + "월 " + day + "일" + "</td></tr>");
out.println("<tr><td>관심분야</td><td>");
for (int i = 0; i < favorite.length; i++) {
out.print(favorite[i]);
if (i < favorite.length - 1) {
out.print(", ");
}
}
out.println("</td></tr>");
out.println("<tr><td>자기소개</td><td>" + intro + "</td></tr>");
out.println("</table>");
out.println("</BODY></HTML>");
}
}
접은 부분의 코드를 실행하면 아래와 같이 출력됩니다.

위 사진과 같이 한글이 깨져서 화면에 출력되는 것을 확인할 수 있습니다.
그럼 이제 이 현상에 대한 해결법을 알아보도록 하겠습니다.
1. Get 방식 한글 처리
Get 방식으로 전달된 질의 문자열은
요청 정보 헤더의 URI에 포함되어 전달됩니다.
GET 방식으로 전달되는 질의 문자열들의 인코딩 작업을 할 때는
다음과 같은 질문에 답이 무엇인지 명확히 하고 작업합니다.
1. 클라이언트가 입력하는 질의 문자열의 인코딩 문자코드는 무엇인가.
2. 서버에서 URI를 인코딩하는 문자코드는 무엇인가.
1) 클라이언트가 입력하는 질의 문자열의 인코딩 문자코드는 무엇인가?
클라이언트가 입력한 문자열들을 인코딩 처리하는 방법은 두 가지입니다.
소스에서 직접 인코딩 문자코드를 지정해주는 방법과
이클립스에서 인코딩 문자를 지정하는 방법입니다.
소스에서 직접 인코딩 문자코드를 지정해주는 방법은
<head>와 </head>사이에 <meta charset="UTF-8"> 태그처럼
사용하고자 하는 문자코드를 지정하는 것입니다.
이클립스에서 소스의 인코딩 문자코드를 지정하는 방법은
이클립스에서 [Window] -> [Preferences] -> [Web] -> [HTML Files]를 선택한 다음,
'Encoding'에서 원하는 문자코드를 지정합니다.
다른 형식(CSS, JSP)의 파일도 같은 방법으로 인코딩을 지정합니다.
2) 서버에서 URI를 인코딩하는 문자코드는 무엇인가?
클라이언트로부터 전달된 URI 문자열의 인코딩 작업은 서버에서 처리해줍니다.
서버마다 기본적으로 URI의 인코딩 문자코드가 정해져 있으며
톰캣 8 버전에서는 UTF-8 문자코드가 기본값으로 적용됩니다.
만일 서버의 URI 인코딩 처리 문자코드를 지정하고 싶다면,
서버의 환경설정 파일 중 server.xml 파일에 인코딩 문자코드를 설정해줍니다.
2. Post 방식 한글 처리
POST 방식은 서블릿 API에서 한글 코드 변환을 해주는 메소드를 제공하고 있어서
메소드를 사용해 간단하게 한글을 처리할 수 있습니다.
POST 방식에서 한글 처리를 해주는 메소드는 HttpServletRequest의 상위 객체인
ServletRequest에서 제공하는 setCharacterEncoding() 메소드입니다.
request.setCharacterEncoding("UTF-8");
setCharacterEncoding() 메소드는 인자값으로 지정된 문자코드를 사용하여
클라이언트가 전달한 요청정보 몸체에 있는 문자열들을 인코딩해주는 메소드입니다.
클라이언트로부터 질의 문자열이 전달된 후 서블릿이 실행될 때
setCharacterEncoding() 메소드로 인코딩 작업을 처리한 후
getParameter() 메소드로 추출하여 사용합니다.
위 2가지 해결 방법 중 한 가지를 사용하여
코드를 변경해주고 다시 실행해주면

위 사진과 같이 한글 깨짐 없이
출력이 된 것을 확인할 수 있습니다.
감사합니다.
'공부 기록 > 백엔드 공부' 카테고리의 다른 글
| [Docker] 도커(Docker)는 무엇일까? (0) | 2024.03.23 |
|---|