46일차 공부 Ajax, 채팅, 모바일 웹
1 교시
** Web communication API
1. Ajax - XMLHttpRequest
=> 비동기적으로 서버의 데이터를 받아오는 기술
=> HTML5에서는 기존의 기능에 몇 가지를 추가해서 Ajax Level2라고 한다.
=> 전체 페이지를 다시 로드하지 않고 서버의 데이터를 가지고 일부분만 업데이트하기 위해서 사용
1) 사용 순서
=> XMLHttpRequest 객체를 생성
=> 생성한 객체를 이용해서 요청을 생성 - open(전송방식, url, 비동기여부)
전송방식은 'GET' 또는 'POST'
GET은 파라미터(클라이언트가 서버에게 넘겨주는 데이터)를 url 뒤에 붙여서 전송하는 방식으로 속도는 빠르지만 파라미터 길이에 제한이 있고 보안이 취약하다.
POST는 파라미터를 header에 숨겨서 전송하는 방식으로 파라미커 길이에 제한이 없고 url에 파라미터를 붙여서 전송하지 않기 때문에 GET방식보다 보안이 우수
최근에는 조금 더 명확하게 작업을 하기 위해서 PUT 과 DELETE도 추가
GET은 Read, POST는 Insert, PUT은 Update, DELETE는 Delete작업에 사용하도록 권장
URL은 데이터를 전송받을 URL
비동기 여부는 기본적으로 비동기 방식으로 동작하는데 false를 설정하면 동기식으로 동작
=> 요청을 전송 - send(data)
data 는 파리미터 - HTML5에서는 일반 데이터 이외에 FormData가 추가됨
=> 요청을 취소 - abort()
2) 요청 시 발생하는 이벤트
=> load : 응답을 받았을 때
=> loadstart, loadended, abort, error
=> progress : 응답을 받고 있는 도중 발생하는 이벤트
3) 받아온 데이터
=> 이벤트 처리 함수의 매개변수로 처리
=> 매개변수.target.responseText - XML 형식을제외한 데이터
=> 매개변수.target.responseXML
4) Form의 데이터를 전송
=> 최근에는 폼의 데이터를 전송하는 부분을 ajax로 처리하기도 한다.
대표적인 경우가 댓글 쓰기 이다.
게시판의 글쓰기는 입력을 하면 목록보기 화면으로 전환하는 경우가 많지만 댓글은 보통 그 페이지에 남아있고 댓글만 추가되서 보여지는 형태로 구현을 많이 한다.
=> 폼의 데이터를 하나로 만들기
var 변수명 = new FormData(form객체);
//폼에 있지 않은 데이터를 추가하려면
변수명.append("이름", 데이터);
//ajax 객체에 넣어서 전송
ajax객체.send(변수명): // 서버에게 전달
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>ajax 요청</h2>
<input type="button" value="텍스트파일읽기" id="ajaxbtn" />
<form id="myform">
이메일<input type="email" name="email" id="email"/><br/>
이름<input type="text" name="name" id="name"/><br/>
<input type="button" value="폼 전송 ajax" id="ajaxform"/>
</form>
<div id="disp"></div>
</body>
<script>
//body에 있는 태그들을 찾아오기
var ajaxbtn = document.getElementById("ajaxbtn");
var disp = document.getElementById("disp");
var myform = document.getElementById("myform");
var ajaxform = document.getElementById("ajaxform");
ajaxform.addEventListener('click', function(event){
// ajax요청을 생성
var formdata = new FormData(myform);
// 데이터 추가
formdata.append("age", 50);
var request = new XMLHttpRequest();
request.open('POST', 'resource/process.jsp');
request.send(formdata);
// 응답을 처리
request.addEventListener('load', function(event){
disp.innerHTML = event.target.responseText;
});
});
// 버튼을 누를 때 동작하게 하기
ajaxbtn.addEventListener("click", function(event){
// ajax 요청을 생성
var request = new XMLHttpRequest();
request.open('GET', 'resource/textfile.txt');
request.send();
// 전송이 완료되었을 때 수행할 내용
request.addEventListener('load', function(event){
// disp에 가저온 내용 출력
// json이나 xml이면 파싱을 수행
if(disp.innerHTML == ''){ // 클릭하면 보이고 다시클릭하면 숨기고(토글)
disp.innerHTML = event.target.responseText;
}else{
disp.innerHTML = '';
}
})
});
</script>
</html>
2~3 교시
5) CORS
=> 이전에는 ajax는 자신의 도메인에만 접근이 가능
=> 이전에는 외부 도메인의 ajax처리는 proxy를 만들어서 처리
=> jsonp 서비스를 구축하면 외부 도메인에서도 ajax로 직접 요청이 가능
외부 도메인에 ajax 요청을 직접하는 것을 Cross-Origin Resource Sharing이라고 한다.
=> Kakao Open API는 jsonp 서비스를 제공하기 때문에 ajax 요청을 직접하는 것이 가능하다.
2. Web Push
=> Server Sent Events(SSE) 라고도 하는데 이 기술은 서버가 클라이언트의 요청이 없는데 메시지를 전송하는 것
=> 스마트폰 애플리케이션에서는 이 기술을 APNS(Apple Push Notification Service)나 FCM(Firebase Cloud Message)
이라고 한다.
=> 클라이언트 작업
1) EventSource 객체 생성
var 변수명 = new EventSource("서버경로");
2) message 이벤트 등록
변수명.addEventListener("message", function(매개변수){
매개변수.data : 서버가 보내 준 데이터
});
3. Web Socket
=> Web에서 양방향 통신을 위한 Spec
=> http는 서버에게 클라이언트가 요청을 하고 서버가 클라이언트에게 데이터를 넘겨주면 통신이 종료된다.
계속해서 통신을 하고자 하면 계속 연겨을 요청해야 한다.
=> Web Socket은 한 번 연결을 하면 연결을 해제할 때까지 계속 연결을 유지한다.
채팅같은 서비스에는 http 통신보다는 WebSocket을 이용하는 것이 효율적이다.
=> WebSocket과 Web Push는 서버가 구현되어 있어야 사용이 가능하다.
작업순서
1) 웹 소켓 객체 생성
var 변수명 = new WebSocket("ws://서버 주소");
2) 메시지 전송
변수명.send(메세지);
3) 이벤트 처리
open(접속했을 때), close(접속을 해제할 때), message(서버에서 메시지가 온 경우)
서버에서 보내준 메세지는 message이벤트 처리 함수의 매개변수.data
변수명.addEventListener('message', function(event){
event.data: 전송된 메시지
});
192.168.0.115
4 교시
채팅의 경우는 클라이언트들을 저장할 List를 생성
open 이벤트가 발생하면 클라이언트를 list에 저장
close 이벤트가 발생하면 클라이언트를 list에서 제거
message 이벤트가 발생하면 list의 모든 클라이언트에게 메세지를 전달
** 웹 채팅 만들기
1. websocket-api.jar 파일을 WEB-INF 디텍토리의 lib 디렉토리에 복사
2. 서버 역할을 수행할 클래스를 java resource/src 디렉토리에 생성
=> 클래스 이름은 아무런 의미가 없다.
3. 웹소켓서버 클래스
package webfrontend0611;
import java.util.ArrayList;
import java.util.List;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
//주소 생성
//ws://192.168.0.200:9000/webfrontend0611/chat
@ServerEndpoint("/chat")
public class WebSocketServer {
//클라이언트 목록을 저장할 List를 생성
//Session이 클라이언트 1개
//모든 클라이언트가 공유해야 하므로 static으로 생성
private static List<Session> list = new ArrayList<>();
//open 이벤트 처리
@OnOpen
public void onOpen(Session session) {
//list에 클라이언트 추가
list.add(session);
System.out.println(list.size() + " 접속 중");
}
//접속 해제 이벤트 처리
@OnClose
public void onClose(Session session) {
//세션에서 클라이언트 제거
list.remove(session);
System.out.println(list.size() + " 접속 중");
}
//메시지가 온 경우 이벤트 처리
@OnMessage
public void onMessage(String message, Session session) {
//메시지를 list의 모든 클라이언트에게 전송
for(Session s : list) {
try {
s.getBasicRemote().sendText(message);
}catch(Exception e) {
System.out.println(e.getMessage());
}
}
}
}
chatting.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>채팅</title>
</head>
<body>
닉네임<input type="text" id="nickname" size="20"/><br/>
보내는 메세지<input type="text" id="message" size="50"/><br/>
<input type="button" value="보내기" id="sendbtn" /><br/>
받은 메세지<textarea id="disp" rows="20" cols="80"></textarea>
</body>
<script>
// DOM 객체 찾아오기
var nickname = document.getElementById("nickname");
var message = document.getElementById("message");
var sendbtn = document.getElementById("sendbtn");
var disp = document.getElementById("disp");
// 웹 소켓 객체 생성
var webSocket = new WebSocket("ws://192.168.0.115:1234/webfrontend0611/chat")
//연결되었을 때 수행할 내용
webSocket.addEventListener("open", function(event){
//채팅은 새로운 메시지를 위에 출력
//disp.value = "접속에 성공\n" + disp.value;
webSocket.send(nickname.value + "님 입장");
});
//메시지가 온 경우
webSocket.addEventListener("message", function(event){
//채팅은 새로운 메시지를 위에 출력
disp.value = event.data + "\n" + disp.value;
});
//버튼 눌렀을 때 메시지 보내기
sendbtn.addEventListener("click", function(event){
var m = nickname.value + ":" + message.value;
webSocket.send(m);
message.value = '';
});
message.addEventListener("keydown", function(event){
var e = event || window.event;
var keycode = ('which' in e)
? e.which : e.keyCode;
if(keycode == 13){
var m = nickname.value + ":" + message.value;
webSocket.send(m);
message.value = '';
}
});
</script>
</html>
5 교시
** 모바일 웹
1. 구현 방식
1) 하나의 페이지를 만들고 css를 이용해서 다르게 보이도록 만드는 방법 : 반응형 웹 디자인
2) 모바일 페이즈를 별도로 만들어서 모바일에서 접속햇을 때 모바일 페이지를 보여줌
2. 모바일 기기의 접속
=> navigator 객체의 userAgent속성을 확인하면 운영체제와 브라우저 이름이 나오게 되는데 이 때 모바일 운영체제를 확인할 수 있다.
Android는 스마트폰과 태블릿을 구분하지 않음
Apple은 iPhone과 iPad로 폰과 테블릿을 구분한다.
3. 모바일 페이지의 설정
=> viewport 메타 태그를 이용해서 설정
=> https://developer.android.com/guide/webapps/targeting에서 서 확인 가능
<meta name="viewport" content="width=device-width, user-scalable=no"/>의 형태로 많이 사용
4. 회전 이벤트
=> 기기의 방향이 바뀌면 window 객체에 orientationchange 이벤트가 발생하고 window 객체의 orientation 속성을 조사하면 기기의 방향을 알 수 있다
=> 0이면 수직, 90이면 왼쪽으로 수평, -90이면 오른쪽으로 수평
기기를 반대 방향으로 수직으로 세우게 되면 180이 리턴되어야 하는데 인식 못함
5. 터치 이벤트
=> touchstart, touchend, touchmove, touchenter, touchleave
=> touchcancel
6. 스마트폰 애플리케이션
1) Web App
=> 모바일 웹사이트를 만들어서 안드로이드의 크롬이나 iOS의 사파리를 이용해서 접속
하나의 사이트만 만들면 모두 사용이 가능
터치와 회전을 제외한 다른 센서를 사용할 수 없다.
=> 모바일 페이지를 만들고 안드로이드나 iOS 앱을 만든후 WebView를 이용해서 이 페이지를 출력하는 방법도 있다.
모든 페이지를 전부 WebView를 이용하는 것은 reject 사유
2) Native App
=> 안드로이드나 iOS의 공식 지원 언어를 이용해서 앱을 만드는 것
=> 실행속도가 가장 빠르고 기기의 모든 하드웨어를 사용할 수 있지만 운영체제 별로 앱을 별도로 만들어야 하고 지원하는 언어로만 앱을 만들 수 있다.
3) Hybrid App
=> react-native, flutter, phonegap 라이브러리 : HTML과 CSS 그리고 자바스크리브로 애플리케이션 프로젝트를 만들고 각각의 운영체제에 맞게 빌드를 해서 앱을 생성
이 방법은 센서도 어느 정도 사용할 수 있다.
업데이트가 너무 자주 일어나고 새로운 운영체제가 나오면 바로 사용할 수 없는 단점을 가지고 있다.
ionic 등도 있다.
=> Unity3D(C#) 나 Unreal(C++) 과 같은 프레임워크 이용 : 프로그램을 작성하는 방식은 위와 유사한데 이 프레임워크는 그래픽 구현에 특화가 되어 있다.
가로세로
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>모바일 이벤트</title>
</head>
<body>
<div id="disp"></div>
</body>
<script>
var disp = document.getElementById("disp");
//회전 이벤트는 window 객체의 orientationchange
window.addEventListener("orientationchange", function(event) {
switch (window.orientation) {
case -90:
case 90:
disp.innerHTML = '<h3>' + '가로' + '</h3>';
break;
default:
disp.innerHTML = '<h3>' + '세로' + '</h3>';
break;
}
});
document.addEventListener('touchstart', function(event) {
disp.innerHTML = "터치 시작";
});
</script>
</html>
** lazy loading
=> 지연 로딩
=> 객체 지향에는 지연 생성이라는 개념이 있다.
=> 처음부터 로딩하거나 생성하지 말고 필요할 때 로딩하거나 생성
=> 서버는 일반적으로 초기 구동 시간이 오래 걸리더라도 전부 로딩을 해놓는 것이 좋고
클라이언트는 처음에 필요한 것만 가지고 로딩하고 다른 자원은 필요할 때 로딩하는 것이 좋다.