bookmark_borderCordova Todo List

Cordova Todo List 프로젝트

mytodolist 프로젝트 생성 및 시험

D:\cordova>
> cordova create mytodolist com.example.mytodolist MyTodoList
> cd mytodolist
> cordova platform add android
> cordova run android

NodeJS 서버

index.js

var todos = [];

클라이언트

mytodolist.js

var todos = [];

$.ajax("http://localhost:3000/todos").done(function(result) {
    console.log(result);

    todos = result;
    for (const todo of todos) {
        $(".contents ul").append(liTemplate(todo.text, todo.checked));
    }
});

$("#addButton").click(function() {
    var text = $("#inputBox").val();
    todos.push({ text: text, checked: false });
    $("#inputBox").val("");
    console.log(todos);

    $(".contents ul").append(liTemplate(text, false));
    saveTodos();
});

function liTemplate(text, checked) {    
    var li = $('<li></li>');

    alert(text);
    li.attr('value', text);
    li.append(inputTemplate(text, checked));
    li.append(text);
    li.append(buttonTemplate());

    li.click(function(event) {
        var el = $(event.target);
        var index = el.index("li");
        console.log(index);
    
        if (el.is("button")) {
            todos.splice(index, 1);
            $("li")[index].remove();
        }
        else if (el.is("input[type='checkbox']")) {
            var isChecked = el.is(":checked");
            if (isChecked) {
                $($("li")[index]).addClass("checked");
                todos[index].checked = true;
            } else {
                $($("li")[index]).removeClass("checked");
                todos[index].checked = false;
            }
        }

        saveTodos();
    });    

    return li;
}

function inputTemplate(text, checked) {
    var inputTag = $('<input type="checkbox" id="checkBox">');
    inputTag.attr('checked', checked);
    return inputTag;
}

function buttonTemplate(text) {
    var buttonTag = $('<button id="delButton">X</button>');
    return buttonTag;
}

빌드 및 시험

> npm run start

npm ERR! Missing script: "start"
==>
package.json
"scripts": {
    "start": "node index.js"
  },

Error: Cannot find module 'express'
==>
> npm install -save express

> cordova run android

플러그인 설치

날짜선택 플러그인

알림 플러그인

function onSuccess(date) {
    var text = $("#inputBox").val();
    todos.push({ text: text, checked: false, date: date });
    $("#inputBox").val("");
    console.log(todos);

    $(".contents ul").append(liTemplate(text, false, date));
    saveTodos();
}

$("#addButton").click(function() {
    datePicker.show(options, onSuccess, onError);
});

bookmark_borderCordova

Cordova

  • 오픈소스 하이브리드 앱 개발 도구
  • 웹 기술을 이용해 개발
  • 윈도우, OS X, 리눅스에서 사용 가능
  • 안드로이드, iOS, Mac OS X, 윈도우 등 멀티 플랫폼 지원
  • 플러그인을 통한 확장
  • Cordova 의 한계
    • 네이티브 앱에 비해 성능이 떨어짐
    • 플러그인 개발의 어려움

Cordova의 작동원리

Cordova 개발환경

  • NodeJS / Cordova
  • 플랫폼 별 요구사항
    • 안드로이드: JDK, 안드로이드 SDK
  • JDK 다운로드 및 설치
  • 안드로이드 스튜디오 설치
  • Cordova 설치
    • > npm install –g cordova
    • > cordova –version
  • 새 Cordova 프로젝트 생성
    • > cordova create hello com.example.hello HelloWord
    • > cd hello
  • 안드로이드 에뮬레이터 생성
    • > More Actions > Virtual Device Manager > Create virtual device > Pixcel2 > download >
    • > cordova platform add android@8.0.0
    • > cordova run android
      • Android SDK의 경로를 찾지 못하는 문제
        • ANDROID_SDK_ROOT=undefined (recommended setting)
        • > More Actions > SDK Manager > Android SDK Location 확인
        • set ANDROID_SDK_ROOT=C:\Users\user\AppData\Local\Android\Sdk
      • Gradle 을 찾지 못하는 문제
      • javac 를 찾지 못하는 문제
        • Failed to run “javac -version”, make sure that you have a JDK version 8 installed.
        • set PATH=%PATH%;C:\SDK\jdk1.8.0_321\bin;
    • Android Emulator가 띄워져 있는 상태에서 실행
    • 영구적 PATH 등록 : 설정 > 정보 > 고급 시스템 설정 > 환경 변수 > 시스템 변수 > path 에 추가
      • C:\SDK\gradle-7.2\bin
      • C:\SDK\jdk1.8.0_321\bin

코도바 플러그인 설치 및 사용

Cordova 플러그인 설치

Cordova 플러그인

  • NodeJS 의 NPM 과 같이 Cordova 의 기능을 확장
  • 웹 앱에서 OS 기능을 사용하려면 플러그인이 필요
  • OS 종속 코드와 자바스크립트 인터페이스로 이루어짐

Cordova 플러그인 설치 및 삭제

Cordova 배터리 상태 플러그인

  • 디바이스의 배터리 잔량 확인
    • batterystatus 이벤트 -> status.level
  • 디바이스의 충전상태 확인
    • batterystatus 이벤트 -> status.isPlugged
  • 디바이스의 배터리 경고 확인
    • batterylow 이벤트
    • batterycritical 이벤트
  • 플러그인 설치
    > cordova plugin add –save cordova-plugin-battery-status

index.html

    <body>
        <div>
            <span id="battery">100</span>%
        </div>
        <script src="cordova.js"></script>
        <script src="js/jquery-3.4.1.min.js"></script>
        <script src="js/index.js"></script>
    </body>

deviceready 이벤트

  • Cordova 플러그인이 모두 로드 된 후 발생
  • window.addEventListener 함수를 통해 등록
  • 플러그인은 deviceready 이벤트 발생 이후 사용하여야 함

index.js

var battery = $("#battery");

window.addEventListener('deviceready', function() {
    window.addEventListener('batterystatus', function(status) {
        battery.text(status.level);
    }, true);
}, true);
  • Virtual Device Manager > AVD 실행
  • > cordova run android

Cordova 카메라 플러그인

  • 디바이스의 카메라로 사진을 찍어 불러오기
  • 디바이스의 이미지 라이브러리에서 사진 불러오기
    • getPicture 함수
      camera.getPicture(success, error, options)
      • success : 사진을 불러오는데 성공했을 때 실행되는 콜백함수
      • error : 사진 불러오기에 실패했을 때 실행되는 콜백함수
      • options : 사진을 가져오기 위한 option 객체
쿤의 패러다임 푸코의 에피스테메

과학(물리학)에 적용

과학, 철학, 문화 등 모든분야에 적용되는 인식 체계
의식적 작용 무의식 속에서 작동 (알아채지 못함)
나름 합리적 기준으로 선택 합리적 기준 없음

  • 카메라 플러그인 설치
    > cordova plugin add –save cordova-plugin-camera
  • 설치 플러그인 확인
    > cordova plugin list
        <button id="btnTakePic">사진 찍기</button>
        <button id="btnLoadPic">사진 불러오기</button>
        <div>
            <img id="image"/>
        </div>

index.js

var battery = $("#battery");
var image = $("#image");

options = {
    quality: 80,
    correctOrientation: true
}

window.addEventListener('deviceready', function() {
    window.addEventListener('batterystatus', function(status) {
        battery.text(status.level);
    }, true);

    $("#btnTakePic").click(load(1));
    $("#btnLoadPic").click(load(2));
}, true);

function load(sourceNum) {
    return function() {
        navigator.camera.getPicture(
            function(imageUri) {
                image.attr('src', imageUri);
            },
            function(error) {
                alert('에러발생!');
            },
            {
                sourceType: sourceNum,
                ...options,
            }
        );
    }
}

펼침연산자

            {
                sourceType: sourceNum,
                ...options,
            }
아래와 동일
            {
                sourceType: sourceNum,
                quality: 80,
                correctOrientation: true
            }
  • 배열이나 객체를 피연산자로 받음
  • 피연산자로 전달된 배열이나 객체를 펼침
  • 다른 배열이나 객체에 값을 복사해 추가할 경우 사용
var arr = [1, 2, 3];
console.log([...arr, 4, 5]);

var obj = { a:0, b:2 }
console.log({...obj, c:5});

bookmark_border동시통역 채팅 프로그램 만들기

네이버 파파고 번역 API

Papago NMT API

네이버 API 이용신청

Request 모듈

  • NodeJS 앱에서 HTTP 요청 기능
    • Jquery 의 .ajax 함수와 비슷
  • my_littlechat> npm install –save request
# request 사용법

var request = require("request");

request.get('/books', function(error, response, body) {
    
});

request.post('/books', { body: { key: value } }, function(error, response, body) {
    
});

request.put('/books', { body: { key: value } }, function(error, response, body) {
    
});

request.delete('/books', function(error, response, body) {
    
});
app.post('/send', function(req, res) {
    var message = {
        sender: req.body.sender,
        ko: req.body.ko,
        en: req.body.en
    };
    console.log(message);

    messages.push(message);
    res.status(200).send({ message: "Success" });
});

서버 구현

app.post('/send', function(req, res) {
    var message = {
        sender: req.body.sender,
        ko: req.body.ko,
        en: req.body.en
    };
    console.log(message);

    var options = {
        url: "https://openapi.naver.com/v1/papago/n2mt",
        form: {
            source: message.ko.length == 0 ? "en" : "ko",
            target: message.ko.length == 0 ? "ko" : "en",
            text: message.ko.length == 0 ? message.en : message.ko
        },
        headers: {
            "X-Naver-Client-Id": "ID",
            "X-Naver-Client-Secret": "KEY",
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
        }
    };

    request.post(options, function(error, response) {
        var result = JSON.parse(response.body).message.result;
        message.ko = message.ko.length == 0 ? result.translatedText : message.ko;
        message.en = message.en.length == 0 ? result.translatedText : message.en;

        console.log(message);
        messages.push(message);
        res.status(200).send({ message: "Success" });
    });    
});

app.get("/receive", function(req, res) {
    var result = { total: messages.length, messages: [] };

    if (messages.length > req.query.from) {
        result.messages = messages.slice(req.query.from);
    }

    res.status(200).send(result);
});

클라이언트 구현

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>my little chat</title>
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
      .messages {
        width: 500px;
        height: 500px;
        overflow: scroll;
        background: #eeeeee;
      }
    </style>
  </head>
  <body>
    <div class="messages" id="messages"></div>
    <div>
      <select id="selectBox">
        <option value="ko">한국어</option>
        <option value="en">영어</option>
      </select>
      아이디: <input type="text" id="senderId" />
      내용: <input type="text" id="chatInput" />
      <button id="sendButton">전송</button>
    </div>
    <script src="./chat.js"></script>
  </body>
</html>
var curIndex = 0;
var language = "ko";
var messages = [];

setInterval(function() {
    $.ajax(`http://localhost:3000/receive?from=${curIndex}`).done(function(data) {
        for (const message of data.messages) {
            console.log(message);

            $("#messages").append(
                message.sender + " : " + (language == "ko" ? message.ko : message.en)
            );
            $("#messages").append("<br/>")
        }

        curIndex = data.total;
    });
}, 1000);

$("#sendButton").click(function() {
    var message = {
        ko: "",
        en: "",
        sender: $("#senderId").val()
    }

    if (language == "ko") message.ko = $("#chatInput").val();
    else message.en = $("#chatInput").val();

    console.log(message);

    $.ajax({
        url: "http://localhost:3000/send",
        method: "POST",
        data: JSON.stringify(message),
        dataType: "json",
        contentType: "application/json"
    }).done(function() {
        console.log("POST done");
        $("#chatInput").val("");
    });
});

$("#selectBox").change(function() {
    language = $("#selectBox").val();
    console.log(language);
    $("messages").html("");
    curIndex = 0;
});

bookmark_bordernodeJS Todo list 프로그램

NodeJS Todo list

  • todo list 웹 페이지를 NodeJS 서버를 통해 호스팅
  • todo list 저장 및 불러오기 API 구현

Todo list API

# index.js

var express = require('express');
var app = express();

//var todos = {};
var todos = { "자바스크립트 공부하기": true };

app.use(express.json());
app.use(express.static("public"));

app.post("/todos", function(req, res) {
    todos = req.body.todos;
    console.log(req.body);
    res.status(200).send({ message: "success" });
});

app.get("/todos", function(req, res) {
    res.status(200).send(todos);
})

app.listen(3000, function() {
    console.log("3000 포트로 웹서버 실행!");
});
  • http://localhost:3000/todos
    • 응답 : { “자바스크립트 공부하기”: true }
  • app.use(express.static(“public”));
    • 웹 시작 디렉토리 : D:\…\my_todolist\public
    • 여기에 클라이언트 html, css, js 파일 위치
  • 메서도 체인(Method Chaining)
    • res.status(200).send({ message: “success” });
    • 함수를 연속해서 호출
    • 각 함수들이 자신을 리턴해서 가능 ( return this; )

Todo 클라이언트

  • 저장함수
function saveTodos() {
    $.ajax({
        url: "http://localhost:3000/todos",
        method: "POST",
        data: JSON.stringify({ todos: todos }),
        dataType: "json",
        contentType: "application/json"
    }).done(function() {
        console.log("POST done");
    })
}
  • 체크박스 정보 추가
function inputTemplate(text, checked) {
    var inputTag = $('<input type="checkbox" id="checkBox">');
    inputTag.data('value', text);
    inputTag.attr('checked', checked);
    return inputTag;
}
  • 추가버튼, 체크박스, 삭제버튼 클릭시 저장함수 saveTodos(); 호출
  • 시작시 서버에 저장된 메모정보 로드
$.ajax("http://localhost:3000/todos").done(function(result) {
    console.log(result);

    todos = result;
    for (const todo of Object.keys(todos)) {
        $(".contents ul").append(liTemplate(todo, todos[todo]));
    }
});

bookmark_borderRESTful API

RESTful API

  • REST 란?
  • Representational State Transfer 의 약자
  • api 에 대한 상세 스펙을 보지 않아도 HTTP요청의 여러 정보를 통해 API가 하는 일을 알 수 있도록 설계된 api
  • REST API가 표현하는 것
    • 자원과 자원에 대한 행위
    • 자원 : 서버에 저장되어 있는 데이터들
      • 쇼핑몰 서비스에서의 자원 : 상품 목록,주문 목록,회원 목록 등
      • 도서관리 서비스에서의 자원 : 도서 자체
  • REST API를 통해 사용하려는 자원을 HTTP uri 로 명시
  • HTTP메서드로 자원에 대한 행위를 명시

CRUD

  • Create : 생성(POST)
  • Read : 조회(GET)
  • Update : 수정(PUT)
  • Delete : 삭제(DELETE)

REST API 작성 규칙

  • 자원은 URI에 영문 소문자, 명사 복수형으로 표현
  • 파일 확장자는 URI에 포함하지 않음
  • 자원의 계층구조는 /(슬래쉬)로 표현

RESTAPI 예시

CRUD HTTP 메서드 URI
책들의 목록을 표시 GET /books
책 한권의 정보를 표시 GET /books/{id}
새 책을 생성 POST /books
책을 수정 PUT /books/{id}
책을 삭제 DELETE /books/{id}

RESTful API를 사용하는 이유

  • HTTP프로토콜 상에서 동작
  • 특정 언어나 플랫폼에 종속되지 않음
  • API 의 의도를 API사용자가 쉽게 파악할 수 있음

Express.js로 RESTful API 만들기

  • Express로 HTTP 메서드 처리
  • Express로 URI 처리
  • Express로 HTTP 바디 처리

Express Router

  • 미들웨어의 한 종류
  • HTTP 메서드, uri 에 따라 미들웨어 실행 여부 결정
  • Router 생성
    • express.Router()로 Express Router 생성
  • 생성한 라우터는 다른 미들웨어와 마찬가지로 app.use 를 통해 등록할 수 있음
  • Express Router를 사용하면 Express앱의 모듈화가 가능
# router.js

var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next) {
    res.send('GET /');
});

router.post('/', function(req, res, next) {
    res.send('POST /');
});

router.put('/', function(req, res, next) {
    res.send('PUT /');
});

router.delete('/', function(req, res, next) {
    res.send('DELETE /');
});

module.exports = router;
# index.js

var express = require('express');
var app = express();
var router = require('./router.js')

app.use(router);

app.listen(3000, function() {
    console.log("3000 포트로 웹서버 실행!");
});
  • Insomnia 설치
    • 서버에 GET, POST, PUT, DELETE 등을 전달할 수 있는 유틸리티

Express Route Parameter

  • RESTApi 에서 자원의 아이디를 uri 를 통해 전달
  • 아이디와 같이 Uri의 변하는 요소를 Route prameter 라고 함
  • Express Router 에서는 :(콜론)과 파라미터 이름으로 Route parameter를 설정
  • Request 객체의 params 프로퍼티로 Route parameter에 접근
router.get('/:id', function(req, res, next) {
    res.send('전달받은 파라미터 : ' + req.params.id);
});
  • GET localhost:3000 -> 응답 : Cannot GET/
  • GET localhost:3000/13244 -> 응답 : 전달받은 파라미터 : 13244

Query String

  • URI 를 통해 값을 전달하는 또 하나의 방법
  • RESTAPI 에서는 주로 자원을 검색, 필터링 할 때 사용
  • ex) /books?author=김군오&language=kr

Express에서 Query String 사용

  • Request 객체의 query 프로퍼티로 접근
  • Route parameter 와 다르게 어떤 query string을 받을지 미리 설정하지 않음
  • 라우트에 영향을 주지 않음
  • 쿼리스트링의 유무와 관계없이 http 메서드와 uri 를 통해서만 라우트가 결정
  • 전달하지 않은 query string에 접근하면 값이 설정되어 있지 않음
    • undefined 변수로 취급
router.delete('/', function(req, res, next) {
    res.send('Year : ' + req.query.year);
});
  • DELETE localhost:3000 -> 응답 : Year : undefined
  • DELETE localhost:3000/?year=2021 -> 응답 : Year : 2021

HTTP Body

• POST, PUT 메서드는 HTTP 요청에 Body 전달 가능
• Body에는 text, json, xml, html, 파일 등 어느 것이라도 전송될 수 있음
• Body는 Content-type 헤더에 따라 적절히 해석되어야 함

# index.js
app.use(express.json());

# router.js
router.post('/', function(req, res, next) {
    res.send('제목 : ' + req.body.title);
});

# insomnia test json
{
	"title" : "도서의 제목입니다."
}
  • POST localhost:3000 -> 응답 : 도서의 제목입니다.

bookmark_bordernpm과 express 모듈

NPM으로 모듈 설치

NPM

  • NodeJS 모듈을 공유하고 다운받는 저장소
  • CLI (명령줄 인터페이스)로 간편하게 모듈 관리
  • 의존성 관리
    • A 모듈이 B 모듈을 사용할 때 A모듈은 B모듈에 의존성이 있다고 말함
    • package.json 파일로 프로젝트 의존성 관리

npm init 명령어

  • NodeJS 프로젝트를 시작하기 위한 명령어
  • package.json 파일을 생성
  • 프로젝트의 이름, 버전, 개발자 정보 등의 메타데이터
  • NPM모듈의 의존성 정보 등을 담고 있음
  • 새로운 폴더 생성 및 실행
    • my_module_test>npm init
  • package.json
{
  "name": "my_module_test",
  "version": "1.0.0",
  "description": "나의 모듈 시험",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "author": "",
  "license": "ISC"
}
  • 엔트리 포인트 : “main”: “index.js”,
  • “scripts”: {
    “start”: “node index.js”
    },
    => npm run start 명령으로 실행

Express.js 모듈 사용

NPM 패키지 검색

  • https://www.npmjs.com/
  • express
  • > npm install –save express
    • package.json 에 의존성 정보를 저장하려면 –save 옵션과 함께 실행
    • express에 의존성 있는 모든 모듈 설치됨

Express

  • 고성능 웹 프레임워크
  • 프로그래머가 작성한 함수를 실행해 HTTP요청에 대한 HTTP응답을 프로그래머가 원하는 대로 만들어 HTTP클라이언트에게 응답할 수 있음
  • 요청한 URL이나 HTTP메서드에 따라 원하는 함수를 실행시켜 주는 라우팅 기능
  • HTML의 내용 일부분을 변수에 저장된 값으로 치환해 동적인 HTML을 만들어 응답하는 뷰 템플릿 엔진도 가지고 있다
  • 미들웨어로 기능 확장

require 함수로 외부 모듈 이용하기

  • require 함수 모듈명을 인자로 실행
  • 파일명을 전달할 때와 마찬가지로 해당 모듈을 반환
var express = require('express');
var app = express();

app.listen(3000, function() {
    console.log("3000 포트로 웹서버 실행!");
});
  • my_module_test> npm run start
  • ctrl + C 키로 종료

미들웨어 콜백함수의 인수

  • HTTP 요청 -> 미들웨어1 -> 미들웨어2 -> 미들웨어… -> HTTP 응답
  • Request 객체
    • HTTP요청에 대한 정보가 담겨 있음
  • Response 객체
    • 브라우저에 전송할 HTTP응답을 어떻게 만들지에 대한 정보를 설정
  • next 함수
    • 이전 미들웨어에서 다음 미들웨어도 실행해야 한다고 알려주는 함수
app.use(function(req, res, next) {
    res.send('OK');
})
  • 디버깅
    • JavaScript Debug Terminal 로 실행
    • 디버그 터미널에서 my_module_test> npm run start 수행
    • break point

bookmark_borderNodeJS

NodeJS 소개

NodeJS

  • 브라우저 외부에서 실행되는 자바스크립트 엔진
  • 구글 크롬의 자바스크립트 엔진인 V8을 이용해 만들어짐
  • 기본 자바스크립트 기능 외에 운영체제 기능을 활용할 수 있는 라이브러리 제공
  • 주로 개발자 도구나 웹 서버 상에서 실행되는 프로그램을 작성할 때 많이 사용

Node 특징

  • 비동기 I/O처리
    • 시간이 많이 걸리는 Input,Output 작업을 비동기로 처리
  • 빠른 속도
    • 구글 크롬의 자바스크립트 엔진인 V8의 등장으로 자바스크립트의 속도 문제도 어느 정도 해결
  • 패키지 매니저를 통한 의존성 관리
    • NPM이라는 패키지 매니저를 제공
    • 노드 패키지 매니저는 전세계 수 많은 사람들이 자신들의 모듈을 업로드 할 수 있는 코드 저장소
  • 단일 쓰레드
    • 쓰레드란 CPU가 동시에 여러가지 일을 처리할 수 있게 해주는 기능

NPM

  • Node Package Manager
  • NodeJS로 만들어진 모듈 공유
  • 프로젝트 의존성 관리를 위한 package.json

로컬환경에 NodeJS 설치

VisualStudioCode NodeJS 디버깅

  • 중단점
  • 조건부 중단점
  • 로그지점
    • i 값 출력 : {i}

모듈 프로그래밍

  • 여러 파일에 기능을 쪼개서 개발
  • 코드 가독성이 올라가고 관리가 쉬워짐
  • module.exports 객체 이용
  • require(‘{파일명}‘) 함수로 모듈 로드
function add(a, b) {
    return a + b;
}

function sub(a, b) {
    return a - b;
}

module.exports = {
    'add' : add,
    'sub' : sub
}
var calculator = require('./0609-nodejs-module-1.js');

console.log(calculator.add(1, 2));
console.log(calculator.sub(5, 3));

bookmark_borderOpenAPI

OpenAPI

API

  • Application Programming Interface
  • 운영체제나 프로그래밍 언어 기능을 사용하기 위한 인터페이스
  • 예:
    • 다른 프로그래밍 언어에서 운영체제의 기능을 이용하려 할 경우
      • 운영체제에서 자신의 기능에 대해 접근할 수 있는 인터페이스를 공개
      • 프로그래머에게 인터페이스에 대한 자세한 스펙 또는 명세를 제공
      • 이 명세가 바로 API

OpenAPI

  • 특정 사이트의 데이터에 접근하는 API를 공개해 외부 사이트에서 자유롭게 가공하고 사용할 수 있도록 함
  • API 제공자는 API 사용료를 통해 직접적인 수익을 얻거나 사용자 유입 등을 유도할 수 있음
  • API 사용자는 직접 개발하는 것보다 훨씬 적은 비용으로 기능 개발이 가능

OpenAPI 사용 절차

OpenAPI의 종류

RESTAPI

  • 보통의 http통신 방식으로 api 를 호출하는 방식
  • 추가적인 라이브러리가 필요 없고 어느 플랫폼에서든 사용하는 언어에서 http통신만 지원한다면 api 를 사용

• 웹 JS SDK

  • Software Development Kit의 약자
  • 자바스크립트 sdk는 화면에 표시될 ui 와 상호작용 까지 포함하고 있고 더 풍부한 서비스를 제공
  • 대표적인 예 : 지도 api

네이티브 SDK

  • 안드로이드나 iOS에서 실행되는 스마트폰 앱을 위해 제공되는 방식

한동대학교 API

Query parameter

  • Http요청에서 인자를 전달하는 방식 중 하나
  • 인자에 이름을 부여하고 개수 제한이 없다는 것이 장점
  • 주소에 정보가 공개된 다는 점은 보안적으로 취약할 수 있음
  • Url 뒤 ?표시로 시작
  • http://example.com?date=20190601&param2=test

식단 정보 API

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>openapi-handong</title>
    <style>
      table,
      th,
      td {
        border: solid gray;
      }
    </style>
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
  </head>
  <body>
    <h1>오늘의 식단</h1>
    <button id="haksikBtn">학식</button>
    <button id="momsBtn">맘스</button>
    <table>
      <thead>
        <tr>
          <th>한글메뉴</th>
          <th>가격</th>
        </tr>
      </thead>
      <tbody id="tableBody"></tbody>
    </table>
    <script src="./0604-app.js"></script>
  </body>
</html>
var haksik = [];
var moms = [];

$.ajax("http://smart.handong.edu/api/service/menu")
    .done(function(result) {
        haksik = result.haksik;
        moms = result.moms;
        addItem(haksik);
    });

function addItem(menuArr) {
    for (var menu of menuArr) {
        $("#tableBody").append(`<tr><td>${menu.menu_kor}</td><td>${menu.price}</td></tr>`);
    }
}

$("#haksikBtn").click(function() {
    $("#tableBody").html("");
    addItem(haksik);
});

$("#momsBtn").click(function() {
    $("#tableBody").html("");
    addItem(moms);
});

카카오 지도

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"/>
	<title>Kakao 지도 시작하기</title>
</head>
<body>
	<div id="map" style="width:500px;height:400px;"></div>
	<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=8979d3e8b21fffebfaa7d5b095b9595f"></script>
	<script>
		var container = document.getElementById('map');
		var options = {
			center: new kakao.maps.LatLng(33.450701, 126.570667),
			level: 3
		};

		var map = new kakao.maps.Map(container, options);
	</script>
</body>
</html>

bookmark_borderAJAX

웹 서버와 브라우저 통신 방법

서버 – 클라이언트 모델

  • 네트워크를 이용하는 어플리케이션을 만들 때 사용
  • 서버: 클라이언트의 요청에 따라 파일이나 데이터를 보내주는 프로그램
  • 클라이언트: 서버에 파일이나 데이터를 요청하고 소비하는 프로그램

웹 브라우저

  • 웹 서버에 HTML파일을 요청해 다운로드하고 화면에 표시하는 프로그램
  • HTML을 분석해 화면에 그리고 이미지나 스트립트 파일 등 추가적인 리소스가 필요하면 서버에 요청한다

HTTP 프로토콜

  • 웹 서버와 웹 브라우저가 서로 통신하는 규칙
  • 요청과 응답으로 이루어짐
  • 최근에는 웹 브라우저 뿐만 아니라 컴퓨터 프로그램, 스마트폰 앱 등에서 널리 사용되고 있음

HTTP요청

  • GET : 정보를 요청하기 위해서 사용한다. (SELECT)
  • POST : 정보를 추가하기 위해서 사용한다. (INSERT)
  • PUT : 정보를 업데이트하기 위해서 사용한다. (UPDATE)
  • DELETE : 정보를 삭제하기 위해서 사용한다. (DELETE)

HTTP응답

  • 2xx: 성공
  • 3xx : 리디렉션
  • 4xx: 요청 오류
  • 5xx : 서버 오류

AJAX 기술

  • Asynchronous JavaScript And XML
  • 페이지를 로드 하지 않고 브라우저에서 서버에 요청할 수 있는 기법
  • HTML, 텍스트, JSON 등의 데이터를 주고 받음
  • 비동기 실행: 데이터를 로드 하는 동안 자바스크립트 코드를 중단하지 않고 계속 실행됨

Jquery AJAX

  • Jquery 를 이용하면 간편하게 ajax 통신을 할 수 있음
  • 형식
    • $.ajax(url, options)
    • url : 요청하려는 웹 리소스의 url
    • options : 요청에 대한 옵션
  • done, fail, always 함수를 이용하여 비동기 작업이 완료되었을 때 수행할 함수 지정
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <script>
      $.ajax('data.txt')
        .done(function(data) {
          // 성공시 실행코드
          console.log(data);
        })
        .fail(function(data) {
          // 실패시 실행코드
          console.log('에러 발생!');
        })
        .always(function(data) {
          // 항상 실행되는 코드
          console.log('ajax 호출이 완료되면 실행됩니다.');
        });

      console.log('AJAX 호출은 비동기 방식입니다.')
    </script>
  • 실행시 data.txt 파일을 찾을 수 없음.

개발용 웹 서버 (Live Server)

  • 로컬 환경 (개발용 PC)에서 손쉽게 웹 서버 실행
  • 현재 폴더 기준으로 URL을 통해 파일 접근
  • Livereload 기능 제공
    • 파일이 변경되는 것을 감지해서 코드를 수정하고 저장하는 것만으로 페이지를 “새로 고침” 해 줌
  • “AJAX 호출은 비동기 방식입니다.” 가장 먼저 호출
  • 내용을 추가하면 바로 반영됨 (Liveload 기능)

Jquery AJAX활용

사이드 메뉴 레이아웃

  • 사이드 메뉴를 표시하는 HTML 문서
  • 메뉴를 선택하면 해당 내용이 저장되어있는 다른 HTML을 요청하고 화면에 표시
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>ajax-sidemenu</title>
    <link rel="stylesheet" type="text/css" href="./0602-style.css">
  </head>
  <body>
    <nav id="sidemenu">
      <ul>
        <li>메뉴 1</li>
        <li>메뉴 2</li>
        <li>메뉴 3</li>
      </ul>
    </nav>
    <div id="content">
      보고싶은 메뉴를 선택하세요.
    </div>
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <script src="./0602-app.js"></script>
  </body>
</html>
#sidemenu, #content {
  float: left;
}

#content {
  padding: 10px 40px;
}
var menu = $('#sidemenu li');
var content = $('#content');

menu.click(function(event) {
    var url = event.target.innerText + '.html';
    $.ajax(url)
        .done(function(html) {
            content.html(html);
        });
});

$.getJSON

  • Jquery 의 getJSON 함수 이용
  • .ajax함수와 비슷하지만 데이터를 자바스크립트 객체 변환

단어장 만들기

  • 단어장은 JSON형식으로 저장되어 있음
  • $.getJSON 함수로 단어장 내용을 불러와 화면에 표시
[
    {
        "title": "capture",
        "description": "포획하다, 사로잡다, ...을 붙잡다"
    },
    {
        "title": "captivate",
        "description": "...을 매혹하다, 마음을 사로잡다, 매혹시키다"
    },
    {
        "title": "captious",
        "description": "트집 잡는, 책망하는, 헐뜯는"
    }
]
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>ajax-wordbook</title>
  </head>
  <body>
    <ul></ul>
    <h2></h2>
    <p></p>
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <script>
      var dict = $('ul');
      var title = $('h2');
      var p = $('p');

      $.getJSON('dict.json')
        .done(function(data) {
          for(var word of data) {
            var li = $('<li></li>');
            li.text(word.title);
            li.data('word', word);
            li.click(function(event) {
              var el = $(event.target);
              var word = el.data('word');
              title.text(word.title);
              p.text(word.description);
            });

            dict.append(li);
          }
        });
    </script>
  </body>
</html>

bookmark_borderjQuery Todo리스트 – 2

JSON

  • Javascript Object Notation 의 약자
  • 자바스크립트 객체를 자바스크립트 외부로 전송하기 위해 문자열 형태로 표현
  • 데이터가 간결하고 사람이 이해하기 쉬움
자바스크립트 Object JSON (Javascript Object Notion)
var object = {
  name: ‘이름’,
  age: 20,
  major: ‘GLS’,
  friends: [‘철수’, ‘영희’]
}
{
  “name”: “이름”,
  “age”: 20,
  “major”: “GLS”,
  “friends”: [“철수“,”영희”]
}
  • JSON.parse 를 이용해 JSON 을 자바스크립트 객체로 변환
  • JSON.stringify 를 이용해 자바스크립트 객체를 JSON 으로 변환
var obj = {
    a: 'JSON',
    b: 'NOSJ',
    arr: [1, 2, 'test']
}

console.log(obj);

var json = JSON.stringify(obj);
console.log(json);

var newObj = JSON.parse(json);
console.log(newObj);

결과:
{a: 'JSON', b: 'NOSJ', arr: Array(3)}
{"a":"JSON","b":"NOSJ","arr":[1,2,"test"]}
{a: 'JSON', b: 'NOSJ', arr: Array(3)}
var todos = {};

$("#addButton").click(function() {
    var text = $("#inputBox").val();
    todos[text] = false;
    $("#inputBox").val("");
    console.log(todos);
});

Data 어트리뷰트

  • HTML 엘리먼트에 데이터를 저장
  • $().data(‘key’, ‘value’) 로 값 저장
  • $().data(‘key’) 로 값 접근
    <script>
      var students = [
        { name:'김군오', id:'219xxx' },
        { name:'홍길동', id:'210xxx' }
      ];

      var ul = $('ul');
      for (let student of students) {
        var li = $('<li>' + student.name + '</li>');
        li.data('id', student.id);
        li.click(function(event) {
          var el = $(event.target);
          alert(el.data('id'));
        });

        ul.append(li);
      }
    </script>

Todo List

  • 추가 버튼을 클릭하면 할일목록 생성
  • 삭제버튼 누르면 삭제
  • 체크박스 클릭하면 취소선 처리
var todos = {};

$("#addButton").click(function() {
    var text = $("#inputBox").val();
    todos[text] = false;
    $("#inputBox").val("");
    console.log(todos);

    $(".contents ul").append(liTemplate(text));
});

function inputTemplate(text) {
    var inputTag = $('<input type="checkbox" id="checkBox">');
    inputTag.data('value', text);
    return inputTag;
}

function buttonTemplate(text) {
    var buttonTag = $('<button id="delButton">X</button>');
    buttonTag.data('value', text);
    return buttonTag;
}

function liTemplate(text) {    
    var li = $('<li></li>');

    li.attr('value', text);
    li.append(inputTemplate(text));
    li.append(text);
    li.append(buttonTemplate(text));

    li.click(function(event) {
        var el = $(event.target);
        //console.log(event);
        //console.log(el);
        console.log(el.data('value'));
    
        if (el.is("button")) {
            delete todos[text];
            $(`li[value='${text}']`).remove();
        }
        else if (el.is("input[type='checkbox']")) {
            var isChecked = el.is(":checked");
            if (isChecked) {
                $(`li[value='${text}']`).addClass("checked");
                todos[text] = true;
            } else {
                $(`li[value='${text}']`).removeClass("checked");
                todos[text] = false;
            }
        }
    });    

    return li;
}