Spring(혹은 전자정부프레임워크)에서 maven build가 정상적으로 수행된 후에 『Run As - Java Application』으로 해당 클래스를 실행했을 때 다음과 같은 에러가 발생했다면 무엇이 문제라는 것일까?


Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'messageBean' defined in class path resource [context-hello.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.joe.MessageBean]: Specified class is an interface

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1105)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1050)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)

at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)

at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)

at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)

at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)

at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)

at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)

at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)

at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)

at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)

at com.joe.HelloApp.main(HelloApp.java:10)

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.joe.MessageBean]: Specified class is an interface

at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:68)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1098)

... 13 more


위의 에러메시지에서 몇 가지 단서들을 확인할수 있는데 

 -. context-hello.xml에 있는 messageBean이라는 이름의 bean 객체를 생성하지 못했다는 것이고

    Error creating bean with name 'messageBean' defined in class path resource [context-hello.xml]

 -. bean을 생성하기 위해 지정된 클래스가 interface이기 때문에 bean(객체)를 생성할수 없다

    Failed to instantiate [com.joe.MessageBean]: Specified class is an interface


참고로 context-hello.xml 파일의 내용은 다음과 같다. 


<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">


<bean name="messageBean" class="com.joe.MessageBean" />


</beans>


그러면 bean을 생성할 대상이 되는 클래스인 com.joe.MessageBean를 보면 다음과 같다.


package com.joe;


public interface MessageBean {

public void sayHello(String name);

}


따라서 결국은 문제가 된 것은 context-hello.xml에서 bean 생성 할 대상으로 지정한 클래스가 interface여서 발생한 에러였다. Java는 근본적으로 interface를 막바로 객체(bean) 생성할수가 없다. 만일 객체를 생성할수 있다고 한들 그 객체가 행할수 있는 기능(메소드) 자체가 정의되어 있지 않기 때문에, 위에서 보듯이 sayHello()라는 메소드가 무엇을 행할지 내용이 없다. 이것이 interface이다. 


따라서 interface는 객체를 막바로 생성할수가 없고 생성할수 있다고 해도 그 객체(bean)이 아무런 동작도 할것이 없는것이다.

따라서 interface를 구현한(implements) 클래스를 객체로(bean)으로 생성하도록 context-hello.xml의 내용을 변경해 주어야 한다.


여기서 MessageBean 인터페이스를 구현한 하위 클래스는 다음과 같다.


package com.joe;


public class MessageBeanEng implements MessageBean {

@Override
public void sayHello(String name){

System.out.println("Hello, "+name);

}

}


따라서 context-hello.xml의 내용을 바꾸어 주어야하는데 interface인 MessageBean을 그 구현 클래스인 MessageBeanEng로 변경해 주어야 하는 것이다.


<bean name="messageBean" class="com.joe.MessageBean" />


를 아래와 같이 바꾸어 주어야 한다.


<bean name="messageBean" class="com.joe.MessageBeanEng" />



Spring(혹은 전자정부프레임워크)에서 자주 사용되는 개념인 DI(Dependency Injection)에 대해서 간단한 예제를 통해 살펴보고자 한다.


DI란 '의존성 주입'이라고 번역이 되는데 표현 자체가 거창해서 그렇지 사실은 그동안 프로그래밍에서 사용되어 오던 것이다.

예를들어 업로드 파일을 서버에 저장하는 SaveFile이라는 클래스가 있을 때 저장되는 파일 이름을 모두 대문자로 변환해서 저장하는 ToUpper라는 클래스를 SaveFile에서 사용한다고 하면 SaveFile은 ToUpper 클래스에 의존되어 있다고 표현한다.


class SaveFile

{

private File file;

private ToUpper upper;


private void saveFile() {

//여기서 upper객체를 사용해서 파일이름을 대문자로 변환후 저장하는 코드

}

.......

}


이럴 경우 ToUpper 클래스를 SaveFile 클래스 내부에서 new로 생성해서 사용할수도 있지만 ToUpper 클래스를 외부에서 주입해서(이걸 DI라고 한다) 사용할수 있을 것이다.

가장 보편적인 방법은 SaveFile의 생성자에서 매개인자(파라미터)로 ToUpper 클래스의 객체를 받아서 사용하는 형태가 있을 것이다.


class SaveFile

{

private File file;

private ToUpper upper;


public SaveFile(ToUpper upper){ //생성자를 통해 의존성 주입(DI)하는 방식

this.upper = upper;

}


private void saveFile() {

//여기서 upper객체를 사용해서 파일이름을 대문자로 변환후 저장하는 코드

}

.......

}


그런데 이 방식외에 Spring 컨테이너의 도움을 받아서 XML 설정 파일의 property 태그를 이용하는 방법도 있다.

이때 사용되는 것은 setter 메소드이다.



class SaveFile

{

private File file;

private ToUpper upper;


//setter만드는 규약에 맞게 setter 메소드를 만들어 두면 Spring 컨테이너가 

//XML 설정 파일의 property 태그를 이용해서 ToUpper 클래스의 객체를

//아래 메소드의 파라미터인 mUpper에 주입(DI)해 준다.

//따라서 ToUpper 클래스의 객체를 new로 생성하지 않아도 정상적으로 사용할수 있는것이다.

//setter를 만드는 규칙은 XML 설정 파일의 property name가 upper로 되어 있는 것을 근거로

//upper의 첫 글자를 대문자로(U) 바꾼 후 앞에 set을 추가한 형태인 setUpper로 만들면

//Spring 컨테이너가 알아서 이 setter를 찾아서 해당 property의 ref가 지정한 bean을

//mUpper에 주입해 준다. 이것이 프라퍼티를 이용한 DI 방식이다.

public void setUpper(ToUpper mUpper) {

this.upper = mUpper;

}


private void saveFile() {

//여기서 upper객체를 사용해서 파일이름을 대문자로 변환후 저장하는 코드

}

.......

}


※ ToUpper 클래스의 내용은 생략(해당 클래스가 잘 만들어져 있다고 가정...)


아래는 XML 설정파일의 정보이다. 파일 이름이 MyBean.xml이라고 가정한다.


<?xml version = "1.0" encoding = "UTF-8"?>

<beans xmlns = "http://www.springframework.org/schema/beans"

   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"

   xsi:schemaLocation = "http://www.springframework.org/schema/beans

   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">


   <!-- SaveFile 클래스를 임의 클래스에서 객체로 사용하도록 bean 정보 설정 -->

   <bean id = "mySaveFile" class = "com.joe.SaveFile">

      <!-- SaveFile 클래스의 setUpper()에게로 ref가 지정하는 bean(객체)를 Spring 컨테이너가 주입해준다

즉 SaveFile 클래스에서 setUpper()의 매개인자로 ref가 지정하는 bean을 주입해 준다.

즉 setUpper(myUpper)식이 되는 것이다.

 -->

      <property name = "upper" ref = "myUpper"/>

   </bean>


   <!-- SaveFile 클래스가 사용하게 될 ToUpper 클래스에 대한 bean -->

   <bean id = "myUpper" class = "com.joe.ToUpper"></bean>

</beans>


이제 사용하는 방법은 다음과 같다.


package com.joe;


import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;


public class MainApp {

   public static void main(String[] args) {

      ApplicationContext context = new ClassPathXmlApplicationContext("MyBean.xml");


      SaveFile sf = (SaveFile) context.getBean("mySaveFile");

      sf.saveFile();

   }

}


HTML의 <col> 태그에 대해서


<col> 태그는 테이블에서 column(열)의 속성을 지정하는 역할을 하는 태그이다.

<col> 태그는 테이블의 column 전체에 특정한 속성(예를들어 특정 색상으로 표시되게)을 적용하는데 유용하다.


다음과 같은 코드가 있다고 할때


<!DOCTYPE html>

<html>

<head>

<style>

table, th, td {

    border: 1px solid black;

}

</style>

</head>

<body>


<table>

  <colgroup>

    <col style="background-color:red">

    <col style="background-color:yellow">

    <col style="background-color:#ababab">

  </colgroup>

  <tr>

    <th>이름</th>

    <th>나이</th>

    <th>전화번호</th>

  </tr>

  <tr>

    <td>홍길동</td>

    <td>25</td>

    <td>010-1234-4567</td>

  </tr>

  <tr>

    <td>고길동</td>

    <td>45</td>

    <td>010-7777-8888</td>

  </tr>

</table>


</body>

</html>


이 경우 테이블은 2행 3열의 테이블을 이룰것인데 colgroup 안에서 첫 번째 column 전체를 red로, 두 번째 column 전체를 yellow로 그리고 세 번째 column 전체의 색상을 짙은 회색(#ababab의 색상이 짙은 회색임)으로 column의 속성을 지정하는 경우가 되겠다.




만일 col 태그의 내용을 다음과 같이하면 

  <colgroup>

    <col span="2" style="background-color:red">

    <col style="background-color:#ababab">

  </colgroup>


이 경우는 다음과 같이 첫 번째, 두 번째 column 전체가 red로 설정이 된다. 왜냐하면 span 속성에 의해 첫번째와 두번째 column을 합쳐서 적용하도록 했기 때문이다.




만일 col 태그의 내용을 다음과 같이하면 

  <colgroup>

    <col style="background-color:red">

    <col span="2" style="background-color:yellow">

  </colgroup>


이 경우는 다음과 같이 첫 번째 column은 red, 두 번째, 세 번째 column은 yellow로 적용이 될 것이다.





웹 애플리케이션 개발시 크롬 웹 브라우저의 개발자 도구(F12,  혹은 Ctrl-Shift-I)를 적절히 활용하면 html 코드의 복잡한 숲속에서 좀 더 스마트하게 돌아다닐수가 있게 된다.

오늘 포스팅에서는 개발자 도구 중에서 웹 페이지의 복잡한 구조 중에서 특정 영역에 대한 html 요소를 한번에 쉽게 찾아서 확인하는 방법에 대한 글이다.

보통은 디자이너나 웹 프블리셔가 디자인이 적용된 html, css 파일을 던져 주면 그것을 가지고 개발자가 기능을 구현하게 될텐데 구성이 복잡한 웹 페이지의 경우 특정 영역에 대한 html 구성이 어떻게 되었는지를 확인할려면 html 태그 숲 속을 헤매는 경우가 있다.

이러한 작업을 한번에 해결해 주는 기능이 크롬 웹 브라우저의 개발자 도구가 제공하고 있다.


아래와 같은 웹 페이지가 있다고 할 경우(이해를 돕기 위해서 그냥 단순한 경우를 예로 살펴보기로...) 빨간색 영역에 대한 html 요소를 확인하고자하면

(저 영역이 사실은 게시글 작성자 닉네임을 적는 공간인데 input 태그로 되어 있는 영역이다. 이미지가 좀 희미...;;)



-. F12로 개발자 도구 창이 활성화 되도록 한 후에 상단의 "Elements" 탭을 클릭

-. 웹 페이지에서 해당 영역을 마우스로 클릭한 후 마우스 우측을 클릭

-. 팝업 메뉴 중에서 "검사(N)"을 클릭하면

-. 우측 개발자 창에서 해당 영역에 대한 html 요소에 대한 정보가 한번에 보여진다.







Java의 정적 초기자(static initializer)에 대해서 살펴보고자 한다. 

다음과 같은 코드가 있을 때 static { ... }으로 감싸줘 있는 부분을 static initializer라고 한다. 


Oralcle 공식 문서를 보면 "이 정적 초기자 block은 클래스 body 어디에서 나타나도 되며 하나의 클래스가 임의의 갯수의 static initialization block(정적 초기자)를 가질수 있다"고 되어 있다.


그리고 정적 초기자 영역의 코드는 단 한번만 실행되는데 그 실행시점은 

-. 해당 클래스의 객체를 생성할때

-. 해당 클래스의 static 멤버(변수 혹은 메소드)에 최초로 접근할 때 한번 실행이 된다. 이 경우는 심지어 해당 클래스의 객체를 생성하지 않았을 지라도 해당 클래스의 멤버에 최초 접근시 정적 초기자가 실행이 된다.


또한 정적 초기자는 생성자 이전에 실행이 된다.

아래 코드는 확장자를 넘겨 주었을 때 해당 확장자가 어떤 MIME 타입인지를 반환해주는 코드이다. 이때 정적 초기자가 어떻게 실행되는지를 보도록 하자.


public class MyMimeType {

private static Map<String, String> mimeMap;

  //이 영역이 정적 초기자(static initializer)

static {

System.out.println("$$$$$$$ Hello, This is MyMimeType의 정적 초기자입니다");

mimeMap = new HashMap<String, String>();


mimeMap.put("JSON", "application/json");

mimeMap.put("JPG", "image/jpeg");

mimeMap.put("PDF", "application/pdf");

mimeMap.put("ZIP", "application/zip");

mimeMap.put("JAR", "application/java-archive");

//그 외의 mime 타입은 생략...

}

public static String getMimeType(String mType) {

System.out.println("$$$$$$$ Hello, This is MyMimeType의 getMimeType()입니다");

//위의 정적 초기자에서 입력해 놓은 Map의 key 값으로 Mime Type을 반환해낸다.

//만일에 위에서 지정한 5가지 이외의 mType(Map 객체의 key 역할) 값이 오면 null이 반환된다.

return mimeMap.get(mType.toUpperCase());

}

}


만일에 프로그램의 특정 영역에서 MyMimeType 클래스의 객체 생성 없이 아래와 같이 호출했다고 하면


String mType = MyMimeType.getMimeType("ZIP");


해당 메소드가 실행되기 전에 정적 초기자가 먼저 실행되고 이후에 해당 메소드가 실행이된다. 

다음과 같은 순서로 로그가 출력될 것이다.


$$$$$$$ Hello, This is MyMimeType의 정적초기자입니다

$$$$$$$ Hello, This is MyMimeType의 getMimeType()입니다


이후에 아래와 같이 getMimeType() 메소드를 다시 호출하면 


String mType_2 = MyMimeType.getMimeType("jpg");


이제는 정적 초기자는 실행되지 않고 해당 메소드만 실행이되어 다음과 같은 로그를 출력하게 될 것이다.


$$$$$$$ Hello, This is MyMimeType의 getMimeType()입니다



Java varargs 메소드에 대해서


Java에서 다음과 같은 형태의 메소드를 보게 될것이다.


private void makeDir(String... args) {

   ...

}


위의 메소드에서 매개인자(argument)의 형태가 특이하다. String... args

String 타입인건 알겠는데 3개의 ...(three dots)로 표현된 부분이 의미하는 것이 무엇인가하는 것이다.


이러한 메소드를 이름하여 Java varargs라고 한다.  varargs란 또 뭔가? 사전에 찾아도 나오지 않는단어이다. 이건 variable arguments의 줄임 표현같다. 그래서 '가변 인자'라고 표현하면 되겠다.


이러한 형태의 메소드는 Java version 5부터 소개된 파라미터 타입니다.

아마도 Android를 해본 사람은 AsyncTask 클래스에서 이런 모양의 메소드 파라미터를 보았을 것이다.


varargs 파라미터는 해당 데이터 타입의 argument를 0개 이상의 임의의 갯수의 argument를 받을수 있다는 뜻이다.

위의 경우 String... args에는 makeDir() 메소드를 호출하는 곳에서 아래의 경우가 모두 가능하다.


makeDir("aaa", "bbb", "ccc", "ddd", "eee");

makeDir("ddd", "eee");

makeDir("ccc");

makeDir("aaa", "bbb", "eee");

makeDir();

makeDir("aaa", "bbb", "ccc", "ddd", "eee", "fff");


이와같이 임의의 갯수의 argument를 전달할수 있다.

다음과 같이 int형 varargs도 당연히 가능하다.


public String myAddr(int... number) {

  ...

}


varargs 메소드 내부에서 사용법은 다음과 같다.


public int sum(String name, int... args) {

int sum = 0;

for(int i=0; i<args.length; i++){

sum += args[i];

}


return sum;

}


varargs 파라미터 사용시 주의 사항은 varargs 파라미터는 파라미터들의 순서상 맨 마지막에 위치해야된다는 점이다.


다음의 경우는 올바른 사용법이다.


public int sum(String a, int b, int... args) { ... }


그러나 다음의 두 경우는 잘못된 경우이다. 허용되지 않는다.


//varargs가 맨 앞에 온 경우이다.

public int sum(int... args, String a, int b) { ... }


//varargs가 가운데 온 경우이다.

public int sum(String a, int... args, int b) { ... }



부트스트랩의 모달 창 사용하기


웹 애플리케이션에서 다이얼로그 박스나 팝업 창의 기능은 자주 사용하게 되는 기능이다. 이를 위해서 alert()이나 prompt()를 기본적으로 사용하게 될텐데 그 모양이 그렇게 아름다웁지는 않다는 것과 혹은 원치 않는 정보가 보여져야하는 등의 이유로 인해서 본 포스팅에서는 부트스트랩이 제공하는 모달 창에 대해서 정리해보고자 한다.


모달 창이라 함은 현재 페이지 상의 최 상위에 띄워지는 일종의 다이얼로그 박스나 팝업창을 말한다.

부트스트랩의 모달 창을 사용하기 위해서는 아래의 라이브러리들을 포함시켜 줘야 한다.


  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>


아래는 코드 조각이다.


<!DOCTYPE html>

<html>

<head>

<meta charset="EUC-KR">

<title>Insert title here</title>

 

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

</head>

<body>


<!-- 부트스트랩의 모달 창을 사용할려면 아래의 class 이름들을 그대로 사용해야 한다. 변경하면 모양이 달라진다.-->

  <!-- Modal -->

  <div class="modal fade" id="myModal" role="dialog"> <!-- 사용자 지정 부분① : id명 -->

    <div class="modal-dialog">

    

      <!-- Modal content-->

      <div class="modal-content">

        <div class="modal-header">

          <button type="button" class="close" data-dismiss="modal">×</button>

          <h4 class="modal-title">모달 창 타이틀</h4> <!-- 사용자 지정 부분② : 타이틀 -->

        </div>

        <div class="modal-body">

          <p>여기에 필요한 텍스트 메시지 넣기</p> <!-- 사용자 지정 부분③ : 텍스트 메시지 -->

        </div>

        <div class="modal-footer">

          <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>

        </div>

      </div>

    </div>

  </div>


<br/><br/>

<!-- 아래에서 data-toggle과 data-target 속성에서 data-toggle에는 modal 값을 data-target속성에는 모달 창 전체를 

감싸는 div의 id 이름을 지정하면 된다. -->

&nbsp;&nbsp;<button type="button" data-toggle="modal" data-target="#myModal">모달 창 열기</button>

&nbsp;&nbsp;<a data-toggle="modal" href="#myModal">모달 창 열기</a>


</body>

</html>


위 코드가 실행되면 다음과 같은 모양의 모달 창이 뜨게 될 것이다.




요즘은 RESTful한 웹 서비스가 대세를 이루다보니 서버로부터 받는 데이터가 JSON 형태의 데이터가 많다. 즉 서버가 제공하는 API를 통해 데이터를 JSON 형태로 수신하는 경우가 많아졌다. 좀 달리말하면 서버의 특정 URI에로 URL을 던져서 해당 데이터를 JSON으로 수신해야 할 경우 이를 위해 jQuery에서 제공하는 함수인 getJSON() 함수의 용법에 대해서 살펴보고자 한다.


우선 getJSON()의 Syntax를 보면 다음과 같다(https://api.jquery.com/jquery.getjson/ 참조)


getJSON( url [, data ] [, success ] )


이 함수가 하는 기능은 HTTP의 GET method를 통해서 서버의 특정 URI가 던져주는 결과를 JSON 형태로 받아오는 역할을 한다.

(Load JSON-encoded data from the server using a GET HTTP request.)


파라미터는

 -. url : 필수항목으로, 요청이(http request) 보내질 URL이다. 데이터 타입은 String.

 -. data : option으로 key-value쌍으로 구성된 서버로 전송될 데이터.

 -. success : optional으로 서버로부터 JSON 데이터 수신이 완료되었을 때 실행하게 될 function이다. 이 function의 파라미터로 서버가 전송한 JSON 데이터가 담기게 된다.


예제코드를 보자.


아래 코드에서 /replies/all/100의 url을 서버로 던지면 서버에서 결과 값을 JSON 데이터 형태로 반환해 주면 그 결과 데이터(JSON 데이터)가 아래의 function(mData)의 mData에 저장이 된다.


$.getJSON("/replies/all/100", function(mData){

console.log("데이터 길이: ", mData.length);

console.log("데이터 mData[0].replytext: ", mData[0].replytext); 


//아래에서 다음과 같은 로그 출력이 된다.

//getPageList() mData : [object Object]

console.log("getPageList() mData : " + mData);


//아래에서 다음과 같은 로그 출력됨

//getPageList() mData.list : [object Object],[object Object],[object Object],[object Object]...

console.log("getPageList() mData.list : " + mData.list);

//JSON 데이터를 String 형태로 출력할때 JSON.stringify()를 활용하면 편리하다.

//JSON.stringify()에 의해서 JavaScript Object가 String으로 변환되어 myJSON에 저장이된다.

var myJSON = JSON.stringify(mData);

console.log("myJSON : "+myJSON);

});


위의 마지막 코드에서 JSON 포맷의 데이터가 줄이줄줄이 출력이 될 것이다.


[{"rno":17,"bno":100,"replytext":"연습중... ","replyer":"eeeeeee","regdate":1533170966000,"updatedate":1533190576000},{"rno":14,"bno":100,"replytext":"ccc...라는 걸 수정함","replyer":"ccc","regdate":1533117687000,"updatedate":1533190598000},{"rno":11,"bno":100,"replytext":"Ajax로 댓글 작성 후 화면 새로 고침 없이 막바로 되나?","replyer":"Ajax","regdate":1533117629000,"updatedate":1533117629000},{"rno":10,"bno":100,"replytext":"실리콘 벨리에서의 개발자의 삶","replyer":"실리콘","regdate":1533117004000,"updatedate":1533117004000},{"rno":9,"bno":100,"replytext":"이름이 없는 분이 댓글을 자꾸다네~~~ㅋㅋㅋ","replyer":"홍길동","regdate":1533116371000,"updatedate":1533116371000},{"rno":6,"bno":100,"replytext":"미션 임파시블 영화 많이 봐주세요~  from 톰크루즈","replyer":"톰크루즈","regdate":1533115205000,"updatedate":1533190943000},{"rno":3,"bno":100,"replytext":"둘리야 놀자","replyer":"또치","regdate":1533009522000,"updatedate":1533009522000},{"rno":2,"bno":100,"replytext":"감사합니다","replyer":"홍길동","regdate":1533008551000,"updatedate":1533008551000},{"rno":1,"bno":100,"replytext":"수정한 댓글입니다.","replyer":"user00","regdate":1533006012000,"updatedate":1533020309000}]


이러한 데이터를 순차적으로 취급할때는 jQuery가 제공하는 .each()함수를 많이 이용한다. 

아래는 each()함수의 Syntax이다.


.each( function )


이 함수는 jQuery object나 DOM의 특정 element에 대해 for loop과 같은 반복문 동작을 수행한다.

(Iterate over a jQuery object, executing a function(each함수 안에 있는 function) for each matched element.)


파라미터의 function은 다음과 같은 형태로 되어 있다.


function(Integer index, Element element)


위의 JSON 데이터가 담겨 있는 mData에 대해 다음과 같이 처리할수 있다.


var str = "";


//for loop과 같은 반복문이다.

$(mData).each(function(){

//이 경우의 this는 mData라는 객체를 의미한다.

str += "<li>" + this.rno + ":" + this.replytext + "</li>";

});



.each()에 대해 좀더 간단한 예를 통해 이 함수의 기능을 살펴 보면

다음과 같은 내용이 있다고 할때


<ul>

     <li>Android</li>

     <li>Java</li>

     <li>Spring MVC</li>

</ul>


위의 li안에 있는 각 항목들을 모두 출력해 볼려면 jQuery의 .each()함수를 다음과 같이 이용하면 된다. 

아래의 경우는 DOM의 element 중에서 li라는 element에 대해 for loop 기능을 수행하겠다는 것이다.


$("li").each(function(index) {

//여기서 this는 li를 의미한다.

console.log(index + " : " + $(this).text());

});


결과는 다음과 같이 출력될 것이다.

0 : Android

1 : Java

2 : Spring MVC




HTTP로 URL 값을 전달할때 오로지 영문자와 숫자만으로 전달한다면 인코딩 디코딩이 필요 없을 것이나 실제에 있어서는 다양한 특수문자와 한글 등이 URL 값에 포함되어 전달되는데 이때 제대로 인식을 못해서 404 Not found 에러가 발생하거나 잘못된 값이 전달되는 경우가 발생할수 있다.

예를 들어 


http://www.xxx.xx/info?page=3&title=developer&enginner


이 경우 title에 developer&engineer 값이 전달되어야 겠지만 &라는 특수문자는 &문자 자체로 인식되지 않고 특수한 기능을 하는 문자로 취급되기 때문에 문제가 발생한다.


이 문제를 해결하기 위해 title의 데이터 부분만(developer&enginner) 따로 인코딩해서 보낸다면 원하던 목적을 달성할수가 있게된다.

이때 사용하는 JavaScript의 함수가 encodeURIComponent()decodeURIComponent()가 있다.


encodeURIComponent()함수는 영 대문자와 소문자, 숫자, 그리고 *-_.을 제외한 모든 문자를 유니코드 형식으로 변환한다.

1BYTE 문자는 %XX, 2BYTE 문자는 %uXXXX 형태로...


그리고 이렇게 인코딩된 문자열을 사람이 읽을수 있는 형태로 원복할려면 decodeURIComponent()를 이용하면 된다.


아래는 예제코드이다.


<!DOCTYPE html>

<html>

<body>


<p>Click the button to encode a URI and for decoding also.</p>


<button onclick="myFunction()">Now Try it</button><br/><br/>


<hr/>

"developer&enginner"이라는 문자열을 encodeURIComponent()와 decodeURIComponent()를 이용해서 인코딩과 디코딩을 테스트해 봅니다.

<hr/>


<p/>인코딩 : <span  id="enco"></span>

<p/>디코딩 : <span id="deco"></span>

<P/>최종결과 : <span id="result"></span>


<script>

function myFunction() {

    var mURL = "http://www.xxx.xx/info?page=3&title=";

    var uri = "developer&enginner";

    var res = encodeURIComponent(uri);

    document.getElementById("enco").innerHTML = res;

    

    var dc = decodeURIComponent(res);

    document.getElementById("deco").innerHTML = dc;

    //alert("decoded : " + dc);

    

    var rt = mURL + res;

    document.getElementById("result").innerHTML = rt;

}

</script>


</body>

</html>


한글의 경우도 인코딩해서 보내고 받는 쪽에서 디코딩해서 처리하면 문제가 없을 것이다.

위 코드의 실행결과는 다음과 같이 나오게 될 것이다.


인코딩 : developer%26enginner


디코딩 : developer&enginner


최종결과 : http://www.xxx.xx/info?page=3&title=developer%26enginner


jQuery를 이용해서 콤보 박스 혹은 full-down 메뉴인 select 태그의 선택된(selected) 항목의 값 가져오기.


2가지 방법으로 처리해 보고자 한다.

첫 번째는 select 태그를 이용해서 값을 가져오는 방법과 두 번째는 select의 id를 이용해서 값을 가져오는 방법이다.

자세한 방법은 아래 코드에서...


<!DOCTYPE html>

<html>

<head>

<meta charset="EUC-KR">

<title>Insert title here</title>

<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>

</head>

<body>

<select name="name_Select" id="id_Select">

<option value="val1">txtVal1</option>

<option value="val2">txtVal2</option>

<option value="val3">txtVal3</option>

<option value="val4">txtVal4</option>

</select>

<hr/>

<button id="valFunc_tag">val 함수 using tag name</button><br/>

<button id="textFunc_tag">text 함수 using tag name</button>

<hr/>

<button id="valFunc_id">val 함수 using id</button><br/>

<button id="textFunc_id">text 함수 using id</button>

<script>

$(document).ready(function(){

$("#valFunc_tag").on("click", function(){

//select라는 태그 이름을 이용해서 select 박스를 선택한 후

// .val()함수로 값을 가져오면 option의 value 값을 가져온다. 

//따라서 val1, val2, val3...의 값을 가져온다.

var kkk = $("select option:selected").val();

alert(kkk);

});


$("#textFunc_tag").on("click", function(){

//select라는 태그 이름을 이용해서 select 박스를 선택한 후

// .text()함수로 값을 가져오면 option의 text 값을 가져온다. 

//따라서 txtVal1, txtVal2, txtVal3...의 값을 가져온다.

var kkk = $("select option:selected").text();

alert(kkk);

});

$("#valFunc_id").on("click", function(){

//아래의 경우는 select 박스의 id를 이용해서 select 박스를 선택하되

//나머지는 위의 설명과 같다.

var kkk = $("#id_Select option:selected").val();

alert(kkk);

});


$("#textFunc_id").on("click", function(){

var kkk = $("#id_Select option:selected").text();

alert(kkk);

});

});

</script>

</body>

</html>


'jQuery' 카테고리의 다른 글

부트스트랩의 모달 창 사용하기  (1) 2018.08.06
jQuery의 getJSON()과 each() 함수의 사용법  (0) 2018.08.02

+ Recent posts