오늘 고객사에서 급하게 공지사항을 올리고싶다고 연락이왔다. 현재는 사이트 기획중인 프로젝트이고 도메인하나 따서 올려드린게 전부였다. 전자정부프레임워크 기준으로 작업을 진행하면서 패키지를 생성중이였는데 문뜩 다른 개발자들의 패키지 표준이 궁금하여서 구글링하던 중 패키지관련 좋은글이 있어서 올린다. 패키지관련 고민중이신 분들에게 도움이 되면 좋겠다.

===========================================================

출처 : http://egloos.zum.com/springmvc/v/434948

===========================================================



자바 프로젝트를 진행하면 프로그래머들이, 여타 직장인들처럼 "오늘 점심메뉴는 뭘 먹을까?" 하듯 고민이 하는 부분이 한가지 있다. 물론 프로그래밍을 하다보면 많은 부분에서 고민을 해야겠지만 그중에도 가장 쉬우면서 딱히 가이드 잡기가 어려운 패키지별로 클래스를 정리하는 과정이 그러하다. 프로그래머는 도대체 어떤 기준으로 클래스를 분류해야 체계적으로 자신의 프로젝트를 분류가 되었고, 더 나아가 팀으로 작업할 시에 "왜 이 클래스는 이 패키지에 넣은 거죠?" 라는 난해한 질문을 받지 않을 수 있을까?


먼저 패키지 분류가 복잡해지라도 하나의 원칙과 명확한 분류기준이 있다면 그때그때 프로젝트마다 뒤죽박죽으로 바뀌는 마구잡이식 분류법을 피할 수 있다. 마구잡이식 프로젝트는 코드의 가독성을 해치고 확장성을 망가뜨리는 나쁜 프로그래밍 방법이다. 게다가 구분과 명분이 확실해야 차후에 프로젝트를 진행할 때도 미리 명확한 기준에 맞춰 진행할 수 있고 현재 작성된 코드를 재활용하는데도 사용자 간에 특별한 교육없이도 막힘이 사용할 수 있게 도와준다. 여기에 조금 플러스하자면 잘 분류된 클래스는 2인 이상, 3인 이상 할 것없이 수백명의 프로그래머들과 함께 작업을 하더라도 서로 헷갈릴 이유가 없다.


더욱이 이런 작업 기준을 미리 정해놓는 중요한 이유는 자바의 패키지 분류작업은 작업이 완료된 시점에서 실행되는 것이 아니라 코딩을 해나가는 과정에서 함께 일어나기 때문이다. 모든 작업을 완료한 뒤에서야, "아 이건 내가 여기로 분류 했어야지...."라고 생각해 생각없이 클래스들을 옮겨댔다간 해당 클래스에 의존하고 있는 다른 클래스의 import문이 엉켜 엉망이 될 수 있다. 물론 이클립스는 이런 클래스 파일의 이동을 안전하게 보장해주는 자동 클래스패스 수정 기능이 있지만 이것은 자바 파일에만 한정되있을 뿐 jsp나 다른 xml문서에 대해서는 자동수정을 보장해주지 않는다.

그러므로 이런 보이지 않는 약속같이 중요한 작업은 개인의 독단적인 기준에 의해 분류될 것이 아니라 명확한 분류 기준과 서로 공감대를 가질 수 있는 원칙이 필요하다. 현재 작성되고 있는 이 문서는 기본적인 패키지 분류법에 대해 기술할 것이며 주된 목적은 웹기반 서비스들의 패키지 분류법이다.


패키지 분류 법칙 1. 루트 패키지는 x.y.z 식으로 구성한다.

x.y.z 식이란 최초의 프로젝트 생성시 프로젝트의 패키지를 최소 3단계로 분류해야 한다는 뜻이다. (물론 x.y.z라는 말은 필자가 기억하기 쉬우라고 만든 용어이므로 오용해서는 안된다.) 대부분의 프레임워크나 상용서비스들을 보면 이런 법칙을 준수해서 만드는 것을 볼 수 있는데 먼저 기본 루트 패키지를 굳이 3단계씩이나 걸쳐서 분류해야 하는지, 그 까닭을 보자.


import org.apache.taglibs.*

import net.sf.cglib.*

import com.sun.accessibility.*;


먼저 위의 import문 보자. 예리한 눈썰미를 가진 자바 프로그래머라면 위 코드만 보더라도 기존의 오픈소스 그룹들이 분명 보이지 않는 패키지 정렬법을 갖고 있다는 사실을 알 수 있다. 사실 오픈소스 그룹들 뿐만이 아니다. 대부분의 업계 또한 위의 법칙을 준수한다.

일단 첫번째로 org와 net으로 시작하는 가장 높은 부모 패키지가 보일 것이다. 이 패키지는 프로젝트를 이끄는 그룹의 성격을 결정한다. org는 organization의 약자인데 조직, 기구 단체를 뜻한다. 즉 비영리 그룹이나 단체가 될 것이다. 지극히 소규모의자바 동호회라 할지라도 어쨌든 org의 범주에 속한다. net은 정확히는 알 수 없지만, 이 라이브러리는 net을 기반으로 하는 기술이라는 것이라고 추측해 볼 수 있다. 그리고 그 아래의 com은 company의 약자로 영리 목적의 회사에서 제작한 프레임워크라는 것을 뜻한다. 만약에 회사에서 프로젝트로 라이브러리나 프레임워크, 또는 기본적인 기능소스를 구현할 지라도 classpath에는 명확히 이 소스의 단체 성격을 밝혀주어야 한다. 당장에는 필요 없더라도 확장시에 필히 요구되는 사항이다.

두번째로 apache, sf, sun을 보면 바로 알 수도 있겠지만 이 패키지 명은 자사의 그룹 또는 사명을 정해주는 구간이다. 일반적으로 회사라면 사명이 들어가고 그룹이라면 그룹명이 들어가는게 일반적이다. 이처럼 빈 루트패키지에 또 다시 빈 하위패키지를 정의해주는 이유는 만약에 이 소스가 본인 뿐 아니라 회사 내, 또는 그룹 내에서 활발하게 쓰인다면 누구나 프로젝트의 출처를 알 수 있게 되므로 작성자가 소스를 사용함과 동시에 출처 알게 된다는 것에 큰 의의가 있다. 작성자가 출처 정확히 알고 있다면 기능이 업데이트 되었을 시에 업그레이드된 프레임워크를 사용할 수도 있고, 필요하다면 사용자 피드백을 공유할 수도 있을 것이다.

세번째로 들어가는 taglibs나 cglib, accessibility는 실제 이 프로젝트의 artifact 구조를 뜻한다. 위의 두단계로 프로젝트 그룹의 성격과 그룹명을 정해주었다면 이젠 실질적인 소스의 역할 또는 프로젝트명이 들어가야 할 것이다. 예를 들어 설명해보자. 만약에 내가 삼성의 갤럭시 폰의 자바 프로젝트를 맡게 되었다면 패키지 명은 아래와 같이 정할 수 있다.


먼저 com.samsung으로 프로젝트의 그룹을 규정 해주고 그 하위 패키지로 galaxy라는 현재 프로젝트의 성격을 규정 지어준다. 많은 회사와 단체에서 이런 식으로 몇가지 단계를 나누어 패키지를 분류하는 이유는 성격을 구분짓는다는 이유 말고도 또 있다. 예를 들어 삼성이란 회사에서 galaxy 폰만 판다면 필자눈 굳이 위와 같은 분류로 힘들게 분류하지는 않았을 것이다. 오히려 아예 패키지를 com.samsung.galaxy로 하지 않고 galaxy로 심플하게 통일했을 수도 있고 패키지를 만들지 않았을지도 모른다! 하지만 삼성이런 거대기업은 galaxy만 팔진 않는다. 호텔사업도 하고, 놀이동산도 하고, 갤럭시도 2, 3, 4, 5… 돈이 될 때까지 찍어낼 것이다. 우리가 단 하나의 프로젝트를 구현하면서도 이런 그룹부분과 구조부분을 나뉘어 주는 것도 다 이런 이유에서이다. 즉 기업의 확장에 유연하게 대처할 수 있는 분류법을 사용해야 한다는 것이다. 당신이 이런 기본적인 구조만 갖춘다면 갑작스럽게 닥친 프로젝트에도 유연하게 패키지를 분류하고 빠르게 개발에 착수할 수 있게 된다.

더욱이 자바프로그래머로서 확장을 고려하지 않는 사람은 자바란 객체지향언어의 알맹이는 쏙빼고 껍질만 긁어먹는 사람과 똑같다. 정상적인 회사나 그룹이라면은 단체가 확장하고 번창하길 바라지, 축소를 바라는 단체는 없을 것이다. 게다가 그룹이 커지다 보면 회사나 단체가 책임에 따라 둘로 나뉠 수 있고 처음엔 비영리로 시작한 단체가 안타깝게도 영리 단체로 변모할 수도 있다. 우리가 이런 상황에 유연하게 대처하려면 이런 x.y.z 식의 구분은 필수로 갖추어야 한다.


패키지 분류 법칙 2. 기능별로 분류하자

작성중인 프로젝트를 위의 x.y.z식으로 분류한 다음은 어떻게 해야 좋을까? 이제부터 자바파일을 막 집어넣어도 되는 것일까? 간단하게 영광스런 제작자의 이름이나 어머니 아버지의 이름을 섞어서 패키지를 만드는 것은 어떨까? 아니면 간단하게 숫자나 알파벳순서로 패키지를 작성해 나갈까? 물론 모두 가능한 선택 옵션이지만 올바른 선택은 아니다. 먼저 글을 작성하기에 앞서 우리는 웹기반 서비스를 기준으로 패키지 분류하겠다고 밝혔는데 당신이 웹기반 서비스를 제작한다면 기본적으로 DB, MVC같은 기술과 계층을 나누는 식의 제작방식을 도입하려 할 것이다.

답을 먼저 말하지만 artifact id 이후로 나오게 될 패키지 분류는 가급적 기능의 성격으로 하는 것이 옳다. 이 성격이란 구분 지어 질 수 있는 가장 큰 성격을 말하는데 구체적으로 보자면 DB의 테이블이라 할 수도 있다. 기본적으로 업무에서 웹 프로젝트를 작성할 때 주된 작업은 DB에 있는 자료를 입력, 수정, 삭제하는 식의 작업이라는 사실을 개발경험이 있는 사람이라면 알 수 있을 것이다. (얼마나 DB 작업이 심하면 실무에서는 입출력만 알면 장땡이라는 말까지 있을 정도다.) 그리고 대부분의 DB작업은 테이블을 우선하여 결정짓게 되는데 테이블은 하나의 기능에 대하여 필요한 정보를 컬럼으로 묶는 식의 설계가 될 것이며 테이블은 한가지 기능에 대한 세부적인 세팅 데이터를 갖게 될 것이다.




그렇다면 우리는 단순히 테이블을 기준으로 분류를 나누기만 하면 패키지 분류에 대한 명확한 기준과 기능별 분류라는 이점까지 얻을 수 있다는 결론을 얻게 된다. 더욱이 중요한 것은 쿼리문은 한줄에 하나의 테이블에 대한 연산만 할 수 있도록 설계 되어 있다는 것이다. 물론 join이나 group같은 것을 사용하여 여러 테이블을 묶을 수도 있겠지만 궁극적으로 쿼리문은 한 테이블을 기준으로 동작 가능하게 설계하는 것이 옳다. 왜냐하면 코드의 재사용성을 고려하더라도 차라리 트랜잭션을 활용해 원자성을 유지하며 간단한 쿼리문을 사용하는 것이 좋지, 괜히 성능을 향상시킨다고 과도하게 쿼리문에 의존하다간 코드가 뒤죽박죽이 되버릴게 뻔하기 때문이다.

부득이하게 유지보수를 위하여 하나의 테이블을 여러 테이블로 나누었더라도 이 모든 테이블이 하나의 성격으로 통일될 수 있다면 복수의 테이블을 하나의 기능이라 생각하고 분류를 나누는 것도 좋다. 만약에 'phonebook'이라는 테이블이 있는데 이 테이블을 'phone'과 'book'이라는 테이블로 나뉘어 설계하는게 좋다면 당신은 phonebook.phone과 phonebook.book과 같은 식으로 패키지를 나눌 수도 있을 것이다.

테이블별로 분류한 당신의 패키지는 DB와 관련된 작업을 편리하게 해주면서 동시에 이 소스를 사용해 개발하는 사람들의 이해도를 대폭 상승시켜 줄 것이다. 더욱이 다양한 테이블이 서로 연관관계를 갖는 서비스 계층을 만든다 하더라도 사용자는 본인이 원하는 메소드가 어디에 위치한지 바로 알 수 있을 것이다.


패키지 분류 법칙 3. 계층별로 분류하자



기능별로 패키지를 분류하였다면 이젠 계층별로 분류하자. 사실 계층별로 분류하는 것은 기능별로 분류하는 것보다 더욱 중요한데 혹자는 이런 계층별 분류를 티어(tier, tiered) 또는 레이어(Layer)라고 부르기도 한다. 티어는 사용자가 어떤 디자인 모델을 차용하서 제작하느냐에 따라 갈리므로 작성자가 먼저 어떤 구조로 설계하는지 결정하는게 가장 중요하다. 기본적인 웹 계층이라면 MVC 구조로 많이 제작될 것이며 View는 JSP로 Controller는 서블릿 또는 스프링이나 스트럿츠 같은 프레임워크가 관리하는 형태로 제작 될 것이다. 결국 우리가 클래스로 묶어서 배포할 부분은 모델부분에 해당한다. 모델은 직접 DB에 접근하여 데이터를 가져오고 연산하여 컨트롤러에 넘겨주는 주된 역할을 담당한다.

그러면 모델계층을 한번 분할시켜보자. 모델은 DAO(Data Access Object, DB에 접속하여 데이터를 가져오는 클래스) 계층과 자바빈과 같이 테이블의 컬럼을 오브젝트로 변환시키는 domain계층, domain과 dao계층을 활용하여 직접적인 기능을 구현하는 service 계층 등으로 나뉠 수 있다. 이런 역할분담은 매우 기본적인 것이므로 이런 계층에 따라 패키지를 나누어주는 것이 좋다.

한번 예를 들어보자 필자가 삼성이란 기업의 갤럭시 폰 프로젝트에서 user란 테이블을 만들고 이에 대한 작업을 한다면 다음과 같은 패키지 구성을 할 수 있을 것이다.

각 패키지에는 해당 기술을 추상화 하는 인터페이스가 들어갔을 수도 있고 이것을 구체화 하는 Implement 클래스가 있을 수도 있다. 서비스 패키지는 서비스 내부에 또 다양한 패키지로 기능별 구분이 있을 수도 있고 단순히 한가지 서비스에 대한 클래스가 존재할 수도 있다.

물론 user에는 이보다 더 많은 컨트롤러의 역할을 해줄 수 있는 com.samsung.galaxy.user.web이나 해당 그룹을 지원해줄 수 있는 com.samsung.galaxy.user.support 같은 것들도 들어갈 수 있다. 위와같은 구성은 참고하여 활용할 수 있는 것이지 절대적인 것은 아니다. 중요한 것은 계층별로 패키지를 분류한다는 것이다!


패키지 분류 법칙 4. 패키지 분류의 이점

패키지를 분류하지 않고 하나의 기본 패키지에 몽땅 집어넣으면서 설계하려는 사람은 최소한 자바프로그래머로서는 존재하지 않을 것이다. 근데 이런 분류에 너무 시간이 뺏기고 기본적인 개념이 잡혀있지 않다면 개발하면서 점점 코드가 엉키게 되고 서로 기능과 역할의 경계가 모호해짐과 동시에 실패한 코드가 되고 만다.

만약에 당신이 프로젝트가 시작함과 동시에 척척 패키지를 프로젝트 성격에 맞게 분류하고 곧바로 작업에 착수한다면 알만한 사람들은 당신이 어떤 모델계층을 사용하려 하고 있고 어떤 방식으로 개발하려는지 충분히 이해하고 있다 판단하며 당신을 작업방식을 신뢰할 것이다. 믿지 못하겠지만 매우 간단한 패키지 분류에서조차 얼마나 프로그래밍 실력이 있느냐가 갈리는 것이다.

현재 작성되고 있는 문서는 웹개발에 초점을 맞추어 작성되었지만 다른 소프트웨어 개발 프로젝트에서도 충분히 응용이 가능한 패턴이다. 다른 글에서도 재차 말했지만 초기세팅에 시간을 허비하는 것만큼 낭비가 없다. 만약에 모델의 세부계층에 대해 이해하지 못했다면 검색을 통해 지식을 쌓도록 하자. 모델계층의 계층분할은 곧 역할 분할로 이어지고 효율적이고 체계적인 프로그래밍을 가능케 해준다.


저번주에 웹서버 메일세팅을 하여 MS사의 Outlook이나 Mozilia사의 Thunderbird를 이용하여 웹 서버 작업을 하였습니다. 기본적으로 출처 사이트를 대부분 참고하였고 개인적인 설정변경을 통하여 서버에 작업을 하였습니다. 1차 작성이유는 개인적으로 웹서버 메일을 세팅한것을 잊어버리지 않기위하여, 둘째는 모자란 블로그이지만 미약하게나마 다른분들에게 도움이 될 수 있었으면 좋겠다는 취지로 작성하였습니다. 기본적인 서버세팅이지만 저처럼 리눅스를 많이 사용하지않거나 메일서버세팅을 해본적 없으신 분들을 위하여 작성하였습니다.

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

출처 : http://www.krizna.com/ubuntu/setup-mail-server-ubuntu-14-04/

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

리눅스에서 postfix와 dovecot을 이용하여 서버메일 설정작업을 진행하도록 하겠습니다.

/etc/hostname 에 가셔서 먼저 호스트 네임을 잡아줍니다.

mail.hostname.com

/etc/hosts에서는 ip호스트 네임을 같이 잡아줍시다.

192.168.1.1 mail.hostname.com

postfix를 설치하고 설정파일을 실행합니다.

//update
hostname@mail:~$ sudo apt-get update 

//postfix를 설치 합니다. 
hostname@mail:~$ sudo apt-get postfix

//postfix의 설정을 잡습니다. 
hostname@mail:~$ sudo dpkg-reconfigure postfix

아래에 있는 사진은 제 리눅스 서버에서 설정된 환경입니다.












설정이 완료되셨으면  /etc/postfix/main.cf 에 접속하셔서 아래와 같이 설정해주시기 바랍니다. 현재 제가 잡고있는 main.cf 파일 설정추가는 다음과 같습니다.

smtpd_tls_cert_file = /etc/ssl/certs/server.crt
smtpd_tls_key_file = /etc/ssl/private/server.key
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
myhostname = mail.hostname.com
mydomain = hostname.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = $myhostname, localhost. $mydomain, localhost, $mydomain
relayhost =
mynetworks = 127.0.0.0/8, 192.168.0.0/24
relay_domains = $mydestination
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
home_mailbox = Maildir/
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_local_domain =
smtpd_sasl_security_options = noanonymous
broken_sasl_auth_clients = yes
smtpd_sasl_auth_enable = yes
#smtpd_recipient_restrictions =permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination
smtpd_recipient_restrictions = permit_sasl_authenticated permit_mynetworks reject_unauth_destination
smtp_tls_security_level = may
smtpd_tls_security_level = may
smtp_tls_note_starttls_offer = yes
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes

작업후 tls 인증을 위하여 다음과 같이 작업합니다.

hostname@mail:~$ openssl genrsa -des3 -out server.key 2048
hostname@mail:~$ openssl rsa -in server.key -out server.key.insecure
hostname@mail:~$ mv server.key server.key.secure
hostname@mail:~$ mv server.key.insecure server.key
hostname@mail:~$ openssl req -new -key server.key -out server.csr
hostname@mail:~$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
hostname@mail:~$ sudo cp server.crt /etc/ssl/certs
hostname@mail:~$ sudo cp server.key /etc/ssl/private

설정작업의 경로설정 입니다.

hostname@mail:~$ sudo postconf -e 'smtpd_tls_key_file = /etc/ssl/private/server.key' hostname@mail:~$ sudo postconf -e 'smtpd_tls_cert_file = /etc/ssl/certs/server.crt'

위에 설정이 완료된 후에 /etc/postfix/master.cf 파일에 들어가셔서 아래와 같이 수정합니다. 


submission inet n       -       -       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
smtps     inet  n       -       n       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING


여기까지가 postfix관련 설정 이였습니다. main.cf에서 설정변경이 좀있었고 나머지는 기본 설정따라서 작업하였습니다. 다음 페이지에서는 dovecot설치와 telnet으로 설정 확인 하는 작업을 진행해보도록 하겠습니다.



구글에서 검색을 하다가 좋은글이 있어서 퍼온다.

출처 :http://blog.naver.com/seogi1004 


============================================================================================================

안녕하세요. 문학청년입니다. 정말 오랜만에 이렇게 글을 쓰는 것 같네요. 스터디 준비하랴.. 대회 준비하랴.. 요세 조금 바빠서 글 쓰는 것에 너무 소홀해버렸네요. 그럼 앞으로 다시 분발하여 열심히 쓰도록 하겠습니다.

잡설이 너무 길었네요. 오늘은 다름이 아니라 제가 처음이 연재 기획했던 것과는 달리 오늘은 기본 내용을 간략하게 정리해볼까 합니다. 물론 정리된 내용만 보면 재미가 없겠지요. 그래서 여러분들을 위해서 간단하게 할 수 있는 셀렉터 예제를 만들어봤습니다. 이 예제는 jQuery 오프라인 스터디에서도 사용을 했었는데요. 반응이 좋아서 이렇게 연재 강좌에도 예제로 사용해봤습니다.

한가지 팁을 드리자면 아래 정리된 내용을 출력하여 필요할 때마다 보는 것도 좋을 것 같구요.
아래 정리된 내용들을 살펴 본 뒤에 예제 페이지로 가서 직접 실습해보시면 이해하시는데 도움이 될 것입니다.

예제 페이지 이동하기



(1) Javascript 문법 스타일

기존의 프로그래밍 언어의 엄격한 문법 스타일에 적용되어 있는 사용자라면 분명히 자바스크립트의 자유 분방한 문법 스타일을 보고 적지않게 당황한적이 있을 것이다. 이러한 스타일은 단점이 될 수도 있으나 매우 유연하기 때문에 때에 따라서 매우 강력한 기능을 발휘한다. 그렇다면 가장 많이 사용되는 자바스크립트의 함수와 관련된 문법 스타일에 대해서 알아보도록 하자.

1. 함수를 변수에 설정할 수 있다.

1
2
3
var func = function() {
     alert("안녕");
};



2. 변수에 설정한 함수를 매개 변수로 사용하여 호출 할 수 있다.

1
showAlert(func);



3. 위와 같이 변수에 담지 않고 바로 함수를 매개 변수로 바로 설정 할 수 있다.

1
2
3
4
5
6
showAlert(function() {
     alert("안녕");
});

// 아래와 같이 한 줄로 사용하는 경우도 있다.
showAlert(function() { alert("안녕"); });



3번의 경우 조금 어렵게 생각할 수도 있는데 자세히 보면 그냥 함수 파라메터 값에 변수가 아닌 함수 그 자체가 들어가 있다고 간단하게 생각하면 된다. 이러한 표현식은 jQuery에서 상당히 많이 쓰이기 때문에 이러한 문법 스타일에 최대한 빨리 익숙해져야 한다.


(2) 셀렉터 요약 정리

셀렉터는 jQuery의 가장 강력한 기능이다. 간단하게 설명을 하자면, HTML 문서 안에는 다양한 엘리먼트들이 포함되어 있는데, 이를 컨트롤하기란 결코 간단한 일이 아니다. 일반적으로 자바스크립트에서 엘리먼트를 얻기 위해 많이 쓰이는 방법은document.getElementById("엘리먼트 ID 속성 값") 함수를 사용하면 되지만, 일단 소스 코드가 길어지고 얻을 수 있는 엘리먼트들도 매우 한정적이다.

하지만 jQuery에서는 $("셀렉터 문법") 함수를 사용하여 매우 간단하고 다양한 스타일의 엘리먼트들을 쉽게 얻을 수 있다. 셀렉터로 얻은 엘리먼트들을 확장 집합이라 하는데, 특수한 배열 형태의 객체로 반환이 된다. 이렇게 반환된 객체들은 jQuery가 지원하는 매우 다양한 함수들을 사용할 수 있다.

아래 표에 나와 있는 자식/에트리뷰트/컨테이너 셀렉터는 가장 많이 사용되는 셀렉터 문법이다.

셀렉터 문법
문법 설명
*
모든 엘리먼트
E
태그 명이 E인 모든 엘리먼트
E F
E의 자손이면서 태그명이 F인 모든 엘리먼트
E>F
E의 바로 아래 자식이면서 태그 명이 F인 모든 엘리먼트
E+F
E의 형제 엘리먼트로 바로 다음에 오는 엘리먼트 F
E~F
E의 형제 엘리먼트로 다음에 나오는 모든 엘리먼트 F
E:has(F)
태그 명이 F인 자손을 하나 이상 가지는 태그 명이 E인 모든 엘리먼트
E.C
클래스 명 C를 가지는 태그 명이 E인 모든 엘리먼트. E의 생략은 *.C와 동일함
E#I
아이디가 I인 태그 명이 E인 엘리먼트. E의 생략은 *#I와 동일
E[A=V]
값이 V인 에트리뷰트 A를 가지는 태그 명이 E인 엘리먼트
E[A=V]
값이 V로 시작하는 에트리뷰트 A를 가지는 태그 명이 E인 엘리먼트
E[A$=V]
값이 V로 끝나는 에트리뷰트 A를 가지는 태그 명이 E인 엘리먼트
E[A*=V]
값이 V를 포함하는 에트리뷰트 A를 가지는 태그 명이 E인 엘리먼트
E[A]
에트리뷰트 A를 가지는 태그 명이 E인 모든 엘리먼트
[자식/에트리뷰트/컨테이너 셀렉터]


아래 표는 jQuery가 지원하는 고급 위치 기반 셀렉터이며, DOM에서 위치를 기반으로 엘리먼트를 선택하며 첫 번째 링크나 홀수 번째, 짝수 번째와 같이 엘리먼트의 위치나 다른 엘리먼트와 관계를 기반으로 엘리먼트를 선택해야 하는 경우에 사용하면 된다.

셀렉터 문법
문법 설명
E:first
모든 엘리먼트 E 중에서 첫 번째인 엘리먼트
E:last
모든 엘리먼트 E 중에서 마지막인 엘리먼트
E:first-child
엘리먼트 E의 자식 엘리먼트 중에서 첫 번째인 엘리먼트
E:last-child
엘리먼트 E의 자식 엘리먼트 중에서 마지막인 엘리먼트
E:only-child
엘리먼트 E의 자식 엘리먼트 중에서 형제가 없는 엘리먼트
E:nth-child(n)
엘리먼트 E의 n번째 자식 엘리먼트
E:nth-child(even or odd)
엘리먼트 E의 홀수 or 짝수 자식 엘리먼트
E:even or E:odd
페이지 전체의 짝수 or 홀수 엘리먼트
E:eq(n)
태그 값이 E인 모든 엘리먼트 중에서 n번째로 일치하는 엘리먼트
E:gt(n)
태그 값이 E인 모든 엘리먼트 중에서 n번째 엘리먼트(포함 X) 이후의 엘리먼트
E:lt(n)
태그 값이 E인 모든 엘리먼트 중에서 n번째 엘리먼트 이전의 엘리먼트
[위치 셀렉터]


CSS 명세만으로는 표현할 수 없는 특성이 있는 엘리먼트를 선택해야 하는 경우 아래 표에 나와 있는 셀렉터를 사용하면 된다.

셀렉터 문법
문법 설명
:animated
현재 애니매이션이 적용되고 있는 엘리먼트 선택
:button
모든 버튼 선택
:checkbox
체크 박스 엘리먼트만 선택 (input[type=checkbox])
:checked
선택된 체크 박스나 라디오 버튼만을 선택
:contains(foo)
텍스트 foo를 포함하는 엘리먼트만 선택
:disabled
인터페이스에서 비활성화 상태인 모든 폼 엘리먼트를 선택
:enabled
인터페이스에서 활성화 상태인 모든 폼 엘리먼트를 선택
:file
모든 파일 엘리먼트를 선택 (input[type=file])
:header
헤더 엘리먼트 선택 (<h1>~<h6>)
:hidden
감춰진 엘리먼트만 선택
:image
폼 이미지만 선택 (input[type=image])
:input
폼 엘리먼트만 선택 (input, select, textarea, button)
:not(filter)
필터의 값을 반대로 변경함.
:parent
빈 엘리먼트를 제외하고, 텍스트도 포함해서 자식 엘리먼트를 가지는 엘리먼트
:password
패스워드 엘리먼트 선택 (input[type=password])
:radio
라디오 엘리먼트 선택 (input[type=radio])
:reset
리셋 버튼을 선택 (input[type=reset] or button[type=reset])
:selected
선택된 엘리먼트만 선택
:submit
전송 버튼을 선택 (input[type=submit] or button[type=submit])
:text
텍스트 엘리먼트만 선택 (input[type=text])
:visible
보이는 엘리먼트만 선택 
[jquery 정의 셀렉터]


(3) 자주 사용되는 함수 정리

$.유틸리티 함수, Event 관련 함수, Ajax 관련 함수는 이번 장에서 다루지 않을 것이다.
 
함수 명
함수 설명
엘리먼트 조작
each(Function)
선택된 엘리먼트가 다수일 경우에 each 함수를 사용하여 차례대로 엘리먼트를 선택한다.
에트리뷰트 조작
attr(name, value)
선택된 엘리먼트의 name 에트리뷰트의 값을 value로 설정
 
attr(name)
선택된 엘리먼트의 name 에트리뷰트의 값을 얻어옴.
 
attr(Attributes)
선택된 엘리먼트를 프로퍼티(json)형태로 설정할 수 있음
 
val()
엘리먼트의 value 에트리뷰트 값을 얻어옴. attr("value")와 동일함.
 
val(content)
엘리먼트의 value 에트리뷰트 값을 content로 설정함.
에트리뷰트 제거
removeAttr(name)
해당 어트리뷰트의 값이 초기화 된다.
스타일 변경
addClass(names)
선택된 엘리먼트에 CSS Class를 적용함. 만약에 다수의 Class를 적용하려면 공백으로 구분하여 할당하면 됨.
 
removeClass(names)
선택된 엘리먼트들을 제거함.
 
toggleClass(names)
특정 Class를 적용하지 않은 상태면 적용하고, 적용한 상태면 제거함.
스타일 얻고 설정
css(name, value)
선택된 엘리먼트의 name 에트리뷰트 값을 value로 설정함.
 
css(properties)
{"name1:" value1", "name2": "value2", } 와 같은 형태로 설정함.
 
css(name)
특정 name의 프로퍼티의 스타일 값을 얻을 수 있음.
 
width(value)
선택된 엘리먼트의 width 값을 설정함.
 
height(value)
선택된 엘리먼트의 height 값을 설정함.
 
width()
선택된 엘리먼트의 width 값을 얻어옴.
 
height()
선택된 엘리먼트의 height 값을 얻어옴.
 
offset()
선택된 엘리먼트의 left 값과 top 값을 E.offset().left,E.offset().top과 같은 방법으로 얻을 수 있음.
엘리먼트 내용 설정
html()
선택된 엘리먼트 태그 내용을 얻을 수 있음.
 
html(content)
선택된 엘리먼트의 태그 내용을 content로 설정함.
 
text()
선택된 엘리먼트의 태그 내용 중 텍스트 값만 얻을 수 있음.
 
text(content)
선택된 엘리먼트의 태그 내용을 content로 설정함.
엘리먼트 복사&이동
append(content)
선택된 엘리먼트의 내용 마지막에 새로운 content를 추가함.
 
appendTo(target)
선택된 엘리먼트가 단일이면 target으로 이동시키고 다수라면 복사됨.
 
prepend(content)
append와 달리 앞으로 추가함
 
prependTo(target)
appendTo와 달리 앞으로 복사 또는 이동함
 
before(),
insertBefore()
엘리먼트를 대상의 첫 번째 자식으로 삽입하는 대신에 대상의 바로 앞 형제로 추가함.
 
after(),
insertAfter()
엘리먼트를 대상의 마지막 자식으로 삽입하는 대신에 대상의 바로 뒤 형제로 추가함
엘리먼트 감싸기
wrap(wrapper)
매개 변수로는 String과 엘리먼트 타입이 올 수 있으며, "<div class='hello'></div>" 형태로 매개 변수 값을 넘기면 됨.
 
wrapAll(wrapper)
선택된 모든 엘리먼트를 wrapper로 감쌈
엘리먼트 제거
remove()
페이지 DOM에서 확장 집합의 모든 엘리먼트를 삭제함.
 
empty()
일치하는 집합의 모든 엘리먼트의 Content를 제거함.
엘리먼트 복사
clone(copyHandlers)
일반적으로 엘리먼트를 복사한 확장 집합을 만들면 이들은 DOM 어딘가에 덧붙일 수 있음
[함수 정리 (1)]



(4) 그 밖에 함수 정리

아래 표에 정리된 함수들은 확장된 엘리먼트 집합을 관리하는 함수들이다.

 
함수 명
함수 설명
확장 집합 크기 얻기
size()
해당 엘리먼트의 개수를 반환한다.
확장 집합에서 특정 엘리먼트 얻기
get(index)
확장 집합에서 index번째의 엘리먼트를 가져온다. (배열과 유사함)
 
get()
모든 확장 엘리먼트를 일반 자바스크립트 배열로 얻는다.
 
index(element)
확장 집합에서 특정 엘리먼트의 index 값을 가져온다.
확장 집합 재편성 하기
add(element)
기존의 확장 집합에 다른 엘리먼트를 추가한다.
 
not(expression)
기존의 확장 집합에서 expression와 일치하는 엘리먼트를 제외시킨다.
 
filter(expression)
기존의 확장 집합에서 expression와 일치하는 엘리먼트만 가져온다.
확장 집합의 부분 집합 얻기
slice(begin, end)
기존의 확장 집합에서 begin번째부터 end번째까지의 엘리먼트만 가져온다.
확장 집합 관련 그 밖에 함수들
find(selector)
기존의 확장 집합에서 selector와 일치하는 엘리먼트들로 새로운 확장 집합을 생성한다.
 
is(selector)
기존의 확장 집합에서 selector와 일치하는 엘리먼트가 있다면true, 없다면 false를 반환한다.
jQuery 체인 관리하기
end()
이전 확장 집합을 반환한다.
 
andSelf()
커맨드 체인에서 이전 확장 집합 두 개를 하나로 합친다
관계를 이용하여 확장 집합 얻기
 
아래 표 참조.
[함수 정리 (2)]


함수 명
설명
children()
확장 엘리먼트의 고유한 자식으로 구성된 확장 집합 반환한다.
contents()
엘리먼트의 콘텐츠로 구성된 확장 집합을 반환한다.
next()
확장 집합 내의 각 확장 엘리먼트 바로 다음에 나오는 형제로 구성된 확장 집합을 반환한다.
nextAll()
확장 집합 내의 각 확장 엘리먼트 바로 다음에 나오는 모든 형제로 구성된 확장 집합을 반환한다.
parent()
바로 위 부모로 구성된 확장 집합을 반환한다.
parents()
바로 위 부모와 모든 조상이 포함하는 확장 집합을 반환한다.
prev()
바로 이전에 나오는 형제로 구성된 확장 집합을 반환한다.
prevAll()
이전에 나오는 모든 형제로 구성된 확장 집합을 반환한다.
siblings()
확장 엘리먼트 내에 모든 형제를 포함한 확장 집합을 반환한다.
[관계를 이용하여 확장 집합 얻기와 관련된 함수 정리]


'자바스크립트 > jquery' 카테고리의 다른 글

Jquery 기본  (0) 2015.11.27

+ Recent posts