Data Scientist 옌

매일 발전하는 IT문제해결사

국비지원교육 (22.01-22.07)/강의노트

22-06-17(금) 097일차 [React, Node.js, Python] 리액트 기초, 파일 업로드, OpenAPI 활용

옌炎 2022. 6. 24. 14:17
728x90

수업내용


1교시 (09:30-10:20)

  • 리액트란
    • babel
    • SPA create-react.app
    • react + node.js / react + spring
    • 다른 컴포넌트
  • 우리는 이제 입문하므로 react, http, express 사용하여 공부할 예정

2교시 (10:30-11:20)

  • 01_elements.html
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Document</title>
</head>
<body>

	<!-- Target Container -->
	<div id="react-container"></div>

	<!-- React Library & React DOM -->
	<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
	<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

	<script>
		const dish = React.createElement("h1", null, "구운 연어")

		ReactDOM.render(
			dish,
			document.getElementById('react-container')
		)

		console.log('dish', dish);
	</script>
</body>
</html>

  • 리액트란
    react 
    --------------------

    React
    React는 뷰를 만들기 위한 라이브러리
    ReactDOM
    UI를 실제로 브라우저에 렌더링할 때 사용하는 라이브러리
    가상 돔. 변경된 부분만 바꿈

    두 라이브러리는 모두 unpkgCDN 스크립트에서 다운로드할 수 있다.
    babel
    create-react.app

    document.createElement
    document.appendChild
    className
    SPA : Single Page Application
    request, response를 한 페이지에서 한다.
    리액트가 쓰는 기법 => 요청하면 응답 페이지가 나한테 오는 것 SPA (Single Page Application)
    AJAX가 생기면서 단일페이지 애플리케이션이 생겼다.
    사용자는 사이트를 내비게이션하지만 실제로는 같은 페이지 안에 계속 머문다.
    자바스크립트는 사용자가 애플리케이션과 상호작용하는 것에 맞춰 표시중이던 인터페이스를 없애고 새로운 사용자 인터페이스를 만든다.

3교시 (11:30-12:20)

  • photo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h3>파일 업로드</h3>	
<hr>
 <form method="POST" enctype="multipart/form-data" action="/process/photo">
<table>
<tr>
    <td><label>파일</label></td>
    <td><input type="file" name="photo"></td>
</tr>                
</table>
<input type="submit" value="업로드" name="submit">
</form>
</body>
</html>
  • express_11.js
/*

npm install express --save
npm install http --save
npm install path --save
npm install body-parser --save
npm install serve-static --save
npm install fs --save

// 파일 업로드 모듈
npm install multer --save
// 다른 사이트에도 업로드 할 수 있다.
npm install cors --save
// 마임타입 모듈
npm install mime --save 

node express_11.js

http://localhost:3000/public/photo.html

// 파일 업로드 폴더 
03_express/uploads

*/

// Express 기본 모듈 불러오기
var express = require('express')
  , http = require('http')
  , path = require('path');

// Express의 미들웨어 불러오기
var bodyParser = require('body-parser')
  , static = require('serve-static');

// 파일 처리
var fs = require('fs');  

// 파일 업로드용 미들웨어 
var multer = require('multer');

//클라이언트에서 ajax로 요청 시 CORS(다중 서버 접속) 지원
var cors = require('cors');

// mime 모듈
var mime = require('mime');

// 익스프레스 객체 생성
var app = express();

// 기본 속성 설정
app.set('port', process.env.PORT || 3000);

// body-parser 설정
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())

app.use('/public', static(path.join(__dirname, 'public')));
app.use('/uploads', static(path.join(__dirname, 'uploads')));

//클라이언트에서 ajax로 요청 시 CORS(다중 서버 접속) 지원
app.use(cors());

// multer 미들웨어 사용 : 미들웨어 사용 순서 중요 body-parser -> multer -> router
// 파일 제한 : 10개, 1G
var storage = multer.diskStorage({
    destination: function(req, file, callback){
        callback(null, 'uploads');
    },
    filename: function(req, file, callback){
        callback(null, file.originalname + Date.now());
    }
});

console.log('storage >>> : ' + storage);

var upload = multer({
    storage: storage,
    limits: {
        files: 10,
        fileSize: 1024 * 1024 * 1024
    }
});

console.log('upload >>> : ' + upload);

// 라우터 사용하여 라우팅 함수 등록
var router = express.Router();

router.route('/process/photo').post(upload.array('photo', 1), function(req, res) {
	console.log('/process/photo  호출됨');

    try {
        var files = req.files;
        console.log("files >>> : " + files);
        console.dir('#=============== 업로드된 첫번째 파일 정보#');
        console.dir(req.files[0]);
        console.dir('#===============#');
        
        // 현재의 파일 정보를 저장할 변수 선언
        var originalname = '';
            
        
        if (Array.isArray(files)){ // 배열에 들어가 있는 경우 (설정에서 1개의 파일도 배열에 넣게 했음)
            console.log("배열에 들어있는 파일 갯수: %d", files.length);
            
            for (var index=0; index < files.length; index++) {
                originalname = files[index].originalname;
                console.log("originalname >>> : ", originalname);                
            }
        }else{ 
            console.log('업로드된 파일이 배열에 들어가 있지 않습니다.');
        }
        
        console.log('현재 파일 정보 : ' + originalname );
        
        // 클라이언트에 응답 전송
        res.writeHead('200', {'Content-Type': 'text/html;charset=utf8'});
        res.write('<h1>파일 업로드 성공</h1>');
        res.write('<hr/>');
        res.write('<p>원본 파일명 : ' + originalname + ' </p>');
        res.end();
        
    }catch(err){
        console.dir(err.stack);
    }
});


app.use('/', router);

// Express 서버 시작
http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

4교시 (12:30-13:20)

  • MySQL에 대한 설명
  • https://www.mysql.com/

    1. Archives 버전 설치 
    =====================================

    https://www.mysql.com/downloads/
    MyQQL Community (GPL) Downloads 링크 클릭 
    https://dev.mysql.com/downloads/
    MySQL Community Server 링크 클릭 
    Archives 탭 선택 
    Product Version : 5.7.14 버전 선택 


    cmd, 콘솔을 관리자 버전으로 실행 

    C:\00.KOSMO\40.node\mysql-5.7.14-winx64\bin>mysqld --initialize

    C:\00.KOSMO\40.node\mysql-5.7.14-winx64\bin>mysqld --install
    Service successfully installed.

    root 비밀번호 위치 : 설치 경로\data\컴퓨터이름.err
    root@localhost:비밀번호 
    2022-06-04T08:41:13.021103Z 1 [Note] A temporary password is generated for root@localhost: iSoY7qh:hgFu

    C:\00.KOSMO\40.node\mysql-5.7.14-winx64\bin>net start mysql

    C:\00.KOSMO\40.node\mysql-5.7.14-winx64\bin>mysql -uroot -p
    Enter password: ************

    mysql> alter user 'root'@'localhost' identified by '1234';
    Query OK, 0 rows affected (0.00 sec)




    2. install 버전 설치 
    =====================================
    https://dev.mysql.com/downloads/
    MySQL Community Server 링크 클릭 

    https://dev.mysql.com/downloads/mysql/

    Windows (x86, 32 & 64bit), MySQL Installer MSI 클릭

    https://dev.mysql.com/downloads/file/?id=511553

    아래 No thanks, just start my download 클릭

5교시 (14:30-15:20)

  • MySQL 다운로드

    3. MySQL 서비스 확인
    =====================================

    MySQL 서비스 확인해 보기 
    -------------------------------
    sc query | find /i "mysql"

    서비스 등록 
    -------------------------------
    C:\00.KOSMO\40.node\mysql-5.7.14-winx64\bin>mysqld --install
    C:\00.KOSMO\40.node\mysql-5.7.14-winx64\bin>net stop mysql
    C:\00.KOSMO\40.node\mysql-5.7.14-winx64\bin>mysqld --remove


    4. MySQL 콘솔에서 사용해 보기 : root/1234
    =====================================

    C:\Program Files\MySQL\MySQL Server 8.0\bin>mysql -u root -p
    Enter password: ****

    mysql>
    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | sakila             |
    | sys                |
    | test               |
    | world              |
    +--------------------+
    7 rows in set (0.00 sec)


    mysql> use test;
    Database changed


    mysql> select database();
    +------------+
    | database() |
    +------------+
    | test       |
    +------------+
    1 row in set (0.00 sec)


    mysql> show tables;
    +----------------+
    | Tables_in_test |
    +----------------+
    | users          |
    +----------------+
    1 row in set (0.00 sec)


    mysql> explain users;
    +----------+------+------+-----+---------+-------+
    | Field    | Type | Null | Key | Default | Extra |
    +----------+------+------+-----+---------+-------+
    | id       | text | YES  |     | NULL    |       |
    | name     | text | YES  |     | NULL    |       |
    | age      | int  | YES  |     | NULL    |       |
    | password | text | YES  |     | NULL    |       |
    +----------+------+------+-----+---------+-------+
    4 rows in set (0.00 sec)

    mysql> select * from users;
    +--------+--------+------+----------+
    | id     | name   | age  | password |
    +--------+--------+------+----------+
    | test01 | 전건희 |   27 | 123456   |
    | test02 | 박건원 |   30 | 1234     |
    +--------+--------+------+----------+
    2 rows in set (0.00 sec)


    mysql> quit;
    Bye
  • API란
  인증키 필요 (RESTful 방식) 과금 여부  
Web API O 유료  
Open API O (인증이 필요 없는 것이 RSS) 무료 국가에서 정보 제공 (data.go.kr)

*RESTful 방식: URL + 인증키

6교시 (15:30-16:20)

  • 5_4_openapi_openweather.py
import requests
import json

# OpenWeatherMap 날씨 정보
# https://openweathermap.org/api
# https://home.openweathermap.org/users/sign_in
# http://bulk.openweathermap.org/sample/city.list.json.gz

# 국내 웹 API
# http://www.apistore.co.kr/api/apiList.do
# http://mashup.or.kr/business/main/main.do
# https://developers.naver.com/main
# https://developers.daum.net
# http://api.danawa.com/main/index.html
# http://developer.auction.co.kr/information.aspx?menu=sub1

# 웹 서비스 : 특정 인증키
# RESTful : 레스트풀 : 레스트 api
# http 프로토콜에서 GET 방식으로 요청하면서 인증키를 사용하는 방법
# 요청하는 문서에 대한 인증키 : 식별자 :  URI
# key=value : header 에 전송하는 방식
# application/x-www-form-urlencoded
# 보안에 아주 취약하다.

apikey = "8bd01bdf534febe4e1f977ad888ff41e";
cities = ["Seoul,KR", "Tokyo,JP", "New York,US"]
api = "http://api.openweathermap.org/data/2.5/weather?q={city}&APPID={key}"
print(api)

# 켈빈 온도를 섭씨 온도로 변환하는 함수
k2c = lambda k: k - 273.15
print(k2c)

for name in cities:
    url = api.format(city=name, key=apikey)
    r = requests.get(url)
    data = json.loads(r.text)
    print("+ 도시 =", data["name"])
    print(": 날씨 =", data["weather"][0]["description"])
    print(": 최저 기온 =", k2c(data["main"]["temp_min"]))
    print(": 최고 기온 =", k2c(data["main"]["temp_max"]))
    print(": 습도 =", data["main"]["humidity"])
    print(": 기압 =", data["main"]["pressure"])
    print(": 풍향 =", data["wind"]["deg"])
    print(": 풍속 =", data["wind"]["speed"])
    print("")

7교시 (16:30-17:20)

  • 5_5_openapi_weather.py ←오픈API 활용 가이드 꼭 확인!
import requests

# data.go.kr

# 기상청_중기예보 조회서비스 신청

# 1	중기해상예보조회	예보구역코드, 발표시각의 조회 조건으로 예보일로부터 3일에서 10일까지 해상 날씨 및 파고정보를 조회하는 기능	10000	확인
# 2	중기기온조회	예보구역코드, 발표시각의 조회 조건으로 예보일로부터 3일에서 10일까지 최저/최고기온정보를 조회하는 기능	10000	확인
# 3	중기육상예보조회	예보구역코드, 발표시각의 조회 조건으로 예보일로부터 3일에서 10일까지 육상날씨정보를 조회하는 기능	10000	확인
# 4	중기전망조회	지점번호, 발표시각의 조회조건으로 기상전망정보를 조회하는 기능	10000	확인

# 중기육상예보조회 조회해 오시오


url = 'http://apis.data.go.kr/1360000/MidFcstInfoService/getMidFcst'
serviceKey = "HnIz6BwalfA77V0iIqhOAhDik4a+LfnchDUYK7e9GFAdvBFMEdgiArlsZhflHQOYFIJEKeg+1E0jin7NC4Um8w=="
pageNo = 1
numOfRows = 10
dataType = "XML"
stnId = "108"
regId = "11B00000"
tmFc = "202206161800" # 오늘을 기준으로 24시간 이내만 조회 가능

queryparam = {  'serviceKey':serviceKey
                ,'pageNo': pageNo
                ,'numOfRows':numOfRows
                ,'dataType': dataType
                ,'StnId': stnId
                ,'regId':regId
                ,'tmFc':tmFc}

res = requests.get(url, params=queryparam)
rs=res.status_code
r=res.text
print(rs)
print(r)

8교시 (17:30-18:30)

  • 스프링 코드 버전업하기

Notes


728x90