클라이언트의 요청을 받았을 때 그 요청에 대해 실제 업무를 수행하는 모델 컴포넌트를 호출하는 일을 한다. 또 클라이언트가 보낸 데이터가 있다면, 모델을 호출할 때 전달하기 쉽게 데이터를 적절히 가공하는 일을 한다. 모델이 업무를 수행을 완료하면, 그 결과를 가지고 화면을 생성하도록 뷰에게 전달한다.
즉 클라이언트 요청에 대해 모델과 뷰를 결정하여 전달하는 일을 한다.
데이터 저장소와 연동하여 사용자가 입력한 데이터나 사용자에게 출력할 데이터를 다루는 일을 한다. 특히 여러개의 데이터 변경 작업(추가, 변경, 삭제)을 하나의 작업으로 묵는 트랜잭션을 다루는 일도 한다.
모델이 처리한 데이터나 그 작업 결과를 가지고 사용자에게 출력할 화면을 만드는 일을 한다. 이렇게 생성된 화면은 웹브라우저가 출력한다.
즉 뷰 컴포넌트는 HTML과 CSS, JavaScript를 사용하여 웹 브라우저가 출력할 UI를 만든다.
look and feel
을 쉽게 교채할 수 있다.on source multi use
를 쉽게 구현할 수 있다.아래 그림은 클라이언트 요청에서 화면 출력까지 과정을 나타낸다.
데이터 전송객체(DTO : Data Transfer Object)
라고 한다.DBMS 밴더는 자신들의 DBMS에 접속할 수 있는 API를 만들어 배포한다. 즉 DMBS를 사용하기 위해서는 밴더가 제공하는 API에 맞게 개발해야한다. 문제는 밴더들 별로, API가 달라 개발비용 및 유지보수에 많은 비용이 들어간다.
그래서 마이크로소프트에서 밴더에 종속 받지 않고 DBMS에 접근 가능한 ODBC를 만들어 배포했다. 대부분의 DBMS API는 ODBC에 포함되어 있다. 이 라이브어리를 ODBC 드라이버
라고 명칭한다.
주요특징은 다음과 같다.
주요특징은 다음과 같다.
주요특징은 다음과 같다.
주요특징은 다음과 같다.
JDBC프로그래밍의 첫번째 작업은 DriverManager
를 이용하여 java.sql.Driver 인터페이스 구현체를 등록하는 것이다. 방법은 두가지가 있다.
DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //DriverManager를 직접이용
Class.forName(this.getInitParameter("QName")); //클래스로딩
//QName을 서블릿 초기화 매개변수의 값으 가져와서 작성하는 방법도 있다.
this.getInitParameter(/*매개변수 이름 */);
다음과 같이 DriverManager
의 getConnection()
을 호출하여 MySQL 서버에 연결할 수 있다.
conn = DriverManager.getConnection(
"jdbc:mysql://localhost/studydb", //JDBC URL
"study", // DBMS 사용자 아이디
"study"); // DBMS 사용자 암호
stmt = conn.createStatement(); //java.sql.Statement 인터페이스
stmt = conn.prepareStatement( //java.sql.PrepareStatement 인터페이스
"INSERT INTO MEMBERS(EMAIL,PWD,MNAME,CRE_DATE,MOD_DATE)"
+ " VALUES (?,?,?,NOW(),NOW())");
stmt.setString(1, request.getParameter("email"));
stmt.setString(2, request.getParameter("password"));
stmt.setString(3, request.getParameter("name"));
메서드 | 설명 |
---|---|
executeQuery() | 결과가 만들어지는 SQL문을 실행할때 사용, 보통 SELECT문을 실행 |
executeUpdate() | DML과 DDL관련 SQL문을 실행할때 사용 |
execute() | SELECT, DML, DDL 명령문 모두에 사용가능 |
executeBatch() | addBatch()로 등록한 여러개의 SQL문을 한꺼번에 실행할때 사용 |
PreparedStatement
는 반복적인 질의를 하거나, 입력 매개변수가 많은 경우에 유용하다. 특히 이미지와 같은 바이너리 데이터를 저장하거나 변경할 경우는 PreparedStatement
만 가능하다.
위의 예제에서 SQL문에서 ?
문자로 표시된 것을 입력 매개변수라고 한다. 입력 항목의 값은 SQL문을 실행하기 전에 setXXX()
메서드를 호출하여 설정해야한다.
비교항목 | Statement | PreparedStatement |
---|---|---|
실행속도 | 질의 할때마다 SQL문을 컴파일한다. | SQL문을 미리 준비하여 컴파일 해둔다. 입력 매개변수 값만 추가하여 서버에 전송한다. 특히 여러번 반복하여 질의하는 경우, 실행속도가 바름 |
바이너리데이터전송 | 불가능 | 가능 |
프로그래밍 편의성 | SQL문 안에 입력 매개변수 값이 포함되어 있어서 SQL문이 복잡하고 매개변수가 여러개인 경우 코드 관리가 힘들다. | SQL문과 입력 매개변수가 분리되어 있어 코드작성이 편리하다. |
메서드 | 설명 |
---|---|
first() | 서버에서 첫번째 레코드를 가져온다. |
last() | 서버에서 마지막번째 레코드를 가져온다. |
previous() | 서버에서 이전 레코드를 가져온다. |
next() | 서버에서 다음 레코드를 가져온다. |
getXXX() | 레코드에서 특정 컬럼의 값을 꺼낸다. XXX는 칼럼의 타입이다. |
updateXXX() | 레코드에서 특정 칼럼의 값을 변경한다. |
deleteRow() | 현재 레코드를 지운다. |
위의 그림은 웹어플리케이션의 실행과정이다. 웹브라우저가 웹서버에게 요청을하고, 서버는 클라이언트가 요청한 프로그램을 찾아서 실행한다. 그리고 해당 프로그램은 작업을 수행한 후 그 결과를 웹서버에게 돌려준다. 그러면 웹서버는 그 결과를 HTTP 형식에 맞추어 웹브라우저에게 보낸다.
이대 웹서버와 프로그램 사이에 데이터를 주고받는 규칙을 CGI(Common Gateway Interface)
라고 한다. 그래서 CGI규칙에 따라서 웹서버와 데이터를 주고 받도록 작성된 프로그램을 CGI프로그램
이라한다.
CGI프로그램은 C나 C++, java와 같은 컴파일 언어와 스크립언어로 작성할 수 있다.
자바로 만든 CGI프로그램을 서블릿(Servlet)
이라고 한다. 자바 서블릿이 다른 CGI 프로그램과 다른 점은, 웹 서버와 직접 데이터를 주고 받지 않으며, 전문 프로그램에 의해 관리된다는 점이다.
서블릿의 생성과 실행, 소멸 등 생명주기를 관리하는 프로그램을 서블릿 컨테이너(Servlet Container)
라고 한다. 서블릿 컨테이너가 서블릿을 대신하여 CGI규칙에 따라 웹서버와 데이터를 주고 받는다. 더 이상 CGI규칙에 대해 알 필요가 없지만, 서블릿 컨테이너와 서블릿 사이의 규칙을 알아야한다.
서블릿 클래스는 반드시 javax.servlet.Servlet 인터페이스를 구현해야한다. 서블릿 컨테이너가 서블릿에 대해 호출할 메서드를 정의한 것이 Servlet인터페이스 이다.
서블릿 생명주기와 관련된 메소드
- init()
- service()
- destroy()
여기서 service()
는 클라이언트가 요청할 때 마다 호출되는 메서드이다. 즉 실질적으로 서비스 작업을 수행하는 메서드 이다. 이 메서드에 서블릿이 해야 할 일을 작성하면된다.
web.xml
파일을 배치기술서(Deployment Descriptor)
또는 DD파일
이라고 한다. 여기에 웹어플리케이션의 배치 정보를 담고 있다. DD파일에 등록되지 않은 서블릿은 서블릿 컨테이너가 찾을 수 없다. URL과 서블릿도 매핑한다.
*참고 페키지명+클래스명 = Fully qualified name = QName 이라한다.
웰컴 파일(Welcome Files)
이란, 디렉토리의 기본 웹페이지를 의미한다. 웰컴파일의 이름은 web.xml
의 <welcome-file-list>
태그를 사용하여 설정할 수 있다. 이 태그의 하위 태그로 <welcome-file>
이 있는데, 여기에 파일이름을 적으면 된다. 여러 개의 웰컴파일을 등록하게 되면, 디렉토리에서 웰컴 파일을 찾을 때 위에서부터 아래로 순차적으로 조회한다.
GenericServlet
은 추상 클래스로 서블릿 클래스가 필요로 하는 init()
, destroy()
, getServletConfig()
, getServletInfo()
를 미리 구현하여 상속한다. 즉 service()
메소드만 구현하면 된다.
메소드 | 설명 |
---|---|
getRemoteAddr() | 서비스를 요청한 클라이언트의 Ip주소를 반환 |
getScheme() | 클라이언트가 요청한 URI형식 Scheme을 반환 즉 url에서 ‘:’문자전에 오는 값을 반환 |
getProtocol() | 요청한 프로토콜의 이름과 버전을 반환 |
getParameterNames() | 요청정보에서 매개변수 이름만 추출하여 반환 |
getParameterValues() | 요청정보에서 매개변수 값만 추출하여 반환 |
getParameterMap() | 요청 정보에서 매개변수들을 Map객체에 담아서 반환 |
setCharacteerEncoding() | POST요청의 매개변수에 대한 문자 집합을 설정 (기본은 ISO-8859-1 ) |
ex) `res.setContentType(“text/plain;chartest=UTF-8”);
setContentType()
의 인자 형식이 올바르지 않으면 웹브라우저는 서버에서 받은 결과를 화면에 출력하는 대신 파일저장 대화창을 띄운다.
Servlet 3.0
사양부터는 애노테이션으로 서블릿 배치 정보를 설정할 수 있다. web.xml
대신 애노테이션을 이용해 배치 정보를 작성해보자
@WebServlet(
urlPatterns={"/member/update"},
initParams={
@WebInitParam(name="driver",value="com.mysql.jdbc.Driver"),
@WebInitParam(name="url",value="jdbc:mysql://localhost/studydb"),
@WebInitParam(name="username",value="study"),
@WebInitParam(name="password",value="study")
}
)
public class CalculatorServlet extends GenericServlet {
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException,
....
}
웹 프로그래밍은 기본적으로 Client/Server
방식으로 다음과 같은 형태를 갖게 된다.
[client/server 구조]
웹 어플리케이션이란 웹을 기반으로 실행되는 프로그램을 의미 한다. 따라서 웹 프로그래밍과 웹어플리케이션의 관계는 웹 프로그래밍을 통한 웹 어플리케이션의 구현
이라고 할 수 있다. 웹어플리케이션의 구조는 다음과 같다.
처리순서는
def mergeSort(x):
if len(x)<=1:
return x
m = len(x)//2
L = mergeSort(x[:m])
R = mergeSort(x[m:])
result = []
i=0
j=0
while i<len(L) and j<len(R):
if L[i]<R[j]:
result.append(L[i])
i+=1
else:
result.append(R[j])
j+=1
result +=L[i:]
result +=R[j:]
return result
def quickSort(x):
if len(x)<=1:
return x
pivot = x[len(x)//2]
less = []
more = []
equal = []
for a in x:
if a<pivot:
less.append(a)
elif a>pivot:
more.append(a)
else :
equal.append(a)
return quickSort(less)+equal+quickSort(more)
def bubbleSort(x):
length = len(x)-1
for i in range(length):
for j in range(length-i):
if x[j]>x[j+1]:
x[j], x[j+1]=x[j+1], x[j]
return x
def selectionSort(x):
length = len(x)
for i in range(length-1):
for j in range(i+1,length):
if x[i]>x[j]:
x[i],x[j]=x[j],x[i]
return x
def insertSort(x):
for i in range(1,len(x)):
j = i-1
key = x[i]
while x[j]>key and j>=0:
x[j+1] = x[j]
j=j-1
x[j+1]=key
return x
def binarySearch(arr, val):
arr = quickSort(arr)
low =0
high = len(arr)-1
while(low<=high):
mid= (low+high)//2
if arr[mid]>val:
high = mid-1
elif arr[mid]<val:
low = mid+1
else:
return True
return False
/etc/apache2/mods-available
안에 있음 a2enmod proxy
,a2enmod proxy_http
로 설정함<VirtualHost *:80>
DocumentRoot /var/www/example.com/public_html
ServerName www.example.com
# Index file and Document Root (where the public files are located)
DirectoryIndex index.html index.php
# Log file locations
LogLevel warn
ErrorLog /var/www/amazeapp.com/log/error.log
CustomLog /var/www/amazeapp.com/log/access.log combined
# 아래가 핵심이다.
ProxyRequests off
<Proxy *>
Order deny,allow # 이부분의 경우, 콤마(,) 사이에 공백 없어야 함!
Allow from all
</Proxy>
<Location /> # 내부적으로 접속 노드를 늘리고 싶다면 여기에 추가.
ProxyPass http://localhost:3000/
ProxyPassReverse http://localhost:3000/
</Location>
</VirtualHost>
끝~
https://github.com/sindresorhus/guides/blob/master/run-node-server-alongside-apache.md