2013년 4월 18일 목요일

[Spring] DWR

웹을 이용하다보면 사용자에게 편리하고 유용한 기술이 Ajax란 것을 느낄 수 있다. 그렇지만 동시에 개발자에게는 번거로운 작업이기도 하다. 자바스크립트에서 이벤트를 발생시키고 필요한 데이터를 서버에 전송하여 원하는 결과 값을 json이나 다른 형태의 데이터 포맷으로 가져오는 것이 단순히 웹을 리로딩시키는 것보다는 할 일이 많기 때문이다.

그런데 스프링에서는 굉장히 유용한 기술이 있다. DWR이 그것이다. DWR(Direct Web Remote)은 Ajax를 이용해서 자바스크립트에서 원격으로 서버의 자바객체를 호출할 수 있도록 해주는 자바 기반의 RPC라이브러리다. 자바스크립트에서 자바의 메서드를 호출한다는 것만으로도 대단한 기술이다.

또한 DWR은 서버 측의 결과 객체를 JSON형식으로 변환해 주기 때문에 더더욱 편리하다!

그렇지만 처음 사용하는 것 역시 어려움이 따르므로 어떠한 순서로 DWR을 적용시켜나가는지 살펴보도록 하자.

우선 dwr.jar라이브러리가 필요하다. dwr.jar파일을 추가하면 관련 코드를 xml에 추가해 주어야한다.

xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
http://www.directwebremoting.org/schema/spring-dwr
http://www.directwebremoting.org/schema/spring-dwr-2.0.xsd

xml설정 파일에는 자바스크립트로부터의 요청을 처리할 DWR컨트롤러를 <dwr:controller>태그를 이용해 설정해주어야한다. 그리고나서 컨트롤러가 처리할 요청에 대해 매핑이 필요한데 자세한 코드는 다음과 같다.

<!-- DWR Setting -->
<dwr:controller id="dwrController" debug="true">
<dwr:config-param name="crossDomainSessionSecurity" value="false"/>
</dwr:controller>
<bean id="handlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="alwaysUseFullPath" value="true"></property>
<property name="mappings">
<props>
<prop key="/dwr/engine.js">dwrController</prop>
<prop key="/dwr/**/*">dwrController</prop>
</props>
</property>
</bean>
<bean id="handlerMapping2" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean>

톰켓 7버전부터 단순히 <dwr:controller>를 이용한 컨트롤러 설정이 되지 않는다. 그 이유는 세션 보안과 관련한 문제를 발생시키기 때문이다. 그래서 <dwr:config-param>태그에 속성을 위와 같이 설정해 주어야한다.

그 다음으로 핸들러 매핑 객체를 만들고 있다. dwr을 사용하기 위해서 SimpleUrlhandlermapping클래스를 이용하여 핸들러를 사용할 것이다. 특히 <prop>태그에 경로를 항상 engine.js가 필요하다는 것을 명심해야 한다.

마지막으로 한가지 설정해주어야 할 것이 남았다. 지금까지 스프링을 활용하여 웹 어플리케이션을 제작하면서 @어노테이션 방식으로 컨트롤러를 등록하고 응답에 대한 핸들러를 등록하는 등 많은 설정을 처리해 주었는데 위와같이 SimpleUrlhandlerMapping이라는 매핑을 따로 설정해 줌으로써 기본적인 어노테이션 핸들러 매핑도 함께 설정해 주어야한다. 이렇게 해야만 기존에 사용하고 있던 어노테이션 설정을 변함없이 사용할 수 있으므로 꼭 기억해두자.

마지막 설정으로는 자바스크립트와의 실제 데이터를 주고 받을 클래스인 Dwr 객체를 만들어 주고 이 Dwr을 자바스크립트에서 사용할 수 있도록 <dwr:remote>라는 원격 태그를 지정해 준다. 

        <dwr:configuration>
<dwr:convert type="bean" class="kosta.model.Admin"></dwr:convert>
</dwr:configuration>
<bean id="adminDwr" class="kosta.dwr.AdminDwr">
<property name="admindao" ref="adminDao"></property>
<dwr:remote javascript="adminDwr"></dwr:remote>
</bean>

우선 <dwr:configuration>태그를 이용하여 자바객체를 원하는 형태로 변경할 수 있다. 위에서 보면 Admin클래스를 bean객체로 변환하라는 의미이고 dwr에서는 변환된 bean객체를 다시 JSON으로 변환하여 자바스크립트로 보낼 것이다.
<dwr:remote>태그를 보면 javascript속성을 확인 할 수 있는데 이 속성에 adminDwr이란 값을 넣어주었다. 이렇게 함으로써 자바스크립트에서는 adminDwr로 Dwr과 데이터 교환이 가능하다.

<script type="text/javascript" src="/spring_dwr_practice/dwr/engine.js"></script>
<script type="text/javascript" src="/spring_dwr_practice/dwr/interface/adminDwr.js"></script>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
adminDwr.adminList(show);
function show(data){//결과값이 도착하면 자동으로 호출되는 콜백함수
$.each(data, function(index, member){
var html = "<tr><td>" + member.mem_id + "</td><td>" + member.mem_name + "</td></tr>";
$("table tbody").append(html);
});
}
});
</script>

이제 자바스크립트에서 dwr을 호출할 수 있게 되었다. 먼저 <script>에 xml에서 컨트롤러에게 매핑해 주었던 engine.js와 javascipt에서 지정한 adminDwr라는 이름의 js도 지정해 주도록한다. 이렇게 프로젝트 경로로 매핑을 시킨 것이 SimpleUrlHandlerMapping방식이다.

이렇게 설정이 다 되었으면 이제부터 단순히 자바스크립트 코드에 adminDwr을 이용하여 AdminDwr클래스에 존재하는 메서드나 멤버변수를 호출할 수 있다.

adminDwr.adminList(show) 는 AdminDwr클래스의 adminList함수를 호출하는 것이고 인자로 show라는 함수를 넣어준다는 것을 기억하자. show함수는 콜백함수로써 adminList()메서드의 결과값을 자동적으로 리턴받아 처리할 수 있다. 이때 얻은 결과값은 앞서 언급했던 JSON데이터 포맷을 가지고 있음으로 키와 값으로 데이터를 접근할 수 있다.

2013년 4월 14일 일요일

[Spring] ibatis

앞에서 스프링을 이용하여 좀 더 쉬운 DB연동을 살펴 보았다. 상당히 많은 양의 중복 코드를 줄인 것을 알 수 있다.

그러나 지금 언급하고자 하는 ibatis는 DB와의 연동 시 코드의 양을 더욱 많이 줄여줄 수 있다! 단순히 XML을 사용하여 SQL statement에 매핑이 가능하다. 때문에 JDBC로만 프로그래밍 할때의 번거로움이 상당히 줄어드는 것이다.

그만큼 유용한 프레임워크인 ibatis에 대해 알아보도록하자.

ibatis는 sql 실행 결과를 자바빈즈 혹은 Map객체에 매핑해 주는 솔루션으로 sql을 소스코드가 아닌 XML로 따로 분리해 관리하도록 지원한다. 따라서 복잡한 sql을 작성하기가 수월하고 코드의 분리로 유지보수가 좀 더 간편하다. 왜냐하면 DAO자바 코드에서는 순수하게 자바 코드만을 관리하고 sql문은 따로 XML파일로 관리할 수 있기 때문에 서로의 관계를 느슨하게 만들 수 있기 때문이다.

ibatis를 사용하기 위해서는 ibatis라이브러리를 자신의 웹 어플리케이션 lib폴더에 넣어두는 것을 잊지말자. 그런다음 ibatis 사용을 위한 xml파일을 설정해 주어야한다.

2가지의 XML파일만 설정하면 된다.
첫 번째는 DataBase의 환경을 설정하는 XML이고 두 번째는 사용될 Query를 저장하는 XML파일이다. 우선 Database 환경 설정 XML파일에 <sqlMapConfig>태그를 안에 <transactionManger>태그를 사용하고 속성으로 type을 준다.
예)//////////////////////////////DB설정 XML/////////////////////////////////////////

<sqlMapConfig>

  <transactionManager type="JDBC" commitRequired="false">
    <dataSource type="JNDI">
    <property name="DataSource" value="java:comp/env/jdbc/oracle"/>
    </dataSource>
  </transactionManager>

  <sqlMap resource="kosta/ibatis/Board.xml"/>

</sqlMapConfig>

위 코드는 JDBC타입으로 JNDI네이밍 방식을 사용한다. sqlMapConfig는 ibatis에서 JDBC를 처리하기 위해 필요한 사항을 설정하며 Transaction 관리 정보, DataSource Factory와 sqlMap 파일의 위치를 기술하게 된다.

다음으로는 Query를 지정한 XML파일을 로드해 주어야 하는데 <sqlMap>이라는 태그를 사용하여 루트를 지정해 준다.

예)//////////////////////////////SQL문 설정 XML//////////////////////////////////////

<sqlMap>

<typeAlias alias="Board" type="kosta.model.Board"/>
<typeAlias alias="Search" type="kosta.model.Search"/>

<insert id="insertBoard" parameterClass="Board">
insert into Board values(
board_seq.NEXTVAL,
#title#,
#writer#,
#contents#,
sysdate,
0)
</insert>

<select id="searchBoard" parameterClass="Search" resultClass="Board">
select * from board
<dynamic prepend="where">
<iterate property="areas" conjunction="or" open="(" close=")">
$areas[]$ like #searchKey#
</iterate>
</dynamic>
order by seq desc
</select>

</sqlMap>

위의 sql문을 설정한 XML파일의 내용이다. DTO에 쿼리 결과를 담기 위해서는 위에 보이는 것과 같이 해당 클래스의 <typeAlias>를 지정해야한다. 그런다음 SQL문 태그들을 이용하여 데이터베이스의 데이터들을 관리할 수 있게 된다.

sql문을 사용하기 위한 태그를 살펴보면 태그의 속성에 id와 parameterClass, resultClass가 존재한다는 것을 알 수 있다. id는 Dao에서 호출할 sql문의 이름이다. parameterClass는 입력될 객체를 의미한다. ibatis에는 객체나 프리미티브 타입, 해쉬맵 등의 데이터를 인자값으로 넘겨 줄 수 있다. resultClass는 query의 결과를 담을 데이터를 말하며 resultClass일 경우 객체로 결과를 담는다는 것이다. resultMap을 이용하여 객체를 받을 수 있는데 특히 데이터베이스의 컬럼명과 클래스의 멤버변수명이 다를 때 그 이름을 새롭게 패핑하여 결과값을 얻을 때 사용한다.

위의 이러한 과정을 그림으로 나타내면 다음과 같다.




요약하자면 SqlMapConfig설정파일을 통해 데이터베이스의 Resource를 구하고 사용할 sql문과 sql문의 입력된 데이터와 출력데이터간의 매핑을 처리해주도록 설정한 SqlMap파일을 로드하도록 한다.

그런다음 설정한 SqlMap을 사용하기 위해 SqlMapClient interface를 얻도록 해야한다. 그 코드는 아래와 같다.







Reader reader = Resources.getResourceAsReader("로드할 SqlMapConfig파일 위치");
sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);

동적쿼리문
디비를 활용하다보면 로직에 따라 sql문이 수시로 변경되어야할 경우가 많다. ibatis에서는 로직에 따른 동적쿼리문에 대한 태그를 제공한다.

<dynamic>태그
가장 상위의 태그이고 접두/접미 구문을 위한 수단을 제공한다.
- prepend : 맨 앞에 접두 구문을 붙인다.
- open : body의 내용 앞에 붙여짐. body의 내용이 없을 경우 생략. prepend와 동시에 정의될 경우 prepend 다음에 나타남.
- close : body의 내용 뒤에 붙여짐. body의 내용이 없을 경우 생략.

비교태그
주어진 parameter 객체간의 property값을 비교한다.
- property(필수) : parameter 객체의 property, compareValue 또는 compareProperty를 이용해 데이터 비교
- prepend(옵션) : 접두 구문 추가. 다만 생략되는 경우가 있다. 1. body의 내용이 없는 경우 2. 부모 태그의 속성이 removeFirstPrepend = "true"이고 현재 부모 태그가 부모 body의 첫 번째 요소인 경우
- open(옵션) : <dynamic>태그와 동일
- close(옵션) : <dynamic>태그와 동일
- removeFirstPrepend(옵션) : 첫 번째 자식 태그의 prepend를 생략시킴
- compareProperty : property와 비교할 property
- compareValue : property속성에 의해 비교되는 값(상수)
- <isEqual> : property속성과 compareProperty / compareValue속성이 같은지 비교
- <isNotEqal> : 다른지 비교
- <isGreaterThan> : 큰지 비교
- <isGreaterEqual> : 크거나 같은지 비교
- <isLessThan> : 작은지 비교
- <isLessEqual> : 작거나 같은지 비교

단항태그
주어진 특정 property에 대한 태그
- <isPropertyAvailable> : 특정 property가 존재하는지 체크(Map의 경우 key가 존재하는지 체크)
- <isNotPropertyAvailable> : 특정 property가 존재하지 않는지 체크
- <isNull> 특정 property가 null인지 체크
- <isNotNull> 특정 property가 null이 아닌지 체크
- <isEmpty> 특정 property가 null이거나 비어있는지 체크
- <isNotEmpty> 특정 property가 null이 아니고 비어있는지 체크

Parameter 태그
- <isParameterPresent> : 파라미터가 존재하는지 체크
- <isNotParameterPresent> : 파라미터가 존재하지 않는지 체크

interate태그
Collection 형태의 property로써 sql문의 반복적인 구간 생성
- conjunction : 반복되는 sql문 사이에 구분자로 들어감 (예: ',' or, and 등등)


[Spring] validator

프로그램을 제작하다보면 유효성검사를 할 경우가 굉장히 많다. 특히 웹 어플리케이션에서 사용자의 입력을 받는 경우에 유효성검사를 많이 필요로한다.

생각해보자. 항상 사용자가 개발자가 원하는 데이터값을 입력할까????? 그건 전혀 예측할 수 없는 일이다. 개발자가 무엇을 생각하고 무엇을 요구하는지 사용자는 알고 싶어하지 않는다. 이럴경우 유효성검사가 참 유용하다. 그리고 웹에서 국제화를 위해서도 사용된다. 영어, 일어, 중국어 등 다양한 언어로 서비스를 제공하고 싶다면 유효성 검사방법을 잘 알아두도록 하자.

스프링에는 유효성 검사를 위한 기능을 제공하고 있다. 우선 validator 인터페이스를 implements 한 자바 클래스가 필요하다. 이 클래스를 활용하여 form에서 넘어온 데이터의 유효성을 검사할 것이다. 코드는 다음과 같다.
예)
public class BoardValidator implements Validator {

@Override
public boolean supports(Class<?> arg0) {
// TODO Auto-generated method stub
if(Board.class.isAssignableFrom(arg0)){
return true;
}
return false;
}

@Override
public void validate(Object arg0, Errors errors) {
// TODO Auto-generated method stub
Board board = (Board)arg0;

if(board.getTitle() == null || board.getTitle().length() < 6){
errors.rejectValue("title", "required");
}
if(board.getWriter() == null || board.getWriter().length() < 6){
errors.rejectValue("writer", "required");
}
}
}


 우선 폼으로부터 넘어온 객체가 맞는지 확인한다. 여기서 ture를 반환하면 아래 validate함수를 수행하여 휴효성을 검사하게 된다. 여기서 만약 에러를 반환한다면 미리 지정해둔 메세지를 가지고 폼으로 돌아가도록 설정할 것이다. 일단 메세지 등록에 대해 살펴보자.
예)
required.title = bad title
required.writer = bad writer


properties파일에 등록한 간단한 메세지이다. 이 메세지를 얻기 위해 앞서 설명한 코드에서 rejectValue()의 인자로 해당하는 메세지의 문자열을 넘겨준 것이다.

여기까지는 단순한 로직처리일 뿐이다. 스프링에서 이 로직들을 처리하기 위해서는 항상 DispatcherServlet에 bean으로 객체를 등록해 주어야한다는 것을 잊지말자.
예)
<!-- VALIDATOR -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="message.validation"></property>
</bean>

<bean id="boardValidator" class="kosta.validator.BoardValidator"></bean>


ResourceBundleMessageSource클래스의 객체를 이용해 메세지를 읽도록 하고 유효성검사를 하는 validator도 객체로 만들어 둔다. 이 객체를 사용할 DispatcherServlet에다가 넣어주고 있다.

마지막으로 에러가 발생했을 때 해당하는 메세지를 가지고 화면에 뿌려주도록하기 위해서 spring에서 제공하는 태그를 이용한다.
예)
<spring:hasBindErrors name="commend"></spring:hasBindErrors>
<center>
<h1>글쓰기폼</h1>
<form action="board_insert.do" method="post">
작성자:<input type="text" name="writer"/><form:errors path="commend.writer"></form:errors><br>
&nbsp;제목:&nbsp;&nbsp;<input type="text" name="title"/><form:errors path="commend.title"></form:errors><br>
내용<br><textarea name="contents" rows="6" cols="30"></textarea><br>
<input type="submit" value="등록"/><br>
</form>
</center>


2013년 4월 11일 목요일

[Sping] Spring DB연동

스프링에는 데이터를 얻거나 객체와의 연동을 할 때 꼭 한가지 방법만 존재하는 것은 아니다. DB와의 연동도 마찬가지도 여기서는 jndi네이밍방식으로 DataSource를 구한다음 JdbcTemplet을 객체를 이용하여 DB를 연동해보도록 하겠다.


DataSource를 가져오기위해 우선 server에서 server.xml 설정파일에 DB를 연동하고자 하는 어플리케이션 context에 다음과 같은 코드를 넣어주어야한다.

<Resource auth="Container" driverClassName="oracle.jdbc.driver.OracleDriver" maxActive="100" maxIdle="30" maxWait="10000" name="jdbc/oracle" password="1234" type="javax.sql.DataSource" url="jdbc:oracle:thin:@localhost:1521:XE" username="board"/>


<!-- DB Setting -->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/oracle"></property>
<property name="resourceRef" value="true"></property>
</bean>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>

위에보면 빈 객체가 두개 있는 것을 알 수 있는데 처음에 필요한 객체는 dataSource객체이다. JndiObjectFactoryBean클래스로 만들어진 객체로써 속성으로 jndiName과 resourceRef가 있는데 jndiName에는 자신이 사용하고 있는 데이터베이스의 이름이고 resourceRef는 true로 값을 지정해주어야한다.

이렇게 하여 JdbcTemplate 객체를 얻을 수 있는데 이 객체를 이용하여 DB에 SQL문을 실행할 수 있게 된다. 그러므로 당연히 DB와의 연동이 필요한 Dao클래스에 JdbcTemplate 객체를 bean을 통해 의존 관계를 설정해 주어야겠다.

그리고 마지막으로 Dao를 직접적으로 호출할 Controller에도 dao 객체를 넣어주는 것을 잊지말자!


2013년 4월 10일 수요일

[Spring] MVC 흐름

이번에는 스프링을 이용하여 모델 2방식인 MVC의 흐름을 알아보도록 하자.

위의 그림은 MVC의 흐름을 한눈에 살펴볼 수 있도록 되어있다.

순서대로 하나씩 따라가보자.
1. Client의 요청은 항상 DispatcherServlet으로 전달되며 MVC에 있어서 컨트롤타워라고 생각하면 된다. DispatcherServlet이 MVC의 흐름을 총괄하며 다른 컴포넌트에게 해야할 일을 위임한다.
2. 1번으로부터 받은 Client의 요청에 대해 DispatcherServlet은 HandlerMapping을 통해 어떠한 Controller에게 비즈니스로직을 처리해야하는지 문의하게 된다.
3. HandlerMapping을 통해 해당하는 로직을 처리할 Controller에게 요청을 전송하고 Controller는 요청을 처리한다.
4. Controller에 의해 처리된 그 결과를 ModelAndView객체에 실어 응답한다.
5. ViewResolver에 의해 어떠한 뷰를 보여줄 것인지 결정한다.
6. 해당하는 결과를 화면에 표현한다.

위와 같은 일련의 과정을 잘 이해하도록하자!!! 이러한 흐름을 잘 이해하면서 실제로 MVC패턴을 이용한 어플리케이션을 만들어보자.
1. 가장 먼저 web.xml 설정 파일에 웹 어플리케이션에서 사용한 DispatcherServlet을 등록해야한다. 그리고 만약 DispatcherServlet 설정파일이 springapp-servlet.xml이라면 파일이름 중 앞단어를 이용하여 등록시켜야 한다.
예)
<servlet>
    <servlet-name>springapp</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
</servlet>

이어서 어떤 요청에 대해 DispatcherServlet이 처리할 것인가를 명시해 줄 필요가 있다. 따라서 매핑의 과정이 추가된다.
<servlet-mapping>
    <servlet-name>springapp</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

이렇게 함으로써 .do라는 요청들은 모두 DispatcherServlet이 처리할 것이라는 설정이 완료된다.
2. DispatcherServlet 클래스를 만들어 어노테이션 방식으로 @Controller를 등록하고 WebApplicationContext 설정파일을 이용하여 필요한 객체를 DI기법으로 얻는다.
3. DispatcherServlet 클래스에 어노테이션 방식을 이용하여 @RequestMapping로 요청에 대한 Controller(메소드)를 구현하고 매핑한다. (지금은 디폴트 어노테이션 핸들러 매핑 방식을 사용하겠지만 스프링에는 더 다양한 방법이 여러개 존재한다는 것을 알아두자)
4. Controller를 통해 처리된 데이터는 ModelAndView 객체에 담고 ViewResolver를 통해 뷰를 선택한다.
5. 결과를 출력한다.

만약 여러개의 DispatcherServlet을 설정해야 한다.면 ContextLoaderListener로 설정한다.

2013년 4월 8일 월요일

[Spring] AOP(Aspect Oriented Programming)

로직 중에는 핵심적으로 수행되는 로직과 공통으로 수행되는 로직이 존재한다. 특히 공통적으로 사용되는 기능은 로깅, 트랜잭션, 보안 등이 존재한다.

공통적으로 수행되는 로직은 아무리 단순할지라도 많은 곳에서 사용되어지면 그만큼 중복된 코드가 많아지게되고 관계가 복잡해 진다. 이러한 현상을 극복하기 위해 AOP가 등장하였다.

AOP를 가장 잘 설명해 주는 그림이다. CourseService, StudentService 그리고 MiscService가 핵심 관심 사항이고 항상 보안, 트랜잭션 등의 공통 관심 사항에 필요한 로직을 셋 다 수행하도록 되어있다.
만약 핵심 관심 사항이 늘어나거나 공통 관심 사항이 늘어날 경우에 굉장히 불필요하고 번거로운 작업이 많이 생기게 된다. 예를 들어 각각의 핵심 관심 사항에 일일이 공통 관심 사항을 설정한다는 것은 엄청난 시간과 에너지 소비일 것이다.

그러나 AOP에서는 핵심 로직을 구현한 클래스를 실행하기 전, 후에 공통 로직을 여러클래스에 미리 적용시켜 놓음으로써 번거로운 작업을 줄일 수 있다.

우선 공통 관심 사항을 구현해보자.
예)

public class LoggingAspect {
private Log log = LogFactory.getLog(getClass());

public Object logging(ProceedingJoinPoint jointPoint) throws Throwable{
log.info("기록시작");//proceed 이전에 실행
StopWatch stopWatch = new StopWatch();
try{
stopWatch.start();
Object obj = jointPoint.proceed();//실제 비지니스 메서드 호출 시점
return obj;
}catch(Throwable e){
throw e;
}finally{
stopWatch.stop();//proceed 이후에 실행
log.info("기록 종료");
log.info(jointPoint.getSignature().getName() + "메서드 실행 시간 : " + stopWatch.getTotalTimeMillis());

}
}
}
위와 같은 코드로 원하는 모든 핵심 로직에 기록을 시작하고 종료할 수 있다. jointPoint.proceed()는 핵심 로직이 수행되는 시점이다.

위에 구현한 클래스를 적용시키기 위해 XML파일 설정이 필요하다.

예) AOP설정 파일(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" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans   
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

<bean id="logAspect" class="kosta.LoggingAspect"></bean>

<aop:config>
<aop:pointcut expression="execution(public * kosta..*ServiceImple.*(..))"
id="servicePointcut" />
<aop:aspect id="loggingAspect" ref="logAspect">
<aop:around method="logging" pointcut-ref="servicePointcut" />
</aop:aspect>
</aop:config>

</beans>
이미 구현한 로깅 공통 관심 사항 객체를 설정한다.
aop태그를 통해 로깅의 대상이 될 메소드의 범주를 설정하고 로깅 객체를 참조한다. 그리고 대상 메소드가 호출될 때 로깅 메소드가 호출될 시점을 설정한다.

코드만으로 이해하기 어려울 수 있으니 AOP용어에 대해 살펴보자.
Aspect : 공통 관심 사항(예 : 트랜잭션, 로깅, 보안 등)
JoinPoint : Aspect가 적용 될 수 있는 지점(예: 메소드, 필드)
Poincut : 공통 관심 사항이 적용될 JoinPoint
Advice : 어느 시점에 어떤 공통 관심 기능을 적용할지 정의
Weaving : 어떤 Advice를 어떤 Pointcut에 적용시킬 것인지에 대한 설정



[Spring] DI(Dependency Injection)

DI는 스프링 컨테이너가 지원하는 핵심 개념 중 하나이다. 객체 간의 의존 관계를 객체 자신이 아닌 외부의 조립기가 수행해 준다는 개념이다.

예를 들면 A라는 클래스에서 B라는 클래스의 객체가 필요한 경우 보통은 A클래스 안에서 B라는 객체를 new키워드로 생성하거나 singleton방식으로 객체를 얻는 방식을 많이 사용한다.

하지만 문제점은 이들 A와 B의 결합도가 높아진다는 것이다. 이로 인해 의존하는 클래스 B가 변경되는 경우 A의 코드를 변경해야 하는 문제가 있다. 이처럼 하나의 변경으로 인해 의존하는 다른 부분들의 수정이 불가피한 경우가 많을 수록 서로의 의존도, 즉 결합도가 높다는 것이다.

new키워드의 문제점이 의존 클래스가 변경되면 코드를 변경하는 것이고 또한 단위 테스트를 하기 위해서는 실행에 필요한 올바른 객체가 존재해야한다. (단위 테스트는 코드의 품질을 향상시키고 개발 속도를 증가시키는데 필요하다.)
singleton방식에서는 의존 클래스의 변경에 의한 문제점은 해결할 수 있지만 new키워드와 같이 올바르게 동작하는 객체가 있어야만 단위 테스트가 가능하다는 문제가 존재한다.

이러한 문제점들을 해결하기 위해 DI개념을 사용하는 것이다.

객체간의 의존관계를 객체가 아니라 외부의 조립기가 수행하는 것을 의미한다. 이 의존관계는 클래스의 변경으로 인한 수정이 필요하지 않고 구현 클래스에 대한 차이를 모르는 채 서로 다른 구현으로 대체가 가능하다는 점에서 모든 문제를 해결할 수 있다.

스프링 DI
스프링은 설정 파일과 어노테이션을 이용하여 객체 간의 의존 관계를 설정하는 기능을 제공하여 객체 조립기를 사용할 수 있다.

예) 스프링 설정 파일(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-2.5.xsd">

<bean id="dao" class="kosta.MySQLDao"></bean>

<bean id="service" class="kosta.WriteServiceImple">
<constructor-arg ref="dao"/>
</bean>
</beans>

스프링 설정 파일은 Application에서 사용할 Spring 자원들을 설정하는 파일이며 XML기반이다.

위에 코드는 bean태그를 이용하여 객체를 설정해주고 있다. 특히 constructor-arg 태그를 이용하여 생성자에 이미 설정해둔 dao객체를 전달해 줌으로써 의존 관계를 설정하고 있다.

<bean>태그 기본속성
name - 호출할 이름 설정
id - 호출할 이름 설정
class - 생성될 객체의 클래스
factory-method : singleton패턴으로 작성된 객체의 factory메소드 호출 시

이렇게 설정파일을 작성한 뒤 스프링을 이용하여 설정 파일을 로딩하고 객체를 얻는다.

예) 스프링 설정 파일을 로드하고 BeanFactory를 생성한 뒤, 필요한 객체를 가져오는 코드-------

public class Main {
public static void main(String[] args){
Resource resource = new ClassPathResource("applicationContext.xml");
BeanFactory factory = new XmlBeanFactory(resource);
Service service = (Service)factory.getBean("service");
service.insert();
}
}
factory.getBean("id")로 설정 파일에서 이미 설정해둔 빈 객체들을 가져올 수 있다. 이러한 방법을 통해 느슨한 의존 관계를 설정하게 되고 이는 코드의 변경이나 테스트의 어려움을 줄이는데 유용한 개념이다.

[Spring] 스프링 프레임 워크

2주간 프로젝트를 마치고 이어서 스프링 프레임 워크에 대해 알아보자. 처음 공부하기는 상당히 어려운 부분이 많고 특히 혼자서 이해하기가 난해한 부분이 없지 않다. 그렇지만 스프링의 핵심기술 DI, AOP, MVC를 꼭 이해하도록 하자. 이를위해 우선 스프링에 대해 전반적으로 살펴보도록 하겠다. 그리고 조금씩 심화시켜나가면서 스프링에 대해 알아갈 것이다.

기존에는 JSP를 활용한 모델 1방식으로 프로젝트를 진행해보았다. 모델 1방식은 JSP와 Java Bean을 이용하여 웹 어플리케이션을 개발하는 방법을 말한다.
모델 1방식으로 개발하면 배우기가 쉬워 누구가 쉽게 만들 수 있고 때문에 개발 속도가 향상되는 장점이 있지만 큰 문제점은 JSP에서 너무 많은 코드들이 혼재되어 있고 따라서 JSP가 처리해야하는 일이 많아진다. 따라서 개발자는 유지보수의 어려움을 겪게되는 문제가 있다.

한번 만들어진 프로젝트는 오랜시간동안 서비스를 하기위해 유지보수가 필수이다. 이 유지보수를 어렵게 만든다는 점에서 개발을 위한 새로운 방법이 필요했다.

이러한 문제점 때문에 웹 어플리케이션이 복잡해지고 사용자 요구가 증가함에 따라 새로운 개발방식을 요구하게 되는데 그것이 현재 모델 2방식이다.


모델 2방식
어플리케이션을 Model - View - Controller로 분리하여 개발하는 방식을 말한다.
Model : 비즈니스 로직을 담당하며 Java Bean과의 연동을 통해 로직을 처리한다.
View : JSP로 Client에게 응답을 처리한다. 즉, 모델 1방식에서 가장 많은 역할을 해야했던 JSP는 오로지 요청에 대한 응답 페이지의 출력을 목적으로만 사용한다.
Controller : 서블릿을 이용하여 클라이언트의 요청을 받아 Model과 View사이에서 일의 흐름을 조정한다.

모델 2방식에서는 컨트롤러의 역할이 중요하다. 때문에 컨트롤러의 역할을 살펴보자면
1. 클라이언트의 요청을 받아 클라이언트가 보낸 데이터를 읽고 검사한다.
2. 모델에게 비즈니즈 로직을 처리해달라고 요청한다.
3. 모델의 처리 결과에 맞는 뷰에게 응답을 요청한다.

그렇다면 모델 2방식의 장단점에 대해 알아보자.
장점 : 비즈니스 로직과 프레젠테이션의 분리로 인해 어플리케이션이 명료해지며 유지보수와 확장이 용이하다. 따라서 디자이너와 개발자의 작업을 분리해 줄 수 있다.
단점 : 개발을 위한 설계로 인해 개발 기간이 늘어나고 MVC 구조에 대한 이해가 동반된다.

자 이제 왜 모델 2방식을 이용한 웹 어플리케이션이 필요한지 어느정도 감이 올 것이다. 스프링은 모델 2방식인 MVC구조에 대한 프레임워크를 제공하고 있으며 나아가 다양한 프레임워크와 연동을 지원하기 때문에 많은 개발자들이 배우고 있는 프레임워크이다.

그렇다면 프레임워크는 무엇이며 라이브러리와는 어떤 차이가 있을까?

라이브러리는 개발자가 원하는 목적을 위해 사용되는 API들의 묶음으로 개발자가 자신에게 필요한 것을 스스로 설정하면서 프로그램을 구현해나갈 수 있는 유용한 자료이다. 프레임 워크는 개발에 있어서 어느정도의 틀을 미리 제공하고 있다. 따라서 개발자가 처음부터 모든 것을 구현할 필요가 없다. 어느정도의 프로세스가 이미 정해져있다는 것이다.

개발자에게 있어서 프레임워크는 어떤 존재인지 생각해보자. 지금처럼 대규모의 프로젝트가 산적해있는 상황에서는 개발의 속도가 필요하다. 그렇기 때문에 하나하나씩 모든 것을 구현해 나가며 단독으로 프로젝트를 진행하는 것은 의미가 없다. 빠르게 많은 코드를 제작해 나가야 함에 있어서 프레임워크가 필수적이고 개발자마다 다른 코드 스타일을 적응해가면서 개발하는 것도 쉽지 않다. 하지만 이렇게 정해진 틀이 제공된다면 대규모 프로젝트를 진행하는데 도움이 될 것이라는 것은 당연하다.

현재 웹 어플리케이션 제작에 있어서 가장 많이 사용되는 프레임워크가 스프링이다.

스프링이란 오픈 소스 프레임워크로써 엔터프라이즈 어플리케이션 개발의 복잡성을 줄여주고 필요한 기능을 제공하기 위한 목적으로 만들어졌다. 특히 과거에 많이 사용되던 EJB의 복잡성과 느린 속도를 대처하기 위해 등장하였다.

스프링 장점
- 경향 컨테이너로써 객체의 라이프 사이클을 관리, JEE구현을 위한 다양한 API제공
- DI 지원, 설정 파일이나 어노테이션을 통해서 객체 간의 의존 관계를 설정
- AOP지원, 트랜잭션이나 로깅, 보안과 같은 공통으로 필요한 기능들을 분리해서 원하는 모듈에 적용
- POJO지원, 특정한 인터페이스를 구현하거나 클래스를 상속받지 않아 기존에 작성한 코드를 그대로 사용
- JDBC를 위한 다양한 API지원
- Transaction 처리를 위한 일관된 방법제공
- 다양한 API와의 연동 지원

장점을 보면 DI나 AOP 등등 처음 보는 개념을 많을텐데 하나씩 알아가도록하자. 개발자를 위해서 제공되는 아주 좋은 기술이다!

2013년 3월 18일 월요일

[JSP] 게시판 만들기!

게시판을 배워보는 것은 프로그래밍의 필수적인 요소를 모두 익힐 수 있는 좋은 과정이다.

그 이유는 게시물을 생성(Create), 읽기(Read), 수정(Update), 삭제(Delete) 하면서 데이터의 흐름을 이해하고 어떻게 데이터를 전달하고 저장하는지에 대해 전반적으로 알아갈 수 있기 때문이다. 프로그래밍 실력을 키울 수 있는 좋은 예인 것이다.

제작할 게시판에는 다음과 같은 기능을 추가할 것이다.
1. 답글
2. 페이지 처리
3. 검색
4. 파일 업/다운
5. 이미지 게시판

지금까지 배운 JSP를 위주로 구현해 나갈 것이며 EL, JSTL태그도 많이 사용할 것이다.

코드를 위주로 알아보자.
우선 게시판을 위한 DB 테이블이 필요하다.

create table board(
b_id number(5) primary key,
b_name varchar2(20),
b_title varchar2(50),
b_content varchar2(3000),
b_pwd varchar2(10),
b_date date,
b_hit number(5) default 0,
b_ref number(5),
b_step number(5),
b_level number(5),
b_parentid number(5)
)

보통 게시판에 글을 올릴 때 필요한 데이터를 확인할 수 있다. 그러나 ref, step, level, parent라는 컬럼에 대해서는 의아할 것이다. 이 컬럼들은 해당하는 글의 답글을 달기 위해 필요한 요소이다.

ref : 부모의 그룹번호
step : 부모의 글을 기준으로 순서 결정
level : 답글을 나타내는 들여쓰기를 위한 속성
parentid : 부모의 글 번호

다음으로 게시판에 삽입될 하나의 글 객체를 위한 클래스이다.
public class Board {
private int b_id;
private String b_name;
private String b_title;
private String b_content;
private String b_pwd;
private Timestamp b_date;
private int b_hit;
private int b_ref;
private int b_step;
private int b_level;
private int b_parentid;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
글 하나를 게시판에 삽입할 Dao클래스
//////////////////////////////////////////////////////////////////////////////////////////////////
public class BoardDao {
private static BoardDao dao = new BoardDao();

public static BoardDao getInstance() {
return dao;
}

public Connection getConnection() throws Exception {
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/oracle");
return ds.getConnection();
}

public int insertBoard(Board board) {
int re = -1;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "";
int number = 0;// 글번호를 저장

int b_id = board.getB_id();
int b_ref = board.getB_ref();
int b_step = board.getB_step();
int b_level = board.getB_level();
int b_parentid = board.getB_parentid();

try {
con = getConnection();
// 글번호를 미리 생성
sql = "select max(b_id) from board";
pstmt = con.prepareStatement(sql);
rs = pstmt.executeQuery();

if (rs.next()) {
number = rs.getInt(1) + 1;// 현재 작성한 글번호를 이전에 작성한 글에 +1을 해서 구한다
}
// 답변글일 때
if (b_id != 0) {
sql = "update board set b_step = b_step + 1 where b_ref = ? AND b_step > ?";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, b_ref);
pstmt.setInt(2, b_step);
pstmt.executeUpdate();

b_step = b_step + 1;// 나의 b_step
b_level = b_level + 1;// 나의 b_level
b_parentid = b_id;// 나의 b_parentid
} else {
// 원본글일 때
b_ref = number;
b_step = 0;
b_level = 0;
b_parentid = 0;
}

sql = "insert into board values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, number);
pstmt.setString(2, board.getB_name());
pstmt.setString(3, board.getB_title());
pstmt.setString(4, board.getB_content());
pstmt.setString(5, board.getB_pwd());
pstmt.setTimestamp(6, board.getB_date());
pstmt.setInt(7, board.getB_hit());
pstmt.setInt(8, b_ref);
pstmt.setInt(9, b_step);
pstmt.setInt(10, b_level);
pstmt.setInt(11, b_parentid);

re = pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rs != null) {
rs.close();
}
if (pstmt != null) {
pstmt.close();
}
if (con != null) {
con.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return re;
}

게시물 등록 메서드이다. 나머지는 조금씩의 수정이 필요.

[JSP] 필터

필터는 JSP/서블릿 등을 실행하기 이전에 요청이 올바른지 또는 자원에 접근할 수 있는 권한을 가졌는지의 여부를 미리 처리할 수 있도록 해주며, JSP나 서블릿이 생성한 응답 데이터를 변경하거나 취소할 수 있는 기능을 구현할 수 있도록 해준다.

2013년 3월 16일 토요일

[JSP] 쿠키와 세션

http은 웹 상에서 html화면을 브라우저로 보여주는 기능에 최적화 되어 있는 프로토콜이다. 이 프로토콜 덕분에 브라우저를 이용하여 인터넷을 사용하는데 전혀 무리가 없는 것이다.

그런데 이 프로토콜에 한가지 맹점이 있다. 그것은 웹 서버에서 사용자를 식별하거나 접속을 유지하고 있다는 사실을 인지하지 못하는 것이다.

이러한 문제점을 해결하기 위해 쿠키와 세션을 사용한다. 쿠키를 활용하면 클라이언트가 웹 서버에 요청할 때 쿠키를 함께 전달하여 서버가 사용자의 정보를 읽어올 수 있으며 서버에 세션을 활용하여 사용자의 접속상태를 확인해 줄 수 있다.

우선 쿠키에 대해 알아보자.

쿠키
- 웹 브라우저가 보관하고 있는 데이터로서, 웹 브라우저가 웹 서버에 요청을 보낼 때 쿠키를 함께 전송한다.

쿠키의 구성
이름 - 쿠쿠를 구별하는데 사용되는 이름
값 - 쿠키의 이름으로 얻을 수 있는 데이터
유효 시간 - 쿠키의 유지 시간
도메인  - 쿠키를 전송할 도메인
경로 - 쿠키를 전송할 요청 경로

쿠키 생성 후 전달
Cookie cookie = new Cookie("cookieName", "cookieValue");
response.addCookie(cookie);

쿠키 값 읽어오기
Cookie[] cookies = request.getCookie();
request 객체를 통하여 쿠키배열을 얻을 수 있다. 전송된 쿠키를 활용하기 전 항상 null인지 확인하도록 하자.

쿠키 값 변경
Cookie cookie = new Cookie("기존의 이름", "새로운 값");

쿠키 삭제 및 유효시간 설정
cookie.setMaxAge(0);//삭제
cookie.setMaxAge(60*60);//1시간 설정

도메인 설정
cookie.setDomain(".somehost.com"); www.somehost.com이나 mail.somehost.com과 같은 모든 호스트로 쿠키 전송

경로 설정
cookie.setPath("원하는 경로");


세션
- 세션은 웹 브라우저에 정보를 웹 컨테이너에 보관할 때 사용된다. 즉, 서버에서만 생성된다. 세션은 웹 브라우저마다 따로 존재하기 때문에 웹 브라우저와 관련된 1 대 1 정보를 저장하기에 알맞은 장소다. 또한 쿠키보다는 세션을 더 많이 사용하는데 가장 큰 이유는 보안 때문이다. 쿠키의 경우 웹 브라우저로부터 데이터를 전달시 중간에서 누군가에 의해 쿠키의 값을 읽을 수 있다. 하지만 세션은 서버에 데이터를 저장하기 때문에 그러한 문제점이 없다.

JSP에서는 session이 보통 내장 객체로 제공되기 때문에 쉽게 사용할 수 있다.

session 메서드
getId() : 세션의 고유 ID를 얻음
getCreationTime() : 세션이 생성된 시간을 구함
getLastAccessedTime() : 웹 브라우저가 가장 마지막에 세션을 접근한 시간
session.setAttribute("이름", "값");//세션에 이름으로 값을 저장
session.getAttribute("이름");//세션에서 이름이르 값을 얻음
session.invalidate();//세션 종료
session.setMaxInactiveInterval(60*60);//세션의 유효 시간을 1시간으로 설정(default로 30분)

2013년 3월 14일 목요일

[JSP] JSTL

JSTL은 유용한 커스텀 액션을 포함하고 있는 라이브러리이며, 이 라이브러리를 통한 액션 태그를 사용하여 JSP에 스크립틀릿과 같은 자바코드를 줄일 수 있다.

JSTL을 가지고 변수를 선언하고 if문, for문 등의 간단한 로직을 구현할 수 있으며 다른 JSP페이지를 호출하고 날짜, 시간, 숫자의 포맷을 변경할 수도 있다.

JSTL을 구성하는 라이브러리들이 몇몇 존재하는데 여기서는 코어와 포메팅 라이브러리에 대해 알아보도록하자. 우선 JSTL을 jakarta.apache.org에 접속하여 라이브러리를 받도록하자. 내려받은 파일은 톰켓에 lib폴더에 넣어주자. 그리고 taglib 지시자로 태그를 사용할 수 있도록 설정해야한다.
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

이렇게하여 커스텀 액션 태그가 추가되었다. 그럼 커스텀 태그의 사용에 대해 알아보자.
<c:set>
- 변수를 선언하고 변수에 초기값을 대입하는 기능의 커스텀 액션
예) <c:set var="result" value="100"></c:set>

또는 <c:set var="result" value="${num}></c:set>처럼 EL문을 사용할 수도 있다. 또한 이 태그의 속성값인 scope를 통해 네 가지의 내장객체에 어트리뷰트를 저장하는 것이 가능하다는 것을 잘 알고 있도록 하자.

<c:if>
- 프로그램의 if문과 비슷한 역할
예) <c:if test="${num1>num2}">

이렇게함으로써 num1과 num2의 조건관계를 알아볼 수 있다.

<c:choose>
- 프로그램에서 switch의 역할과 비슷하다.
예)
<c:chooes>
    <c:when test="${num==0}">
        Hello JSP<br>
    </c:when>
    <c:otherwise>
        Bye<br>
    </c:otherwise>

<c:forEach>
- 프로그램의 for문
예 1.) <c:forEach begin="0" end="10">
              Hello JSP<br>
        </c:forEach>

기본적으로 0부터 10까지 증가가 1씩되면서 Hello JSP를 10번 출력한다. 증가의 수를 변경하고 싶다면 속성 step에 수를 입력하면 된다.(step="2")

예 2.) <c:forEach var="i" items="${arr}">
             ${i}<br>
         </c:forEach>

데이터를 여러개 담고 있는 컬렉션을 하나씩 돌려 저장된 객체를 리턴시켜 줄 수 있다.
그 종류는 배열뿐만 컬렉션 아니라 arraylist, map, iterator, enumeration객체들과 콤마로 구분된 항목을의 문자열을 의미한다.

<c:forTokens>
- 자바의 StringTokenizer와 for문이 합쳐진 것과 같다.
예) <c:set var="guests" value="토끼^^거북아~사슴"/>
      <c:forTokens var="animal" items="${guests}" delims="^~">
          ${animal}<br>
      </c:forTokens>

<c:redirect>
-response.senRedirect()와 같다
예) <c:redirect url="http://~~"/>

[JSP] EL(Expression Language)

JSP를 이용하고 코딩을 할 때 불편함이 있는데 그것은 자바코드와 HTML코드, 거기다 스크립트코드가 모두 혼합해서 사용될 때 너무 지저분해 보이는 것이다.

JSP에는 자바코드를 줄이고 데이터를 출력하는데 좀 더 간결한 익스프레션 언어(EL)를 제공한다. 익스프레션 언어는 다음과 같이 사용한다.
예) ${cnt};

JSP의 익스프레션과는 구별해야한다. EL에서는 어트리뷰트 이름을 이용하여 값을 출력한다. 그러므로 setAttribute()와 getAttribute()를 통해 데이터를 저장하고 얻었던 작업을 줄여서 나타낼 수 있다.

예를 들어 request.setAttribute("result", 100) 이라고 request객체에 "result"라는 이름으로 100이라는 데이터를 저장하였다. 그렇다면 이 데이터를 얻기 위해서 request의 getAttribute()메서드를 호출하여 얻어야 하지만 EL에선 ${result}로 데이터를 손쉽게 얻을 수 있다.

JSP의 내장 객체 중 scope의 범위에 따른 네 가지 종류의 객체를 살펴보았다.
page, request, session, application 이 그것이다.
이들 모두 set(), get()메서드를 이용하여 어트리뷰트에 데이터를 저장할 수 있기 때문에 당연히 EL을 통해 데이터의 출력이 가능하다.

그렇다면 이들 네 가지 객체 어떻게 EL구문 만으로 데이터를 읽어 들일 수 있을까?
그 이유는 page -> request -> session -> application 순으로 어트리뷰트를 찾아가기 때문이다.

이런 이유로 좀더 명확한 내장 객체의 어트리뷰트를 표현하기 위하여 다음과 같이 사용하기도 한다.
예) ${pageScope.result}

page내장 객체의 어트리뷰트에 result로 저장되어 있는 데이터를 출력하라는 EL구문이 되겠다.

이 네가지 내장 객체뿐만 아니라 더많은 객체가 존재하여 EL구문을 활용할 수 있다.
pageScope : page 어트리뷰트의 집합
requestScope : request 어트리뷰트의 집합
sessionScope : session 어트리뷰트의 집합
applicationScope : application 어트리뷰트의 집합
param : 웹 브라우저로부터 입력된 데이터의 집합(예 ${param.result})
paramValues : 웹 브라우저로부터 입력된 여러 데이터의 집합(예 ${paramValues.result[0]})
header : HTTP요청 메세지에 있는 HTTP헤더의 집합(사용법은 param과 같다)
headerValues : HTTP요청 메세지에 있는 여러 HTTP헤더의 집합(사용법은 paramValues와 같다)
cookie : 웹 브라우저로부터 전송된 쿠키의 집합(예 cookie.result.value)
initParam : 웹 어플리케이션의 초기화 파라미터의 집합
pageContext : JSP페이지의 환경 정보의 집합

EL은 연산과 비교조건이 가능하다. 일반적인 프로그래밍 문법과 비슷하기 때문에 설명은 생략하기로 하고 Empty 연산자를 알아보자.
${empty result}라고 사용하면 result이름으로 데이터 값이 존재하는지 유무를 확인할 수 있다. 리턴형은 Boolean이다.


2013년 3월 13일 수요일

[JSP] JDBC

지금까지는 쿠키와 세션을 이용하여 사용자의 데이터를 저장하고 접속상태를 확인해 보았다. 그러나 많은 데이터나 지속적으로 보관되어야 할 데이터는 궁극적으로 데이터베이스에 저장 되어야 할 것이다.

JSP를 이용하여 데이터베이스와의 연동을 하기 위한 과정을 살펴 보도록하자.

1. JDBC 드라이버 준비
JDBC 드라이버(ojdbc14.jar)를 톰캣에 lib폴더에 복사하자. 오라클이 설치되어 있는 폴더 안에 ojdbc14.jar파일이 있다. jar이란 확장명을 보면 알 수 있듯이 자바와의 연동을 위한 드라이버이다.

2. 드라이버 로드
JSP에서 Class.forName("oracle.jdbc.driver.OracleDriver") 으로 오라클 데이터베이스의 가상드라이버를 로드한다. 그래야 오라클 데이터베이스와 연동할 API를 사용할 수 있다. MySql과 MS SQL 서버는 다음과 같다.

MySql - com.mysql.jdbc.Driver
MS SQL 서버 - com.microsoft.sqlserver.jdbc.SQLServerDriver

3. 데이터베이스 연결
데이터베이스와의 연결을 위해서 Connection이라는 객체가 필요하다. 이 객체를 구하기 위해 3가지 준비물이 필요하다.
- url
- 사용자 계정
- 패스워드

url은 데이터베이스를 구분하기 위해 사용한다. 오라클에서는 다음과 같은 url을 가진다.
jdbc:oracle:thin:@HOST:PORT:SID

위에서 thin이 의미하는 바는 자바언어로 구현되어 있다는 의미이고 OCI일 경우도 있는데 이는 네이티브 모듈을 사용한다.
사용자 계정과 패스워드는 자신이 사용하고 있는 DBMS의 계정와 패스워드를 의미한다.

4. Connection객체 얻기
위에 세 가지의 정보로 Connection 객체를 얻을 수 있는데 DriverManager클래스가 제공하는 getConnection()메서드를 사용한다.
DriverManager.getConnection(String url, Stirng uesr, String password)

5. Statement를 사용한 쿼리 실행
Connection 객체로 Statement 객체를 생성하고 쿼리 질의를 할 수 있다. 그러나 여기서는  PrepareStatment를 사용한다. 그 이유는 둘다 성능의 차이는 없으나 PrepareStatment는 sql문의 틀을 미리 생성해 놓고 값은 나중에 지정한다는 것이다.또한 sql문에 ?부분을 setString(index, 원하는값)으로 치환할 수 있는 장점이 있다.
PrepareStatement pstmt = connection.createStatement();

Preparestatement를 사용하여 쿼리를 실행 할 수 있는데 select 질의를 할 경우 리턴값은 테이블의 로우들이기 때문에 ResultSet 객체로 받아야한다.
ResultSet result = pstmt.executeQuery(String sql);

또는 insert와 update, delete와 같은 테이블 구조변경 질의를 실행하면 그 결과로 -1, 0 ,1을 전달하는데 -1일 경우는 쿼리문 실패, 0일 경우는 쿼리문에 오류는 없으나 DB의 변경이 없음, 1은 성공을 의미한다. 코드는 다음과 같다.
int result = pstmt.executeUpdate(String sql);


6. ResultSet 객체 사용
쿼리문 질의를 통해 얻은 결과로 ResultSet 객체를 얻을 경우. 하나의 row(튜플)을 검색하기 위해 next()메서드를 사용하면 된다. 하나의 로우만을 출력하기 위해서 if(rs.next())로 처리하고 많은 양의 로우를 처리하기 위해서 while(rs.next())로 처리해주어야 한다.

간단한 예로 데이터베이스에 id와 password를 입력하는 메서드를 살펴보자.

public int insertMember(Register register){

Connection con = null;
PreparedStatement pstmt = null;
String sql = "insert into Member values(?,?)";
String url = "jdbc:oracle:thin:@localhost:1521:XE";
String user = "hr";
String password = "1234";
int check = -1;

try{
Class.forName("oracle.jdbc.driver.OracleDriver");
con = DriverManager.getConnection(url, user, password);
pstmt = con.prepareStatement(sql);
pstmt.setString(1, register.getId());
pstmt.setString(2, register.getPass());
check = pstmt.executeUpdate();
}catch(Exception e){
e.printStackTrace();
}finally{
if(pstmt != null){
try{
pstmt.close();
}catch(Exception e){
e.printStackTrace();
}
}
if(con != null){
try{
con.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
return check;
}

이 방법이 가장 기본적인 DB와의 연결이다. 그러나 매번 데이터베이스와의 연동을 위해 해야하는 코딩이 제법 많은 편이다.

2013년 3월 11일 월요일

[JSP] 자바 빈

보통 웹사이트를 둘러보면 Form태그의 입력창에다가 데이터를 입력하고 웹 서버에 데이터의 처리를 요청한다. 요청받은 데이터는 JSP를 통해 처리되는데 처리된 데이터를 저장해야하는 경우가 많다.

JSP에서는 요청받은 데이터를 받아 데이터를 저장할 객체를 생성한다.
이 객체를 자바 빈이라고 하며 form으로부터 전달받은 데이터를 객체로 보관하기 위해 사용한다.

자바 빈을 생성한 뒤 실제로 DB에 저장하기 위해 DAO(Data Access Object)라는 데이터 접근 오브젝트를 사용한다. 이 때 DAO는 static클래스이기 때문에 static의 특징을 모두 가지고 있다.

그렇다면 어떻게 JSP에서 자바 빈을 사용할까?
<jsp:useBean> 태그를 이용하여 간단하게 자바 빈 객체를 만들 수 있다.

예) <jsp:useBean id="obj" class="mall.PersonalInfo"/> //자바 빈 생성
<jsp:setProperty name="obj" property="*"/>//form으로부터의 모든 데이터 저장
<jsp:setProperty name="obj" property="age" value="27"/>//자바 빈 객체에 age라는 변수에 27을 삽입

JSP에서 가장 중요힌 것은 데이터를 어떻게 전달하고 전달받는 것인가이다. 명심하도록 하자!

데이터 전달방법
1. form태그에서 submit으로 데이터 전달(hidden시켜서 데이터를 전달해야하는 경우도 있다.)

2. a태그에서 href속성을 이용한 데이터 전달
예) <a href="Index.jsp?contents=module/register.jsp">회원가입</a>

3. request.setAttribute()로 request내장 객체에 속성값을 지정하여 request객체를 전달

4. 자바 액션 태그 forward를 이용한 데이터 전달. param에 데이터 값 지정
예)<jsp:forward page="Index.jsp">
    <jsp:param value="module/confirm.jsp" name="contents"/>
    </jsp:forward>

5. sendRedirect()를 이용하여 데이터 전달. a태그사용법과 같다.
예) response.sendRedirect("login_form.jsp?id=aaa");

6. 액션 태그 useBean응 이용하여 빈 객체를 생성하여 객체를 저장한다. 빈 객체를 이용하여 데이터 전달이 가능하다.
예)<jsp:useBean id="register" class="kosta.register.Register"></jsp:useBean>
    <jsp:setProperty property="*" name="register"/>

2013년 3월 10일 일요일

[JSP] JSP의 내장객체

JSP에는 선언하지 않고도 사용할 수 있는 내장객체를 제공하고 있다.

예를 들어 request는 서블릿 클래스에 있는 doGet, doPost메서드의 첫 번째 파라미터와 동일한 역할을 한다. out은 서블릿 클래스에서 getWriter메서드를 호출해서 얻는 PrintWriter객체와 같은 역할을 한다.

이처럼 JSP에서 서블릿의 객체를 사용할 수 있는 것은 웹 컨테이너가 JSP를 서블릿으로 변환 할 때 자동으로 선언해 주기 때문이다.

그럼 JSP에는 어떠한 내장객체가 있으며 어떤 기능이 있는지 살펴보자.

request : doGet, doPost 메서드의 첫 번째 파라미터와 동일한 역할
(javax.servlet.http.HttpServletRequest)
response : doGet, doPost 메서드의 두 번째 파라미터와 동일한 역할
(javax.servlet.http.HttpServletResponse)
out : 웹 브라우저로 HTML코드를 출력하는 기능
(javax.servlet.jsp.JspWriter)
application : JSP페이지가 속하는 웹 어플리케이션에 관련된 기능
(javax.servlet.ServletContext)
config : JSP페이지의 구성 정보를 가져오는 기능
(javax.servlet.ServletConfig)
pageContext : JSP페이지 범위 내에서 사용할 수 있는 데이터 저장 기능 등
(javax.servlet.jsp.PageContext)
session : 세션에 관련된 기능
(javax.servlet.http.HttpSession)
page : JSP페이지로부터 생성된 서블릿
(java.lang.Object)
exception : 익셉션 객체
(java.lang.Throwable)

response 내장 객체의 sendRedirect메서드는 파라미터로 지정한 URL을 직접 호출하는 것이 아니라 메세지를 웹 브라우저로 보낸다.
application 내장 객체에 getContextPath메서드와 getRealPath메서드를 이용하여 웹 어플리케이션의 상대경로와 절대경로를 알 수 있다.

2013년 3월 8일 금요일

[JSP] JSP

JSP의 등장배경과 그 쓰임에 대해서는 앞에서 언급하였다. JSP는 HTML문서에 JSP 문법의 코드가 삽입되는 형태로 작성된다.
JSP 페이지에 있는 HTML 코드는 웹 브라우저로 그대로 전송되지만, JSP문법의 코드는 웹 컨테이너 쪽에서 실행되고 그 결과만 웹 브라우저로 전송된다.

웹 컨테이너는 JSP페이지 전체를 서블릿 클래스의 소스코드로 변환하고, 다음에 소스 코드를 컴파일 후 결과를 가지고 서블릿 객체를 만든다. 그 뒤 서블릿 객체를 초기화해서 서블릿을 만든다. 따라서 웹 브라우저로부터 URL이 왔을 때 실행 되는 것은 서블릿이다.

JSP문법의 세가지 형태
1. <%로 시작%>로 끝나는 형태
2. ${로 시작}로 끝나는 형태
3. <jsp:forward>나 <C:if>와 같은 XML태그 형태

세가지 형태 중 첫 번째 문법에서 지시자와 스크립팅 요소로 나눠진다.
우선 스크립팅 요소부터 살펴보자. 스크립팅 요소에도 세가지 문법이 있다.
1. 스크립틀릿
2. 익스프레션
3. 선언부

스크립틀릿은 <% %>사이에 자바 명령문이 들어갈 수 있으며, 명령문은 웹 서버쪽에서 실행 되는 코드이다.

익스프레션은 <%= %>로 표현하고 그 사이에 자바의 결과값을 출력하는 문법이다. 따라서 변수나, 식, 함수를 넣어줄 수 있으며 그 결과값을 출력해 준다.

선언부는 <%! %>이며 사이에 변수 선언이나 메서드 선언을 쓸 수 있다. 자바에서 멤버 변수 또는 메서드라고 할 수 있다. 따라서 자바의 public, private, protected, final, static과 같은 키워드를 그대로 사용할 수 있다. 하지만 JSP는 스레드 기반으로 작동하는 서블릿으로 변환될 것이므로 인스턴스 변수를 선언해서는 안된다. 그리고 점점 JSP에서 자바 코드와 같은 로직을 처리해 주는 코드를 점점 없애려는 추세이기 때문에 자주 쓰이는 형태는 아니다.

지금까지 스크립팅에 대해 알아보았다. 다음으로 지시자에 대해 알아보자.
지시자는 웹 컨테이너가 JSP페이지를 서블릿 클래스로 변환할 때 필요한 정보들을 기술하기 위해 사용하는 문법이다. 세가지의 지시자가 있다.
1. Page지시자
2. Include지시자
3. Taglib지시자

지시자는 <%@ %>로 표현하며 첫 번째 요소로 지시자의 이름이 오고 다음으로는 속성들이 올 수 있다.
예)<%@page 속성 속성 %>

page지시자
JSP페이지 전체에 적용되는 정보를 기술하여 WAS에게 전달.

page지시자 속성
contentType : JSP페이지가 생성하는 문서의 종류, 그 문서를 웹 브라우저로 전송할 때 사용되는 인코딩 타입
import : 스크립팅 요소 안에서 사용할 자바 클래스와 인터페이스를 임포트
buffer : 출력 버퍼 크기
autoFlush : 출력 버퍼가 찼을 때의 동작
isThreadSafe : JSP페이지가 싱클 또는 스레드 모드로 작동하도록 설정
session : JSP페이지의 세션 참여 여부
errorPage : 에러를 처리할 JSP페이지의 URL
isErrorPage : 에러를 처리하는 JSP페이지인지 여부
isELIgnored : 익스프레션 언어의 무시 처리 여부
pageEncoding : JSP페이지의 인코딩 타입
info : JSP페이지에 대한 설명
extends : JSP페이지로부터 생성되는 서블릿 클래스의 슈퍼클래스
language : 항상 java로 설정되어 있으며 스크립팅을 구현할 언어 설정

include지시자
다른 JSP페이지나 HTMl문서를 불러다가 현재 JSP페이지의 일부로 만들기 위해 서용한다.
예)<%@include file="A.jsp"%>

위의 예처럼 불러온 대상은 file이라는 애트리뷰트를 이용해서 지정할 수 있으며, 속성값은 지시자가 속하는 JSP페이지를 기준으로 상대적인 URL로 해석된다.
이처럼 include지시자를 사용함으로써 중복이 되는 JSP페이지를 만들 필요없이 include시켜줌으로써 개발 시간을 단축시키는 등의 이점을 잘 알아두자.
include지시자와 <jsp:include>액션 태그의 차이가 있으니 잠시 언급하겠다.


Taglib지시자
JSP페이지에 사용할 태그 라이브러리를 지정. 표준화된 태그 라이브러리를 JSTL이라고 한다. JSTL을 사용하기 위해서 태크라이브러리 지시자를 꼭 써야한다.
예) <%@taglib profix="c" uri="http://java.sun.com/jsp/jstl/core"%>

 Taglib를 이용하여 JSP페이지 내에 불필요한 자바 코드를 줄일 수 있다. 자바 코드를 줄임으로써 웹 어플리케이션의 표현과 비즈니스 로직을 구분하기 위함이다. 특히 액션 태그를 많이 활용할 것이다. 액션 태그를 살펴보자.

액션태그
<jsp:include page="A.jsp"/> A.jsp페이지를 현제 페이지로 include(페이지 모듈화를 통해 템플릿을 만들기 수월하다)
<jsp:forward page="A.jsp"/> 현제 페이지의 제어를 A.jsp로 전달
<jsp:useBean scope="page" id="cls" class="xx.MyBean"/> xx페키지의 MyBean 클래스를 class로 page 범위에서 사용할 것

[JSP] 서블릿

앞서 서블릿이 무엇인지에 대해 언급하였다.

모든 자바 기반의 웹 어플리케이션은 서블릿에 의해 구동된다. 그러므로 웹 어플리케이션에 있어서 매우 중요하다. 하지만 html 문서와 함께 데이터의 로직을 처리하고 결과값을 전달하기가 매우 어렵다. 왜냐하면 html문서는 브라우저에 의해 해석되어 화면에 보여지는 출력을 담당하지만 서블릿을 비즈니즈 로직을 이용하여 데이터를 처리하는데 그 목적이 있다. 따라서 함께 구현 되어지면 코드가 얽혀 매우 복잡한 코드가 된다.

이런 문제를 개선시키기 위해 JSP가 등장한다. HTML문서에서 프로그램 구현이 가능하도록한 스크립팅 기술을 제공한다. 그러나 실제로는 모든 프로그램의 구현을 JSP로 하지 않고 출력에 대한 부분에 많이 초점을 두고 실제 비즈니스 로직을 처리하기 위해서 MVC패턴을 이용한다. MVC에 대한 내용은 뒤에 하도록 하자.

이처럼 JSP의 등장과 더블어 MVC패턴으로 인해 서블릿의 구현은 잘 하지 않는다. 그러나 서블릿을 알고 있어야한다. 왜? 모든 JSP는 서블릿으로 변환되어 구동되기 때문이다. 즉, 웹서버에서 원하는 데이터는 결국 서블릿이 처리해주는 것이다.

그렇다면 서블릿의 동작을 살펴보자.

처음 웹 서버에서 클라이언트의 데이터의 처리를 Was(웹 어플리케이션 컨테이너)에 요청한다. 컨테이너에서 제일 처음에 데이터 처리를 위한 해당하는 서블릿 클래스를 찾는다. 해당하는 클래스가 존재하지 않으면 서블릿 객체를 생성하게 된다. 이렇게 생성된 서블릿 객체는 메모리에 올려지게 됨으로 그 이후로 계속되는 데이터 처리요청을 스레드 기반으로 지속적으로 서비스 해 줄 수 있게 된다.
마지막으로 모든 요청이 종료되면 해당하는 스레드가 종료하게 된다.

서블릿의 장, 단점에 대해 알아보자
장점
- 스레드 기반이기 때문에 웹 어플리케이션 운영에 효율적
- 자바를 기반으로 하므로 자바 API를 모두 사용가능
- 운영체제나 하드웨어에 영향을 받지 않는다(자바의 장점)

단점
- 비즈니스 로직의 처리와 화면 출력을 위한 처리를 모두 해야한다.
- 프로그래머가 HTML, 자바스크립트, 스타일시트 등 모든 기술을 알고 있어야 한다.

아래는 html로 부터 넘어온 데이터에 대해 get방식으로 처리해주는 서블릿 doGet메서드이다.

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("euc-kr");//요청받은 데이터의 문자를 euc-kr로 인코딩

String name = request.getParameter("name");
String address = request.getParameter("address");

response.setContentType("text/html; charset=euc-kr");//출력할 내용의 타입을 html로 설정하고 euc-kr로 한글이 전달되도록 설정
PrintWriter out = response.getWriter();

out.println("<html><head></head><body>");
out.println("<b>" + name + "</b>");
out.println("<b>" + address + "</b>");
out.println("</body></html>");

out.close();
}
요청과 함께 넘어돈 데이터를 request란 객체를 이용하여 전달받고 적절한 처리를 한뒤 response객체에 출력값을 저정하여 다시 내보내는 과정이다. 이 예제를 잘 이해하고 있어야 한다.

2013년 3월 7일 목요일

[JSP] 웹 어플리케이션

지금까지 자바를 이용해 프로그래밍을 해보고 html과 css를 활용하여 웹을 만들었다. 그리고 자바스크립트와 jQuery를 이용하여 이벤트를 통해 클라이언트 측 브라우저에서 서버로 요청을 하고 요청에 의한 데이터를 클라이언트 측에서 잘 출력하기 위한 과정을 진행해보았다. 즉, 클라이언트 측에서 데이터를 전달하고 전달받은 데이터 출력부분을 살펴보았단 뜻이다.

그렇다면 지금부터는 서버측에서 요청받은 데이터의 처리와 다양한 작업을 하는 것이 순서일 것이다. 서블릿과 JSP는 이 서버에서 요청받은 데이터를 처리하고 응답하는 웹 어플리케이션이라고 할 수 있다.

서블릿 : 자바 기반의 웹 프로그래밍 기술로써 자바 언어의 모든 기능을 사용해 웹 어플리케이션을 제작할 수 있다. 또한 스레드 기반으로 데이터를 처리해 줌으로써 빠른 속도를 자랑한다. 그러나 서블릿은 프로그램을 구현하는데는 좋지만 화면을 출력하는 부분에 있어서는 어려움이 많다. 이러한 문제점을 개선한 것이 JSP이고 JSP는 내부적으로 서블릿 기술에 기반하고 있다.

JSP : 서블릿 기반의 서버 스크립트 언어로써 오늘날 가장 대표적인 웹 프로그래밍 기술이다. 서블릿의 단점인 화면상의 출력을 보완해 줄 수 있다. JSP 역시 자바 기반의 언어이므로 자바의 모든 기능을 사용할 수 있다.

우선 웹 어플리케이션은 무엇일까?
웹을 기반으로 실행되는 프로그램을 의미한다.

우리가 즐겨 사용하는 웹의 동작 순서를 보자.
1. 사용자가 원하는 웹사이트에 접속하기 위해 url을 주소창에 입력한다. 클라이언트에서 서버로 요청을 하는 과정이다.

2. 해당 웹 서버에는 요청을 받아들여 요청에 해당하는 응답을 하게 된다. 이때 웹 서버는 클라이언트의 요청에 대한 데이터 처리를 위해 웹 어플리케이션 서버와 연동이 이루어진다.

3. 웹 어플리케이션 서버에서 처리한 데이터를 웹 서버가 받아서 클라이언트측에 보내줌으로써 클라이언트 브라우저에서 결과화면을 볼 수 있다.

웹 서버와 웹 어플리케이션 서버는 무엇을까? 웹 서버는 대표적으로 Apache와 마이크로소프트의 IIS가 있다. 웹 서버의 역할은 클라이언트의 요청을 받아 적절한 응답을 하는 것이다. 이때 클라이언트로부터 데이터에 대한 처리를 요청하게 될때 JSP가 톰캣이라는 웹 어플리케이션에 의해 서블릿 자바코드로 변환이 이루어지고 컴파일 된다.

즉, 적절한 응답을 위한 데이터처리와 로직을 웹 어플리케이션 서버에서 처리한다. BEA사의 웹로직, IBM의 웹스파이어 SUN의 iPlanet 등이 있고 국산으로는 제우스가 있다. 이들 웹 어플리케이션을 Was라 부른다.

 여기서는 톰캣이라는 Was프로그램을 이용하여 웹 어플리케이션 서버를 구현할 것이다. 톰캣은 자바코드로 비지니스 로직을 서블릿과 JSP로 처리하기 위한 컨테이너이다. 웹 어플리케이션 서버의 일종인 톰켓은 상용화가 목적이 아니면 누구나 무료로 사용할 수 있다. JSP가 서블릿 형태로 변환하여 순수한 자바코드로 컴파일하게 되는데 톰캣은 서블릿과 JSP와 같은 자바코드를 완벽하게 지원한다. 그리고 J2EE 자바환경을 사용한다. J2EE는 서블릿과 JSP와 같은 웹 어플리케이션 서버를 구현하기 위해서 사용하는 자바기술환경이다.

이클립스를 하면서 중요한 부분은 폴더 구성이다. JSP가 들어가야할 디렉토리, 서블릿이나 라이브러리들이 포함될 디렉토리 경로에 대해 잘 파악해 두도록하자.


서블릿의 생명주기(Life Cycle)
서블릿 요청 -> JSP -> 서블릿 자바소스 코드 -> 서블릿 클래스 파일 -> 서블릿 객체 생성(처음에 한번만 Init()수행) -> 서블릿 응답(Doget(), Dopost())



2013년 3월 5일 화요일

[JS] jQuery - Ajax

 여기서는 Ajax에 관련된 jQuery메소드에 대해 알아보고자 한다. 자바스크립트에서 XMLHttpRequest객체를 활용해 보았는데 jQuery에서는 훨씬 간단하게 서버에게 데이터를 요청하고 전달받은 데이터를 조작하는 것도 더 쉽다.

Ajax는 항상 이벤트로부터 시작한다는 간단한 사실을 잊지말자!

하나씩 Ajax를 위한 메소드를 살펴보자.

$(seletor).load(url, parameters, callback)
- url : 요청이 전송되는 서버 url
- parameters : url에 전달하고자 하는 데이터
- callback : 응답 결과로 데이터를 수신한 뒤 호출되는 함수

load함수의 결과로 html의 요소로 넘겨받을 경우 호출한 객체의 자식으로 들어감. 전달받은 데이터가 html의 요소이기 때문에 웹상에서 화면에 결과를 보여주기에 용이하다.

$.get(url, parameters, callback)
url을 사용하여 서버에 파라미터 값을 url에 문자열로 삽입하여 GET전송. callback함수로 데이터를 얻음. 이 방식이나 post방식을 이용하면 text뿐만 아니라 xml문서요소도 받을 수 있다. xml일 경우 DOM객체 형식으로 부모 자식관계를 잘 이용하여 데이터를 참조해야한다.

$.post(url, parameters, callback)
url을 사용하여 서버에 파라미터 값을 본문에 삽입하여 POST전송. callback함수로 데이터를 얻음(TEXT or XML)

여기서 잠깐!
 get과 post의 의미를 좀 더 설명하자면 get 방식은 데이터를 서버로 전송할 때 url에 문자열을 붙여 전송한다. 따라서 url길이에 제한적이며 형식에 맞지 않는 문자는 encoding되어야할 필요가 있다. 또한 url에 데이터를 전송하는 방식이기 때문에 사용자가 확인 가능하다는 특징이 있다.
 post 방식은 모든 데이터를 http헤더에 포함하여 전송하는 방식이다. 따라서 길이에 제한이 없고 사용자가 볼 수 없다는 특징이 있다. 또한 get보다는 문자의 encoding의 필요성은 상대적으로 낮으나 비영어권과 같은 특수한 환경일 경우는 encoding이 필요하다.

$.getJSON(url, parameters, callback)
url을 사용하여 서버에 파라미터 값을 본문에 삽입하여 POST전송. callback함수로 JSON 데이터를 얻음(TEXT or XML)
참고로 json 객체를 얻게 되면 항상 키와 값으로 원하는 데이터를 참조한다.

$.getScript(url, callback)
url을 사용하여 서버에 GET전송

왜 스크립트를 클라이언트에서 get요청을 할까? 그 이유는 처음부터 많은 스크립트를 로드할 경우 로딩시간이 그만큼 길어지기 때문에 사용자에게 불편함을 줄 수 있고 특정한 이벤트나 자주 사용하지 않는 기능을 위한 스크립트는 나중에 로딩해주는 경우를 위해서이다.

$.ajax(options)
- options : 요청에 대한 매개변수를 정의하는 객체

options의 속성종류
url : 요청url
type : 사용 할 HTTP메서드(생략시 GET)
data : 요청에 전달될 객체(object)
dataType : 응답의 결과로 반환되는 데이터의 종류(xml, html, json, jsonp, script, text)
timeout : Ajax요청의 제한시간, 제한시간초과시 error callback 호출되거나 요청 취소
global : true : 전역함수활성 false : 전역함수비활성
contentType : 요청에 지시되는 contentType, 기본값 : "application/x-www-form-urlencoded"
success : 응답이 성공시 호출되는 함수
error : 응답이 에러상태 코드를 반환하면 호출되는 함수
complete : 요청이 완료되면 호출되는 함수(success 또는 error 후 실행)
beforeSend : 요청전송 이전에 호출되는 함수
async : true : 비동기호출, false : 동기호출
processData : flase시 url인코딩 형태로 처리되어 전달되는 데이터를 금지
ifModified : true시 헤더정보 확인하여 미변경시 요청 성공

ajax 전역함수
ajaxStart(callback)
ajaxSend(callback)
ajaxSuccess(callback)
ajaxError(callback)
ajaxComplete(callback)
ajaxStop(callback)

사용예
$(document).ready(function() {
$("#letter-d a").click(function() {
$.ajax({url:"d.xml",
dataType:"xml",
success:function(data) {
$("#dictionary").empty();
$(data).find("entry").each(function() {
$entry = $(this);
var html = "<div class='entry'>";
html += "<h3 class='term'>"+ $entry.attr("term") + "</h3>";
html += "<div class='part'>"+ $entry.attr("part") + "</div>";
html += "<div class='definition'>" + $entry.find("definition").text() + "</div>";
html += "</div>";
$("#dictionary").append(html);
});
}
});
return false;
});
});

2013년 3월 4일 월요일

[JS] JavaScript - Ajax

Ajax 란?
Asynchronous JavaScript XML의 약자로써 페이지의 이동 없이 클라이언츠에서부터 전달한 데이터의 요청을 서버에서 DB와 관련하여 적절한 처리 후 응답하여 하나에 웹페이지에서 모든 동작이 가능하게하는 기술이다.

예를 들어 구글의 지도나 검색시 검색창 아래에 관련 검색이 실시간으로 제공되는 것을 의미한다.

비동기식(Asynchronous)이라는 단어에서 알 수 있듯이 실시간으로 일어나는 순간의 이벤트에 대해 계속해서 데이터의 전달과 데이터 교환이 모두 이루어지는 것이 특징이다. 만약 동기식으로 하나의 작업을 처리하기 위해 다른 요청을 받을 수 없는 상황이 되면 동적인 웹을 구성하기는 어렵다.

그럼 기본적인 자바스크립트만으로 Ajax하는 방법을 알아보자.

위에 그림을 보면 클라이언트로부터의 요청이 XMLHttpRequest로 전달 되는 것을 볼 수 있을 것이고 서버에서 처리한 데이터(XML, TEXT, JSON)들도 XMLHttpRequest로 전달 되는 것을 볼 수 있다. 이는 XMLHttpRequest를 다루는 것이 Ajax에서 중요한 부분이라는 것을 알 수 있다.

XMLHttpRequest는 사용자의 요청을 웹서버에 전송하고 결과를 웹브라우저에 전달해 주는 역할을 하며 클라이언트가 서버와 통신을 하는데 중요한 객체이다.

자바스크립트에서 XMLHttpRequest 객체를 생성해보자.
var request = new XMLHttpRequest();

다음은 open()메서드를 이용하여 전송위치와 전송방식, 동기와 비동기를 설정.
request.open("GET", "hello.jsp", false);//전송위치에는 이미 만들어 놓은 jsp파일로 지정, false는 동기 방식, true는 비동기 방식

request.send();//전송위치로 객체를 전송!

여기까지가 기본적인 XMLHttpRequest 객체 사용법이다.
그렇다면 원하는 데이터는 어떻게 전송시킬 수 있을까? 전송방식이 GET일 경우 다음과 같이 데이터를 넘길 수 있다.
예)
request.open("GET", "hello.jsp?name=kylor", false);
데이터를 처리해 주는 jsp에 ?를 붙이고 name에 kylor이라는 문자를 넘겨주었다. 서버에서는 name에서 문자열을 추출하여 처리할 수 있게 된다.

그렇다면 데이터가 잘 전송되었는지는 어떻게 확인할 수 있을까?
onreadystatechange이벤트로 확인가능하다. onreadystatechange이벤트는 XMLHttpRequest의 상태가 변경될 때마다 호출된다.

onreadystatechange이벤트가 호출될 때 XMLHttpRequest객체의 상태를 readyState속성으로 확인가능하다.
readyState 속성은 0부터 4까지 상수로 존재한다.
0 : 초기화 안됨
1 : send 사용전
2 : 데이터 받지 못함
3 : 상호작용 중(일부)
4 : 완료

완료가 된 상태에서 XMLHttpRequest를 사용할 수 있다는 것은 당연할 것이다.

Ajax요청을 사용하여 데이터의 수신이 완료했더라도 데이터가 올바른 데이터인지 확인해 보아야 한다. 이를 위해 HTTP Status Code를 사용한다.
1.XX : 처리 중
2.XX : 성공
3.XX : 리다이렉트
4.XX : 클라이언트 오류
5.XX : 서버 오류

따라서 다음과 같은 코드가 함께 추가되야 한다.

request.onreadystatechange = function(event){
if(request.readyState == 4){
if(request.status == 200){
...처리....
}
}
}

그렇다면 XMLHttpRequest를 이용하여 서버로부터 리턴받은 XML, JSON을 어떻게 다룰 수 있을까?
JSON일 경우
var json = eval("(" + request.responseText + ")");
json객체를 리턴받아 키와 값으로 데이터를 읽을 수 있다.

XML일 경우
var xml = request.responseXML;
xml객체를 리턴받아 문서구조로 데이터를 읽을 수 있다.

[JS] jQuery - 객체 위치 시키기

jQuery를 하면서 선택자가 가장 중요한 부분이라고 언급하였다. 그리고 jQuery에서 제공하는 다양한 메소드 덕분에 자바스크립트로는 까다로운 부분을 비교적 쉽게 구현 할 수 있다는 장점이 있었다.

jQuery의 또다른 장점이 있다. 그것은 얼마든지 동적으로 객체를 생성하고 내가 원하는 자리에 넣을 수 있는 메서드도 제공하기 때문이다. 여기서는 한번 언급하긴 하였으나 제대로 된 설명이 필요했던 메서드들에 대해 알아보기로 하자.

우선 객체의 생성을 보자
$()을 사용하여 객체를 쉽게 생성할 수 있다.
예)
$("<h1></h1>");//h1태그 생성

객체를 생성했다면 문서에 연결이 필요하다.
예)
$("body").append($("h1"));//body에 h1태그 삽입

중요한 메서드가 바로 append()이다. 생성한 객체를 원하는 객체 앞이나 뒤에 연결을 해야 하는데 jQuery에서는 8가지의 메소드를 제공한다. 8가지 메소드는 부모자식관계와 형제관계로 크게 나눌 수 있다.

부모자식관계
$(A).append(B) : 위에서 언급한 메소드이다. 부모 A태그 가장 뒤에 B태그를 위치시킴
$(A).prepend(B) : 부모 A태그 가장 앞에 B태그를 위치시킴
$(A).appendTo(B) : to로 인해 헷갈릴 수 있는 메서드다 주의하자. A태그를 부모 B태그 가장 뒤에 위치시킴
$(A).prependTo(B) : A태그를 부모 B태그 가장 앞에 위치시킴

다음은 형제관계를 보도록 하겠다. 하지만 그전에 도대체 왜 To를 이용하여 선택자에 따른 메소드의 종류를 많이 만들었을까 생각해보자. 그 이유는 체인 메소드를 이용하여 생성하거나 수정한 객체가 부모 태그일 경우나 자식 태그일 경우로 나눠지게 때문이다. 선택한 객체가 자식태그였다면 appendTo나 prependTo를 이용하여 부모태그에 포함시키는 것이 당연하다.

자 설명은 이쯤하고 형제관계를 보자.
$(A).before(B) : A객체 앞에 B를 위치시킴
$(A).after(B) : A객체 뒤에 B를 위치시킴
$(A).insertBefore(B) : A객체를 B앞에 위치시킴
$(A).insertAfter(B) : A객체를 B뒤에 위치시킴

원하는 객체를 원하는 위치에 이동시키기 위해서 꼭 알아야하는 메소드이다. 잘 알아두자.


2013년 3월 1일 금요일

[JS] jQuery - 애니메이션

기본 애니메이션을 위한 메서드(동적인 상태라는 것을 상기하자)
show() : 문서 객체가 커지게한다.
hide() : 문서 객체가 사라지게한다.
toggle() : show()와 hide()메서드를 번갈아 가며 실행
slideUp() : 문서 객체가 슬라이드 효과와 함께 위로 접힘
slideDown() : 문서 객체가 슬라이드 효과와 함께 아래로 펼쳐짐
slideToggle() : slideDown()과 slideUp()메서드를 번갈아 실행
fadeIn() : 문서 객체를 선명하게 보여줌
fadeOut() : 문서 객체를 사라지게 함
fadeToggle() : fadeIn()과 fadeOut()메서드를 번갈아 실행

메서드 사용 형태
1. $(selector).method();
2. $(selector).method(speed);
3. $(selector).method(speed, callback);
4. $(selector).method(speed, easing, callback);

speed : 애니메이션을 진행할 속도 지정(밀리초 단위의 숫자 또는 "slow", "normal", "fast" 입력)
callback : 애니메이션을 모두 완료한 후 실행할 함수를 지정
easing : 애니메이션을 미묘하게 변화시킬 함수를 지정

사용자 정의 애니메이션
1. $(selector).animate(object);
2. $(selector).animate(object, speed);
3. $(selector).animate(object, speed, easing);
4. $(selector).animate(object, speed, easing, callback);

-object 속성종류
opacity, top, left, right, bottom, top, width, margin, padding

애니메이션 사용에 많은 예가 있다. 그 중 이미지를 클릭하면 순차적으로 이미지가 바뀌는 애니메이션 예를 보자.


<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Change Images</title>
<style type="text/css">
.image {
position: absolute;
top: 10px;
left: 10px;
}

.image img{
width: 300px;
height: 380px;
cursor: pointer;
}
</style>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("img").hide();

$("img:first").show();
$("img").click(function(){
$(this).each(function(){
//alert(this.src);
if(this == $("img:last").get(0)){
$("img:first").fadeIn("slow");
$(this).hide();
}else{
$(this).parent().next().children().fadeIn("slow");
$(this).hide();
}
})
})
})
</script>
</head>
<body>
<a class="image"><img src="../script/images/bg14.jpg"/></a>
<a class="image"><img src="../script/images/bg15.jpg"/></a>
<a class="image"><img src="../script/images/bg16.jpg"/></a>
<a class="image"><img src="../script/images/bg17.jpg"/></a>
<a class="image"><img src="../script/images/bg18.jpg"/></a>
</body>
</html>

2013년 2월 27일 수요일

[JS] jQuery - 메소드

jQuery에는 다양하고 유용한 라이브러리가 굉장히 많다. 그렇기 때문에 많은 개발자들이 jQuery를 사용하는 것이다. 어떠한 메소드들이 있는지 살펴보자.

1. 배열관리 메소드
 $.each(objectArray, function(index, object){})
예)
$.each(array, function(index, obj){//첫 번째 인자로 배열의 인덱스가 오고 두 번째
var output = "";       //인자로 인덱스에 해당하는 객체가 넘겨진다.

output += "<a href=" + obj.link + ">";
output += "    <h1>" + index + " : " + obj.name + "</h1>";
output +="</a>"

document.body.innerHTML += output;
})

$(selector).each(function(index, object){})
예)
$(array).each(function(){//인자로 넘겨주는 값이 없을 때는 this로 객체에 접근 가능
var output = "";

output += "<a href=" + this.link + ">";
output += "    <h1>" + this.name + "</h1>";
output +="</a>"

document.body.innerHTML += output;
})



2. 객체 확장 메소드
$.extend(object, 속성 추가);
예)
var object = {};//빈 객체 생성

$.extend(object, {
    name: "용",
    gender: "남"
}


3. 필터링 메소드
$(selector).filter(selector);
filter의 인자의 선택자와 일치하는 배열 리턴(하나일 경우 하나의 객체만 리턴)


4. 특정 태그 선택 메소드
$(selector).find("tagName");
선택자 중에 tagName을 찾아 요소를 배열로 리턴(하나일 경우 하나의 객체만 리턴)

5. 속성 설정 및 속성 값 반환 메소드
$(selector).attr(name, value);
$(selector).attr(name, function(){});
$(selector).attr(objec);//object속성값 반환

그밖에 메소드들
css() : 스타일과 관련된 모든 기능을 수행(예: .css("font-size", "12 px"))
size() : 객체수를 반환
addClass() : 클래스 속성 추가
removeClass() : 클래스 속성 제거
attr() : 메서드의 인자를 통해 속성추가, 속성값 변경, 속성값 반환
removeAttr() : 속성을 제거
get() : jQuery객체를  DOM객체의 배열로 리턴(인자로 인덱스를 넣으면 배열에서 인덱스에 해당하는 DOM객체를 리턴)
not(expression) : 표현식에 일치하는 객체를 제거한 배열리턴
has(expression) : 표현식과 일치하는 자식을 가진 객체의 배열리턴
is(expression) : 표현식과 일치하는 객체의 배열리턴
end() : jQuery체인에 주로 이용되며 이전선택으로 돌아간다.
andSelf() : 체인에서 이전 두개의 선택자를 하나로 합친다.
html() : 객체 내부의 글자와 관련된 모든 기능 수행(html태그 인식)
text() : 객체 내부의 글자와 관련된 모든 기능 수행
find() : 특정 태크를 선택
remove() : 객체를 제거
empty() : 객체의 후손을 모두 제거
clone() : 객체를 복사
offset() : 객체의 위치를 조회하거나 지정
wrap() : 객체를 싸버린다. 선택한 객체를 자식으로 두고 싶을 때 사용.
$() : 객체 생성
$(A).appendTo(B) : A를 B의 뒷 부분에 추가(자식(A)을 부모(B)내용에 뒤에 붙인다)
$(A).append(B) : B를 A의 뒷 부분에 추가
$(A).prependTo(B) : A를 B의 앞 부분에 추가(자식(A)를 부모(B)내용에 앞에 붙인다)
$(A).prepend(B) : B를 A의 앞 부분에 추가
$(A).insertAfter(B) : A를 B의 뒤에 추가
$(A).After(B) : B를 A의 뒤에 추가(형제 B가 A의 뒤에 추가)
$(A).insertBefore(B) : A를 B의 앞에 추가
$(A).before(B) : B를 A의 앞에 추가(형제 B가 A의 앞에 추가)

2013년 2월 26일 화요일

[JS] jQuery - 이벤트

 자바스크립트에서 브라우저의 이벤트를 연결 시키는 이벤트 모델에 대해 공부하였다. DOM 레벨에 따른 이벤트 연결 방식이 몇가지 있었다. 그러나 주의해야할 점은 항상 브라우저간 차이점을 고려하여 코딩을 해야했었다.(표준 브라우저, IE브라우저)

그러나 jQuery에서는 크로스 브라우징이 가능하다. 이는 표준 브라우저와 IE브라우저에 관계없이 스크립트 제작이 가능하다. 이것이 jQuery의 장점이다.

 jQuery의 이벤트는 기존 자바스크립트의 이벤트가 모두 존재한다. 그러나 자바스크립트의 이벤트 연결보다 훨씬 간편하다.


$(selector).bind(eventName, data, handler)
$(selector).bind(object)
이벤트 할당 함수
eventName : 이벤트 이름(예 : click)
data : 핸들러에 사용할 데이터(생략가능)
handler : 이벤트 핸들러

이벤트종류












$(selector).unbind(event)
$(selector).unbind(eventName)
$(selector).unbind(eventName, handler)
이벤트 핸들러 제거
event : 이벤트를 발생시킨 객체의 정보

$(selector).toggle(handler, ...,handler)
click이벤트를 여러 핸들러로  번갈아가며 실행

$(selector).hover(handler, handler)
mouseenter이벤트와 mouseleave이벤트를 동시에 연결

$(selector).delegate()
현재 또는 미래에 존재하는 문서 객체에 이벤트를 연결

$(selector).live()
현재 또는 미래에 존재하는 문서 객체에 이벤트를 연결

$(selector).one(eventName, handler)
이벤트를 한 번만 연결

$(selector).trigger(eventName)
$(selector).trigger(eventName, data)
인벤트를 강제로 발생(사용자의 입력이 따로 필요없이 이벤트를 실행시킴)

이벤트 객체
이벤트를 연결할때 핸들러에는 event객체가 자동으로 인자로 넘어간다.

속성
event.pageX : 브라우저의 화면을 기준으로 한 마우스의 X 좌표
event.pageY : 브라우저의 화면을 기준으로 한 마우스의 Y 좌표
event.preventDefault() : 기본 이벤트 제거
event.stopPropagation() : 이벤트 버블링 제거

이벤트 통합 메서드
jQuery에서는 이벤트를 통합하여 연결시키는 on()과 off()를 권장하고 있다.

on() : 이벤트를 연결
off() : 이벤트를 제거
$(selector).on(eventName, handler) - bind()와 같은 역할
$(selector).off(eventname[handler,,,]) - nubind()와 같다

[JS] jQuery - 선택자

CSS에서 선택자에 대해서 공부해 보았다. HTML 문서에서 가장 중요한 부분은 내가 원하는 요소를 얼마나 잘 가져오는지가 중요하다.

CSS에서 선택자를 이용하여 원하는 요소에 원하는 스타일을 줄 수 있었고 자바스크립트에서도 DOM을 통해 원하는 객체를 어떻게 가져와야하는지가 중요했다. 왜냐? 객체를 가져와야 그 속성을 추가하거나 제거하고 메소드를 이용하면서 프로그램을 제작할 수 있다.

사실 조작할 대상을 잘 선택하고 조작해야한다. 그것이 프로그램의 중요한 원리 중 하나이다.

선택자는 jQuery에서도 굉장히 중요하다. 선택자만 잘 알아도 jQuery의 반을 마스터 한 것이다. CSS를 하면서 공부했던 선택자를 잘 상기하도록 하자.

일단 기본적으로 알아야 할 내용은 $()에 css선택자 문자열을 전달하면 일치하는 요소의 집합을 나타내는 jQuery를 반환한다는 것이다. 즉, 조회의 결과로 하나의 요소만 일치한다면 하나의 객체만을 얻어서 원하는 작업을 처리해 줄 수 있지만 집합을 얻을 때가 많을 것이고 이를 잘 처리해야하는 것이 프로그래머의 몫이다.(반환되는 요소집합이 배열과 유사하기는 하지만 실제 배열은 아니다)

1. 전체선택자 - $("*")
2. 태그선택자 - $("태그명")
3. 아이디선택자 - $("#아이디")
4. 클래스선택자 - $(".클래스")
5. 자식선택자 - $("부모 > 자식")
6. 후손선택자 - $("부모 후손")
7. 속성선택자
요소[속성] : 특정 속성을 가진 요소(객체) 선택
요소[속성=값] : 해당하는 속성과 값이 일치하는 요소 선택
요소[속성~=값] : 속성에 특정한 값을 단어로써 포함하는 요소 선택
요소[속성^=값] : 속성에 특정값으로 시작하는 요소 선택
요소[속성$=값] : 속성에 특정값으로 끝나는 요소 선택
요소[속성*=값] : 속성에 특정값을 포함하는 요소 선택


8. 입력(input) 양식필터  선택자
요소:button = input 태그 중 type속성이 button인 요소 선택
(종류 : button, checkbox, file, image, password, radio, reset, submit, text)
요소:checked = 체크된 input요소 선택
요소:disabled = 비활성화된 input요소 선택
요소:enabled = 활성화된 input요소 선택
요소:focus = 입력대기 중인 input요소 선택
요소:input = 모든 input요소 선택
요소:selected = option요소 중 선택된 요소 선택

9. 선택필터 선택자
요소:odd = 홀수 번째에 위치한 요소 선택
요소:even = 짝수 번째에 위치한 요소 선택
요소:first = 첫 번째 위치한 요소 선택
요소:last = 마지막에 위치한 요소 선택
요소:animated : 현재 애니매이션이 적용되고 있는 요소 선택
요소:header : 헤더 요소 선택(h1~h6)
요소:hidden : 감춰진 요소 선택
요소:visible : 보여지는 요소 선택


10. 함수필터 선택자
요소:contains(문자열) = 특정 문자열을 포함하는 요소 선택
요소:eq(n) = n번째에 위치하는 요소 선택
요소:gt(n) = n번째의 위치를 초과하는 요소 선택
요소:has(selector) = 선택자로 선택한 요소를 가지고 있는 요소 선택
요소:lt(n) = n번째 위치 미만인 요소 선택
요소:not(selector) = 선택자로 선택한 요소를 가지고 있지 않은 요소 선택
요소:nth-child(3n+1) = 3n+1번째 위치하는 요소 선택(1, 4, 7, 10...)


몇가지 예를 보도록하자.

p:odd = p태그 중 홀수번째 태그 선택
ul li:last-child = ul태그 안에 li태그 중 마지막 태그 선택
table#laguage td:nth-child(1) = laguage라는 아이디를 가진 테이블 안에 td태그 중 인덱스가 1인 태그 선택
$("input[type=checkbox][checked]")
타입이 checkbox이고 체크되어진 input객체를  jQuery객체로  선택.
checkbox:checked:enabled = 활성화되고 선택이 되어 있는 체크박스 객체 선택
input:not(:checkbox) = input객체 중 checkbox가 아닌 객체 선택
img:not([src*="dog"] = img객체 중 src속성에 "dog"를 포함하지 않는 객체 선택
div:has(span) = div객체 중 span객체를 가지는 객체 선택




[JS] jQuery

 인터넷에는 다양한 어플리케이션(RIA)가 많이 존재한다. 웹서핑을 하다보면 무수히 많은 웹 어플리케이션을 만나게 된다. 하지만 매번 install을 해야만 하고 웹서핑을 하면 할수록 내 컴퓨터에는 잘 알지도 못하는 프로그램들이 수두룩하다.

이것은 플러그인 기반의 RIA들 때문인데 이러한 단점을 보완하기 위해 AJAX가 등장하게 되었다. 브라우저 기반의 다양한 어플리케이션을 제공함으로써 별다른 프로그램 설치가 필요없게 되는 것이다.
 AJAX를 하기 위한 기반 언어가 자바스크립트이고 자바스크립트의 강력한 라이브러리로 사용되고 있는 jQuery가 있다.

jQuery란 자바스크립트 라이브러리로써 DOM과 Ajax의 복잡성을 쉽게 다루기 위해 만들어 졌다.

특징
소스가 자바스크립트에 비해 단순해지며 다양하고 유용한 플러그인이 있다. 빠르게 업데이트 되고 있고 이는 많은 개발자들이 jQuery를 사용하고 있다는 증거이기도 하다.
 실제로도 수많은 대형 웹사이트에서 jQuery를 사용하고 있고 미국의 웹개발자 중 65%가 jQuery를 사용한다고 한다.
 또한 jQuery는 다루려는 문서 요소를 찾기 쉽게 만들어 주며, 찾은 후에 내용 추가나 HTML속성과 CSS의 수정, 이벤트 핸들러 정의, 애니메이션 적용 같은 작업을 할 수 있다.

jQuery라는 이름으로부터 알 수 있듯이 조회에 초점을 둔 라이브러리이다. 그 중에 강력한 기능은 바로 원하는 요소에 순차적인 적용(스타일 또는 동작)을 표현하기 위한 메서드 체인 기법이다.

실제 jQuery를 사용하기 전에 알아야할 메소드가 있다.
$(document).ready(function(){
          ...코드...
});

여기서 처음 보는 $함수는 jQuery의 객체를 선택하고 객체가 jQuery의 속성과 메소드, 즉 라이브러리를 사용할 수 있는 것을 의미한다.(팩터리 함수라 하며 jQuery의 전역함수이다.)

위에 jQuery메소드는 문서의 구조만 다 읽어들인 뒤 호출된다. 반면에 $(window).load(function(){
         ...코드...
});
메소드는 문서구조 뿐만 아니라 관련된 리소스들까지 모두 로드한 뒤에 호출된다. 따라서 어느 정도의 속도차가 두 메소드 사이에 존재한다.

여기서는 주로 $(document).ready()를 많이 사용할 것이다.

2013년 2월 25일 월요일

[JS] window.onload로 2개 함수 로드

window 객체의 onload()를 언급한바 있다. HTML문서의 모든 태그들을 다 로드한 뒤에 실행되는 메서드로써 태그에 연결되어 있는 이벤트 함수를 로드한다.

그런데 onload()를 이용하여 두개의 함수를 연결하고자 한다면 다음과 같은 실용적인 코드가 있다. 유용하니 잘 알아두자.

function addEvent(func){//사용자 정의함수. 인자로 함수를 받는다.
    var oldonload = window.onload;//처음에 로드한 함수를 변수에 저장한다.없다면 null
    if(typeof window.onload != "function"){//타입을 검사하여 처음로드되는 것인지 판단
        window.onload = func;//처음로드되는 함수라면 등록
    }else{
        window.onload = function(){//이미 로드된 함수가 있다면 둘다 호출
            oldonload();
            func();
        }
    }
}

addEvent(func1);
addEvent(func2);

2개의 서로다른 함수를 로드하는 새로운 사용자 정의 함수이다.

[JS] 정규표현식

정규표현식은 참 유용한 면이 많다. 문자열은 생각보다 많이 다루게되고 문자를 조작하거나 검색하는데 정규표현식이 굉장히 편리하다. 따라서 자바스크립트에서는 내장객체로써 정규표현식 객체를 제공한다.

생성 방법
1. var reg = /"문자열이나 패턴, 수량, 이스케이프 문자의 조합"/플래그;
2. var reg = new RegExp("문자열이나 패턴, 수량, 이스케이프 문자의 조합", "플래그");

메소드
exec()
- 정규표현식과 일치하는 문자열을 리턴

test()
- 정규표현식과 일치하는 문자열이 있는지 없는지를 나타냄(boolean)


match(regExp)
- 정규표현식과 일치하는 부분을 리턴


replace(regExp, replacement)
- 정규표현식과 일치하는 부분을 지정한 문자열로 치환

search(regExp)
- 정규표현식과 일치하는 부분의 인덱스를 반환

split(regExp)
- 정규표현식을 기준으로 문자열을 잘라 배열을 리턴

대체문자
$& : replace()를 사용할 때 일치한 문자열을 가리킴
$` : 일치하는 부분의 앞부분 문자열을 가리킴
$' : 일치하는 부분의 뒷부분 문자열을 가리킴
$1, $2, $3 : 그룹

플래그문자
g(Global) : 전역 매칭
m(Multiple) : 여러 줄 매칭
i(Ignore Caes) : 대소문자 구분 않음

앵커문자
^ABC : 맨 앞 문자가 ABC
ABC$ : 맨 뒤 문자가 ABC

메타문자
. : 아무문자
[abc] : 괄호 안의 글자
[^abc] : 괄호 안의 문자 제외
[a-z] : a부터 z까지만 입력
[A-Z] : A부터 Z까찌만 입력 ([A-Za-z]로도 쓰임)
[0-9] : 숫자만 입력
\d : 숫자
\D : 숫자 이외
\s : 공백문자
\S : 공백문자 이외
\w : 알파벳과 숫자로 된 문자
\W : 알파벳과 숫자로 된 문자 제외(특수문자)

수량문자
a+ : 하나이상
a* : 0개 또는 하나 이상(여러개)
a? : 0개 또는 1개
a{숫자} : 숫자에 매치(자리수)


2013년 2월 23일 토요일

[JS] 브라우저 객체 모델(BOM) - 나머지 객체들

Screen
웹 브라우저의 화면이 아니라 운영체제 화면의 속성을 가지는 객체이다.

속성
width : 화면의 너비
height : 화면의 높이
availWidth : 실제 화면에서 사용 가능한 너비
availHeight : 실제 화면에서 사용 가능한 높이
colorDepth : 사용 가능한 색상 수
pixelDepth : 한 픽셀당 비트 수

location
브라우저의 주소 표시줄과 관련된 객체

속성
href : 문서의 URL 주소
host : 호스트 이름과 포트 번호
hostname : 호스트 이름
port : 포트 번호
pathname : 디렉토리 경로
hash : 앵커 이름(#~)
search : 요청 매개 변수
protocol : 프로토콜 종류

메서드
assign(link) : 현재 위치를 이동
reload() : 새로 고침
replace(lick) : 현재 위치를 이동(뒤로가기 버튼 사용 X)

navigator
웹 페이지를 실행하고 있는 브라우저에 대한 정보를 가진 객체

속성
appcodeName : 브라우저의 코드명
appName : 브라우저의 이름
appVersion : 브라우저의 버전
platform : 사용 중인 운영체제의 시스템 환경
userAgent : 브라우저의 전체적인 정보



[JS] 브라우저 객체 모델(BOM) - Document

Document 객체는 최상위 객체인 window객체의 하위 객체로 문서에 대한 모든 정보를 관리하는 객체이다.

속성
nodeName : 노드 이름
nodeType : 특정 노드의 형식을 지정
nodeValue : 텍스트 노드의 문자열 값
childNodes : 하위 노드의 리스트
firstChild : 하위 노드 리스트 중 첫번째 노드
lastChild : 하위 노드 리스트 중 마지막 노드
parentNode; 자신의 부모 노드
nextSibling : 자신의 다음 형제노드
previousSibling : 자심의 바로 앞 형제 노드
innerHTML : 태그의 내용

메소드
open() : HTML문서에 데이터를 보낼 준비를 하거나 데이터를 모두 전송했음을 알림
close() : open()로 열려진 문서를 닫아 주는 역할
clear() : 브라우저에 나타난 문서를 지움
write() : 지정된 문서의 데이터를 출력
writeln() : 지정된 문서의 데이터를 출력
createElement(tagName) : 요소 노드를 생성
createTextNode(text) : 텍스트 노드를 생성
appendChild(node) : 객체에 노드를 연결
item(index) : 객체배열 중 해당하는 이덱스 객체 리턴
getElementById(id) : id를 가진 태그(객체)를 리턴
getElementsByName(name) : name을 가진 태그의 배열 리턴
getElementsByTagName(tagName) : tagName과 일치하는 태그의 배열 리턴
getAttribute(String attrName) : 속성값 검색
setAttribute(String attrName, String attrValue) : 속성값 설정
removeChild(child) : 자식노드 제거
insertBefore(Nod new, Node target) : target 엘리먼트의 형제로 앞에 추가(특정 위치 앞)
replaceChild(Node new, Node old) : 자식노드교체
hasChildNodes() : 자식 노드 여부 검사
cloneNode(boolean deep) : 노드복사

다음은 Document 객체의 하위 객체에 대해 알아보자.

Image 객체
<img>태그의 정보를 가진 객체

속성
name : 이미지 객체의 이름
src : 이미지의 URL 주소
lowsrc : 이미지의 URL 주소를 나타내며 해상도가 낮은 이미지를 전송할 때 사용
height : 이미지의 높이
width : 이미지의 넓이
border : 이미지의 테두리
complete : 이미지를 모두 전송받았는지를 알림(boolean)

Form 객체
<form>태그의 정보를 가진 객체로써 폼안에 데이터를 접근하기 위해 많이 사용된다.

속성
action : 서버 CGI 프로그램의 URL을 지정
elements : Form입력 양식에 대한 객체 정보들의 배열
enctype : 서버 CGI 프로그램에 보낼 데이터의 타입을 지정
method : 데이터 전송방식(get, post 등)
target : 처리된 결과를 출력할 윈도우 또는 프레임
length : Form 객체의 갯수
name : Form의 이름

핸들러
onSubmit : 사용자가 입력 양식의 데이터를 서버로 전송할 때 사용되는 이벤트 핸들러
onReset : 입력 양식을 초기화 할 때 사용되는 이벤트 핸들러

메소드
submit() : 입력 양식의 데이터를 서버로 전송할 때 사용
reset() : 입력 양식을 초기화 할 때 사용

---------------------------------------------------------------------------------

Form 객체에는 <input>태그의 타입으로 하위 객체들이 있다. text, button, checkbox, radio, select, textarea, password, hidden 이 하위 객체들의 종류다. 하나씩 살펴보자.

text 객체
문자열을 입력할 때 사용되는 객체이다.

속성
name : 객체의 이름
id : 객체의 id
value : 객체의 값
defaultValue : 관리자에 의해 미리 지정된 객체의 값
type : text객체임을 지정

메소드
focus() : 포커스를 얻음
blur() : 포커스를 잃음
select() : 입력된 값을 선택

핸들러
onFocus : 포커스가 text 객체 안으로 이동할 때 발생
onBlur : 포커스가 text 객체 밖으로 이동할 때 발생
onSelect : text 객체에 입력된 문자열을 선택할 때 발생
onKeypress : text 객체 내에서 키보드를 눌렀을 때 발생
onChange : text 객체에 입력한 문자열이 변경할 때 발생

checkbox 객체
여러 개의 선택 항목 중에서 하나 이상의 항목을 선택하는 객체

속성
checked : 선택여부 지정
name, value, type은 텍스트와 동일

핸들러
onClick : 객체를 클리할 때 발생

radio 객체
여러 개의 선택 항목 중에서 하나의 항목을 선택할 때 사용되는 객체

속성
defaultChecked : 디폴트로 선택되었음을 지정
length : 객체의 갯수
checked, name, value, type은 checkbox와 동일

핸들러
checkbox와 동일

select 객체
여러 개의 목록 중에서 하나 이상을 선택할 때 사용되는 객체
option 객체를 하위객체로 가진다.

속성
selectedIndex : 현재 선택된 목록의 인덱스
options : 목록 정보 배열
options[i].index : 각 목록의 인덱스
options[i].value : 각 목록에 할당된 값
options[i].text : 각 목록에 할당된 문자열
options[i]. selected : 각 목록이 선택되어 있는지 여부
options[i].defaultSelected : 각 목록이 처음 선택되어 있는지 여부

핸들러
onChange : 다른 목록을 선택할 때 발생

textarea 객체
text객체의 속성, 메소드, 핸들러 동일하며 다른 점은 줄바꾸기가 가능하다.

password 객체
입력한 글자를 "*"와 같은 문자로 표현

hidden 객체
시각적으로 표현되지 않은 감추어진 데이터 전송시에 사용