·MVC는 사용자 인터페이스나 데이터 및 논리 제어를 구현하는데 널리 사용되는 소프트웨어 디자인 패턴
-M(Model): 데이터와 비즈니스 로직을 관리
-V(View): 레이아웃과 화면을 처리
-C(Controller): 명령을 모델과 뷰 부분으로 라우팅, 앱 사용자의 입력에 대한 응답으로 모델과 뷰를 업데이트
·app.js에서 '여기는 루트입니다.'화면과 로그인 화면을 작성한 부분을 따로 분리해주기
1) app.set 설정
// 화면 뷰를 저장하고 관리해줄 파일을 ./views로 지정
app.set('views', './views');
// views 폴더 안에 생성될 html코드들을 어떤 엔진으로 해석할지 결정('ejs', 그냥 html이랑 비슷)
app.set('view engine', 'ejs');
2) res.send 내에 적어놨던 html 코드를 ejs 파일로 각각 분리
-작업하던 폴더 > views > home 폴더를 생성
-home 폴더 내에 index.ejs, login.ejs 파일을 생성하여 각각 '이곳은 루트입니다.'와 로그인화면의 html 코드를 붙여넣기
3) app.js파일에서 원래 res.send로 넣어놨던 html코드는 지우고 ejs파일을 받아줄 코드 작성
app.get('/',(req, res)=>{
// ejs파일이 이 파일 내에 들어왔을 때 이동할 곳 지정
// app.set에서 views 파일은 지정해놓았으므로 views 폴더 내의 경로만 지정하면 됨
res.render('home/index');
});
app.get('/login', (req,res)=>{
res.render('home/login');
});
1) express라는 작업 폴더 생성 후 자바스크립트 파일 하나 생성(서버의 중심 파일)
"use strict"
// require를 사용하여 express 모듈 다운
const express = require('express')
// app 변수에 express를 실행시켜 넣어주기
const app = express();
// PORT 번호 설정, PORT는 배가 들어가는 항구에 여러 선착장이 있듯 서버에 존재하는 여러 개의 장소
const PORT = 3000;
// listen 명령어로 서버 띄우기(3000번 포트로 열기)
app.listen(PORT, ()=>{
console.log('서버 가동') // 서버 콘솔에는 간단하게 '서버 가동'이라는 문장 띄우며 서버 오픈
});
2) express라는 서버 프레임워크 사용
3) npm(node package manager)을 통해 express 모듈 설치
- 터미널에 'npm init' 입력 후 'Is this OK? (yes)' 나올 때까지 엔터(전부 기본값으로 설치)
- 설치 완료후 터미널에 'npm install express --save' 입력
- 설치 완료하면 작업 폴더에 node_modules폴더와 package.json(npm으로 설치한 모듈들 관리해주는 메모장), package-lock.json(모듈에 대해 더 자세히 적힌 메모장)파일이 생성됨
- 그러면 node 명령어를 통해 서버 가동 준비 완료
4) 터미널에 node 명령어는 자바스크립트 파일을 v8엔진을 사용해 코드를 해석해달라는 명령어
- 터미널에 'node app.js' 입력하면 '서버 가동'이 출력되며 서버 오픈
- 주소창에 'localhost:3000' 입력하면 열린 서버창 오픈
- 윈도우에 'Cannot Get /'은 루트 경로를 찾을 수 없다는 의미
5) 루트 만들어주기
// 위에서 작성한 코드에서 app.listen 전에 아래의 코드 삽입
// 브라우저에서 '/'루트로 요청이 들어오면
// req 변수로 요청을 받고(어떤 요청인지는 아직 해석 x)
// res 변수로 어떤 응답을 할 지 결정('여기는 루트입니다'라는 문장 보내기로 응답)
app.get('/', (req, res) => {
res.send('여기는 루트입니다.');
});
// 브라우저에서 '/login'루트로 요청이 들어오면
// req 변수로 요청을 받고(어떤 요청인지는 아직 해석 x)
// res 변수로 어떤 응답을 할 지 결정('여기는 로그인 화면입니다'라는 문장 보내기로 응답)
app.get('/login', (req, res) => {
res.send('여기는 로그인 화면입니다.');
});
<!DOCTYPE>
<html lang="ko"> //문서 기본 언어
<head>
<title>제목</title> // 문서의 제목(윈도우창 제목)
<meta charset="UTF-8"> // 문서 인코딩 정보
<meta name="author" content="저자이름"> // 문서 작성자
<meta name="description" option="설명"> // 문서 설명
<link rel="stylesheet" href="my-css-file.css"> // 문서 스타일 적용할 css파일
<style>
... // css파일 외에 직접 설정할 스타일
</style>
...
</head>
<body>
...
</body>
<script src="my-js-file.js"></script> // JS파일을 직접 설정하여 적용 또는 script내에 써서 적용
<footer>
... // 문서 맨 아래에 쓸 정보
</footer>
</html>
2. Body
// 01. <h>
<h1>메인제목</h1>
<h2>소제목</h2>
<h3>소제목의 소제목</h3>
...
<h6>제일 작은 제목</h6>
// 글씨 크기가 점점 작아짐
// 03. <span>
<span style="font-size:32px, margin:21px">문장</span>
// <h>와 <p>는 각각 제목, 단락이라는 의미가 있지만
// span은 "이게 뭐다"라는 의미는 없음, 스타일 설정으로 제목이나 그냥 문장처럼 보일 수 있게 함
// 04. <br>
//한줄 띄우기
// 05. <ul> 또는 <ol>
<ul>
<li>요소1</li>
<li>요소2</li>
<li>...</li>
<li>요소n</li>
</ul>
// ul: 순서가 없는 리스트(글머리 표시가 ○, ■ 등 일반 기호)
// ol: 순서가 있는 리스트(글머리 표시가 1,2,3 또는 a,b,c 등 순서가 있는 문자)
// 07. 하이퍼링크
<a href="하이퍼링크 할 주소" title="단어 위에 마우스 오버시 툴팁 표시">누르면 하이퍼링크 될 단어</a>
// 08. Description List
<dl>
<dt>용어, 질문 등 상위 항목</dt>
<dd>정의, 답변 등 하위 항목</dd>
</dl>
// <dd></dd>내의 내용은 들여쓰기 됨
// 09. 인용문
<blockquote cite="인용할 링크">
<p>인용문</p>
</blockquote>
// 왼쪽에 굵은 선과 함께 인용문이 한 단락으로 표시
<p>...단락...<q cite="인용할 링크">인용문</q>...단락...</p>
// 단락 내에 인용문이 삽입
<p>...단락...<a href="인용할 링크"><cite>인용문</cite></a>...단락...</p>
// 단락 내에 인용문이 Italic체로 표시, 클릭 시 하이퍼링크
// 10. 약어
<p>...단락...<abbr title="약어의 전체 의미">약어</abbr>...단락...</p>
// 약어로 표시되고 마우스 오버시 전체 의미 표시
// 11. 연락처 세부정보
<address>
<p>...단락...<a href="연락처 등 하이퍼링크">문서작성자</a>...단락...</p>
</address>
// 문서 작성자와 연결할 수 있는 링크 삽입
// 13. 컴퓨터 코드
<code></code> // 일반적인 코드 표시
<pre>< // 공백(들여쓰기) 유지
<var></var> // 변수 이름 특별하게 표시
<kbd></kbd> // 컴퓨터에 입력된 키보드(및 기타유형) 입력 표시
<samp></samp> // 컴퓨터 프로그램의 출력 표시
1) <code> 결과:
이렇게 됨
2) <pre> 결과:
이렇게 됨
3) <var> 결과:
<var> 사용 =>
ABC (조금 기울어짐)
<var> 사용 안함 => ABC ( 안기울어짐)
4) <kbd> 결과:
그냥 => Ctrl
kbd =>
Ctrl
5) <samp> 결과:
그냥 =>
Keyboard not found Press F1 to continue
samp =>
Keyboard not found Press F1 to continue
// 14. 시간 및 날짜
<time datetime="컴퓨터에게 읽힐 시간">사람이 읽는 시간(화면에 표시되는 시간</time>
·2016-01-20
·2016-01
·01-20
·19:30
·19:30:01.856
·2016-01-20 T 19:30+01:00
·2016-w04(2016년 4주차)
// 15. Body의 구성
<header></header> // 컴텐츠 소개, 제목
<nav></nav> // 다른 페이지로 이동하기 위한 함수적 네비게이션
<main></main> // 페이지의 독자적 컨텐츠, body에서 딱 한번 사용
<article></article> // 개별적으로 의미를 가지는 컨텐츠
<section></section> // 개별 컨텐츠(<article>) 그룹화
<aside></aside> // 메인 컨텐츠와 직접 연관x, 간접적으로 도움이 되는 추가 정보
<footer></footer> // 마지막 컨텐츠 그룹
<hr> // 수직선, 주제 변경시 사용
// 16. 이미지 삽입
<img src="이미지 경로" // 이미지 로드 오류시 이미지 대신 출력
alt="이미지 이름, 설명"
width="폭" height="높이"
title="이미지 이름, 설명" // 이미지 위에 마우스 오버 시 툴팁 표시
<figcaption>이미지 캡션</figcaption> //<p>와 똑같이 표시되지만 컴퓨터에게 이미지 캡션임을 알리기 위해 사용
// 17. 비디오 삽입
<video src="비디오 경로" controls> // controls는 비디오 컨트롤(재생, 일시정지, 볼륨 조절) 기능 추가
// +적절한 JS api를 이용해 기능 추가 가능
</video>
// +추가로 이용 가능한 속성
<video autoplay> // 로드 시 자동재생
<video loop> // 반복재생
<video muted> // 음소거
<video preload="auto"> // 페이지 로드 시 비디오 전체 로드
<video preload="metadata"> // 페이지 로드 시 비디오 메타데이터 로드
<video preload="none"> // 페이지 로드 시 비디오 로드x
<source src="비디오 경로1" type="비디오 타입1">
<source src="비디오 경로2" type="비디오 타입2">
// <video>안에 src 옵션없이 따로 넣어서 비디오 타입이 호환되지 않을 것을 대비
<track kind="subtitles" src="자막 파일(.vtt 형식) srclang="자막언어*(ko, en 등) label="표시할 자막 이름">
// 자막 표시
// 18. 오디오 삽입
비디오 삽입에서 <video> 대신 <audio> 넣으면 됨
// 19. iframe
<iframe src="iframe 주소" width="폭" height="높이"
"frameborder="프레임 경계" style="스타일" allowfullscreen>
</iframe>
//유튜브, 구글맵 등에서 iframe 주소를 복사해 삽입 가능
-iframe은 해킹의 위험이 존재
-> 필요할 때만 사용
-> HTTPS 사용(HTTP의 암호화된 버전)
-> sandbox 속성 사용(가능한 모든 제한을 줌)
=> 일부 기능을 허용하고 싶다면 sandbox=" " 따옴표 안에 기능 넣기
=> allow-scripts, allow-same-origin옵션은 넣으면 sanbox를 끌 수 있으므로 넣지 말기
->CSP설정(Content Security Policy)
// 20. <svg>
<svg version="1.1" baseProfile="full" width="폭" height="높이" xmlns="XML namespace">
// XMLnamespace는 svg가 처음 정의된 xml 주소
<rect width="사각형 폭" height="사각형 넓이" fill="사각형 색깔" />
<circle cx="원 중심의 x좌표" cy="원 중심의 y좌표" r="반지름" fill="원 색깔" />
</svg>
// svg로 사각형, 원 등 간단한 도형은 쉽게 코딩할 수 있지만 복잡한 도형은 코딩하기 어려움
// svg파일이 있다면
<img src="svg 파일 경로" alt="이미지 설명" height="그림 높이" width="그림 폭" />
// JS나 css로 조정 불가능, css사용하려면 svg 내용에 인라인으로 구문 추가
// svg 지원 안하는 웹사이트에 대해
<img src=".png로 바꾼 경로" alt="이미지 설명" srcset=".svg로 된 경로" />
// css의 백그라운드로 svg이지미 지정, 브라우저가 지원 안 할것을 대비해 두 개 지정
background: url(".png파일") no-repeat center;
background-image: url(".svg 파일");
background-size: contain;
// <td> 대신 <th> 쓰면 표의 글씨가 굵어지고 표의 각 행렬의 제목(header)을 표시
// <td> </td>는 빈 셀을 생성
// <td colspan="합칠 열의 개수">로 열 병합
// <td rowspan="합칠 행의 개수">로 행 병합
<table>
<colgroup>
<col style="스타일" span="적용할 열" />
</colgroup>
<caption>
표의 캡션
</caption>
<thead>
표의 첫 행(굵게 표시)
</thead>
<tbody>
일반적인 표 구성(tfoot보다 밑에 구성될 수도 있음)
</tbody>
<tfoot>
표의 마지막 행(합계 등 표시)
</tfoot>
<table>...</table> // 표 안에 표 넣기 가능
</table>
// <th scope="header 열" 또는 "header 행">으로 화면리더기가 해당 셀이 header임을 인식하게 할 수 있음
// <th id="th를 식별할 id">
// <td headers="열_header_id 행_header_id> // 윗줄에서 th에 id를 부여한 것과 연계하여 td가 어떤 th에 속해있는지 연결
-선형 회귀 모형에서 비용함수(RMSE 또는 MSE 등)을 최소화하는 회귀 계수 θ를 찾기 위한 해석적인 방법
-공식 검증
import numpy as np
import matplotlib.pyplot as plt
# 선형관계에 있는 변수 X, y 100개씩 100행 1열의 배열로 생성
X=2*np.random.rand(100,1)
y=4+3*X+np.random.randn(100,1)
plt.plot(X,y,'b.')
plt.axis([0,2,0,15])
plt.show()
X_b=np.c_[np.ones((100,1)),X] # 모든 샘플에 X0=1을 추가
# X0에 1을 추가한 독립변수 배열에 배열을 전치시킨 것을 곱하여
# 그 역행렬을 구하고
# 역행렬과 독립변수 배열을 전치시킨 배열을 곱한 뒤
# 종속변수 행렬 곱하기
theta_best=np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)
theta_best
### 결과 ###
array([[4.1140573 ],
[2.81512351]])
-엑셀을 이용해 theta_best=np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y) 계산과정 설명
1) 이해를 위해 X와 y 변수에서 각각 세개씩만 데이터 추출한 뒤 X_b, y 배열 생성
6) np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T) : 5)에서 구한 역행렬과 3)에서 전치시켰던 행렬 곱하기
-"=MMULT(행렬, 행렬)" 식 작성 후 Ctrl+Shift+Enter
7) np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y) : 마지막 y 행렬 곱하기
-"=MMULT(행렬, 행렬)" 식 작성 후 Ctrl+Shift+Enter
8) 결과
-파이썬과 비교해보면 똑같은 값이 나옴
-위와 같은 과정을 거쳐서 나온 theta_best를 이용하여 새로운 값에 대한 y값 예측하기
# 새로운 값을 예측
# 0과 2를 모델에 넣었을 때 각각의 예측값
X_new=np.array([[0],[2]])
X_new_b=np.c_[np.ones((2,1)),X_new]
y_predict=X_new_b.dot(theta_best)
y_predict
### 결과 ###
array([[4.25816196],
[9.8437471 ]])
-예측한 0과 2의 값으로 예측된 회귀직선 그려보기
# 그래프로 표시
plt.plot(X_new,y_predict,'r-')
plt.plot(X,y,'b.')
plt.axis([0,2,0,15])
plt.show()
-사이킷런에서 선형회귀
# 사이킷런에서 선형 회귀 모형
from sklearn.linear_model import LinearRegression
# 선형 회귀 모형 객체 생성
lin_reg=LinearRegression()
# X와 y를 모형에 피팅
lin_reg.fit(X,y)
# 선형회귀 모형의 절편과 회귀계수
lin_reg.intercept_, lin_reg.coef_
### 결과 ###
(array([4.25816196]), array([[2.79279257]]))
# 새로운 값(0,2)에 대한 예측
lin_reg.predict(X_new)
### 결과 ###
array([[4.25816196],
[9.8437471 ]])
-LinearRegression 클래스는 scipy.linalg,lstsq() 함수를 기반으로 함
-함수를 직접 호출하면 sklearn의 LinearRegressor()에서 구했던 절편과 회귀계수와 같은 값이 출력
# scipy.linalg.lstsq() 함수
theta_best_svd,residuals,rank,s=np.linalg.lstsq(X_b,y,rcond=1e-6)
theta_best_svd
### 결과 ###
array([[4.25816196],
[2.79279257]])
-scipy.linalg.lstsq() 함수는 다음 식을 계산함 $$\hat{\theta }=X^+y$$
-X+는 X의 유사역행렬
-유사역행렬은 특잇값 분해(SVD)라 부르는 표준 행렬 분해 기법을 사용해 계산
2. 계산 복잡도
-정규 방정식은 (n+1)*(n+1) 크기가 되는 $$X^TX$$의 역행렬 계산
-역행렬을 계산하는 계산 복잡도는 특성 수가 n배로 늘어나면 계산시간이 n^2.4에서 n^3 사이로 늘어남
-사이킷런의 LinearRegression 클래스가 사용하는 SVD 방법은 약 n^2로 특성 수가 두 배 늘어나면 계산시간은 대략 4배 늘어남
-정규방정식이나 다른 알고리즘으로 학습된 선형 회귀모델은 예측이 매우 빠름
(예측 계산 복잡도는 샘플 수와 특성 수에 선형적으로 샘플(또는 특성)이 두배 증가하면 걸리는 시간도 거의 두배 증가)