2020년 2월 20일 목요일

이클립스 프로젝트에 에러 표시(빨간색 x 박스) 해법

다른 PC의 이클립스에서 개발한 프로젝트를 새로운 PC의 이클립스로 import할 경우 원래 PC의 개발환경과 JDK, Tomcat... 등등 환경이 다른 관계로 인해 프로젝트에 빨간색 x 박스가 뜨는 경우가 허다하다.
이를경우 해법은 

1) 현재 PC의 JDK 설치 경로 맞춰주기
프로젝트 위에서 마우슨 우측 클릭 ⇒ 팝업 메뉴에서 Build Path 선택 ⇒ Configure Build Path ⇒ Java Build Path 창의 Libraries 탭 선택 ⇒ JRE System Library 항목 선택 ⇒ 우측 Eidt… 버튼 클릭 ⇒ JRE System Library 창에서 3가지 radio 버튼 항목 중 “Workspace default JRE(Java SE …) 항목 클릭 ⇒ Finish ⇒ Apply

2) .jar 파일이 없다는 경우(maven dependency 에러) pom.xml에서 맞춰주거나 혹은 해당 .jar 파일을 다운 받아서 추가하기
webapp/WEB-INF/lib 폴더(lib 폴더 없으면 생성)에 원하는 .jar 파일 복사 ⇒ 프로젝트 위에서 마우스 우측 클릭 ⇒ 팝업 메뉴에서 Build Path 선택 ⇒ Configure Build Path ⇒ Java Build Path 창의 Libraries 탭 선택 ⇒ 우측 “Add JARs…” 버튼 클릭 ⇒ 새로운 창에서 복사했던 .jar가 있는 webapp/WEB-INF/lib/ 아래의 해당 .jar 선택 ⇒ OK ⇒ Apply

3) 아래와 같은 에러가 발생시에는 
Target runtime jre1.8.0_161 is not defined. MybatisProject Unknown Faceted Project Problem

프로젝트에 에러가 발생했을 때는 구체적으로 어디서 어떤 에러인지에 대한 정보를 이클립스가 제공해주는 데(예를들어 위와 같은 에러) 그것 볼려면 메뉴에서 Window - Show View - Problems 메뉴를 선택하면 에러에 대한 자세한 정보를 볼수 있다.
위와 같은 에러의 경우는

프로젝트 위에서 마우스 우측 클릭 ⇒ Properties ⇒ Java Build Path 창의 좌측 항목들 중 Project Facets 항목 선택  가운데 Project Facet 항목들 중 Java 항목 선택 ⇒ 현재 PC에 설치된 Java 버전과 동일한 버전이 선택됐는지 확인 ⇒ 우측 Details와 Runtimes 탭 중에서 Runtimes 탭 선택 ⇒ 현재 개발 PC에 설치되어 있는 Java 버전에 맞는 항목 선택

나의 경우는 jre1.8.0.202가 설치되어 있었는데 체크박스 체크된 jre 버전은 1.8.0.161이 선택되어 있어서 발생한 에러였다.

2020년 2월 11일 화요일

Spring Controller 클래스에서 view(.jsp)로 이동하는 규칙

Controller 클래스 수행후 이동하게 될 .jsp를 찾는 일은 Spring 기반의 프로젝트에서 늘상하게 되는 일인데 @RequestMapping에 의해서 특정 메소드의 리턴 타입이 String 타입이 있는가하면 void 타입도 있다. 이들 각각의 경우에 이동하게 될 .jsp를 찾능 원리에 대해 정리하고자 한다.

아래와 같이 메소드의 리턴타입이 String 일 경우는

@Controller
public class SomeController {

@RequestMapping("/product")
public String doD(Model model) {

return "productDetail";
}
}

이 경우 이동하게 될 .jsp는 productDetail.jsp로 이동하게 된다.

아래와 같이 메소드의 리턴 타입이 void 인경우

@RequestMapping(value = "/info", method=RequestMethod.GET)
public void show(@RequestParam("seq") int seq, @ModelAttribute("myMEM") MemberInfo info, Model model) {

}

이 경우는 리턴 타입이 void인데 이 메소드 실행후 어떻게 .jsp로 넘어가는가?
리턴 타입이 void 일 경우 .jsp 페이지로 넘어가는 규칙은 접근하는 url 경로에 해당하는 .jsp를 찾는다. 이 경우 RequestMapping이 지정한 경로인 /info에 근거해서 info.jsp를 찾아서 실행한다.

이때 info.jsp를 찾을 때 기본적으로 webapp/ 아래에서 찾지만 이건 정확히 말하면 web.xml에서 DispatcherServlet이 로딩하는 서블릿 컨테이너의 설정 파일이 지정한 위치에서 찾는다.
예를들어서 web.xml의 DispatcherServlet의 설정 내용이 다음과 같을 경우

<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
</servlet>

DispatcherServlet 클래스가 사용할 서블릿 컨터이너의 설정 파일은 아래 위치라는 뜻이고
/webapp/WEB-INF/spring/appServlet/servlet-context.xml

/webapp/WEB-INF/spring/appServlet/servlet-context.xml의 내용은 다음과 같다고 한다면

<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>


즉 prefix가 지정한 위치(webapp/WEB-INF/views/) 아래에서 suffix가 지정한 확장자를 붙여서 view 페이지(.jsp)를 찾는다. 결론적으로 webapp/WEB-INF/views/info.jsp를 찾는다는 뜻이다.

2020년 2월 6일 목요일

PHP로 XML 생성 방법 및 생성시 주의 사항

본 포스트는 네이버페이 연동하면서 진행했던 내용을 중심으로 정리하고자 한다.
다음과 같은 XML 데이터를 생성해서 응답하는 기능을 구현 한다고 가정해 보자.

<response>
   <item id="xxx">
      <name><![CDATA[ 상품명 ]]></name>
      <url>http://xxx.xxx.com/mainNew/.../xxx.php</url>
      <description><![CDATA[...상세설명...]]></description>
      <image>
         http://xxx.xxx.com/xxx_file/xxx.jpg
      </image>
      <thumb>
         http://xxx.xxx.com/xxx_file/xxx.jpg
      </thumb>
      <price>27000</price>
      <quantity>100</quantity>
      <category>
         <first id="xxx">대분류</first>
         <second id="xxx">중분류</second>
         <third id="">소분류</third>
      </category>
   </item>
</response>

이때 주의해야 할 사항 및 요령은,

① 엘리먼트 값으로 한글이 들어가야 하는 부분에 대해 character encoding 처리를 잘 해줘야 한다.
위의 경우는 name, description 엘리먼트에 한글 값이 설정되는 부분이다. 그리고 통상적으로 XML를 생성할 때 XML의 엘리먼트에 들어갈 값은 DB로부터 획득해서 설정하게 될 것이다. 이때 DB에 저장된 한글 데이터가 EUC-KR인지 UTF-8인지 잘 분별해서 엘리먼트에 값이 들어가도록 해야한다. 만일 DB에 저장된 데이터가 EUC-KR인데 XML 생성은 UTF-8로 한다면 다음과 같이 처리해야 한다. 그렇지 않으면 XML 생성시 Encoding error라는 XML parsing 에러가 발생되고 XML이 생성되지 않는다.

$nameFromDB = "여기에 DB로부터 가져온 name의 값이 들어있다고 하면";
$name = iconv("EUC-KR", "UTF-8", $nameFromDB);

$nameFromDB에 있는 EUC-KR 타입의 한글을 UTF-8로 변경해서 $name에 저장한다.

$descriptionFromDB = "여기에 DB로부터 가져온 description의 값이 들어있다고 하면";
$description = iconv("EUC-KR", "UTF-8", $descriptionFromDB);

② http url 정보가 들어가야 하는 엘리먼트에서(위의 경우 url, image, thumb) http url에 &가 포함되어 있을 경우 &라는 특수문자는 &문자 자체로 인식되지 않고 특수한 기능을 하는 문자로 취급되기 때문에 EntityRef: expecting ';'라는 에러 발생한다.  예를들어서 다음과 같은 경우이다.

http://xxx.xxx.com?id=1234&tid=3456
이를 경우 str_replace()함수를 이용해서 &를 &amp;로 바꿔줘야 한다.

$itemUrl = str_replace("&", "&amp;", $원본데이터);

③ XML을 생성중 다음과 같은 에러가 발생했다면 왜, 어디서, 어떤 이유때문에 에러가 발생했는지를 쉽게 파악할 수 있는 방법이 있다.
This page contains the following errors:
error on line 4 at column 19: xmlParseEntityRef: no name
Below is a rendering of the page up to the first error.

이 경우 웹 브라우저의 해당 페이지에서 마우스 우측 클릭하여 "페이지 소스 보기"(크롬의 경우)를 하면 아래와 같은 내용이 표시되는 4번 라인에서 url 엘리먼트에 특수문자들이 들어가 있다(아래의 경우는 에러를 의도적으로 발생시키기 위해 이 값들을 넣은 경우이다). 이를 경우 urlencode() 함수 등으로 특수 문자들을 변환해줘야 한다.

<?xml version="1.0" encoding="euc-kr"?><response>
<item id="itemid">
<name><![CDATA[상품 명]]></name>
<url>http://"/:@&%=?.#"#$%=+/test.html</url>
<description><![CDATA[간지나는 아이템]]></description>
<image>http://localhost/test.jpg</image>
<thumb>http://localhost/test.jpg</thumb>
<price>1000</price>
<quantity>1</quantity>
<category>
<first id="MJ01">대분류</first>
<second id="ML01">중분류</second>
<third id="MN01">소분류</third>
</category>
</item>
</response>

이제 본격적으로 PHP로 위의 예시와 같은 XML을 생성하는 코드를 작성해 보자.

<?php
    header('Content-Type: application/xml;charset=utf-8');
    echo ('<?xml version="1.0" encoding="utf-8"?>');
?>

<response>

<?php
    $dbData = "위의 XML예시에서 XML에 들어갈 item 요소가 여러개 일 경우의 데이터";

    //아래와 같이 반복문을 통해 위의 예시의 XML에서 복수개의 item 항목을 가진 XML을 만들고자 할 경우
    for($i=0; $i<count($dbData); $i++) {
        $price = "DB로부터 가져온 가격 데이터";
        $quantity = 50;
        $itemUrl = "http://xxx.xxx.com/...";
        $imgUrl = "http://xxx.xxx.com/...";

        $nameFromDB = "여기에 DB로부터 가져온 name의 값이 들어있다고 하면";
        $name = iconv("EUC-KR", "UTF-8", $nameFromDB);

        $descriptionFromDB = "여기에 DB로부터 가져온 description의 값이 들어있다고 하면";
        $description = iconv("EUC-KR", "UTF-8", $descriptionFromDB);
?>

<item id="<?=$id?>">
<name><![CDATA[<?=$name?>]]></name>
<url><?=$itemUrl?></url>
<description><![CDATA[<?=$description?>]]></description>
<image><?=$imgUrl?></image>
<thumb><?=$imgUrl?></thumb>
<price><?=$price?></price>
<quantity><?=$quantity?></quantity>
<category>
<first id="<?=$product[0][bdr_category_code1]?>">대분류</first>
<second id="<?=$product[0][bdr_category_code2]?>">중분류</second>
<third id="<?=$product[0][bdr_category_code3]?>">소분류</third>
</category>
</item>
<?php
} //for
//end while;
echo('</response>');
?>

이렇게 하면 PHP에서 간단하게(?) XML을 생성해서 클라이언트들의 request에 응답할 수 있다.
이상의 내용은 네이버페이 연동 개발을 하면서 진행했던 내용이었다.