이럴 때는 간단하게 숫자체크를 하는 메소드를 공통 클래스에 포함 시켜 필요할 때마다 호출하여 사용한다.
익셉션을 이용한 숫자 체크 방법
숫자를 체크하는 방식은 Double.parseDouble 또는 Integer.parseInt를 활용하여 Exception을 통해 숫자여부를 판별
public class StringNumberCheck {
public static void main(String[] args) {
String str_1 = "가나다라" ;
String str_2 = "523" ;
String str_3 = "5.7" ;
String str_4 = "-5" ;
String str_5 = "-5.9" ;
System.out.println(isNumber(str_1)) ;
System.out.println(isNumber(str_2)) ;
System.out.println(isNumber(str_3)) ;
System.out.println(isNumber(str_4)) ;
System.out.println(isNumber(str_5)) ;
}
// 익셉션에 걸린 다는 것은 잘못된 코드라는 뜻, 반대로 활용하면 숫자인지 아닌지 가려낸다.
public static boolean isNumber(String str){
boolean result = false;
try{
Double.parseDouble(str) ;
result = true ;
}catch(Exception e){}
return result ;
}
}
// 숫자 : true 아닐 경우 :false
출처: https://fruitdev.tistory.com/84 [과일가게 개발자]
Flask(웹 어플리케이션)과 Nginx(웹 서버)를 uWSGI(WSGI 인터페이스)를 이용하여 서로 연결하여 서비스를 할 수 있습니다.
WSGI(Web Server Gateway Interface)
- 웹서버와 웹 어플리케이션이 어떤 방식으로 통신하는가에 관한 인터페이스를 의미
- 웹서버와 웹어플리케이션 간의 소통을 정의해 어플리케이션과 서버가 독립적으로 운영될 수 있게 돕는다.
- WSGI 어플리케이션은 uWSGI라는 컨테이너에 담아 어플리케이션을 실행하게 되며, uWSGI가 각각의 웹서버와 소통하도록 설정하면 끝이다. Flask, django와 같은 프레임워크는 이미 WSGI 표준을 따르고 있기 때문에 바로 웹서버에 연결해 사용할 수 있다.
- WSGI는 파이썬 표준이며, 서버에서 들어온 요청에 맞춰서 파이썬 웹 어플리케이션에 미리 등록된 로직을 콜백 함수로 서버에 응답해줍니다. 여기서 WSGI 인터페이스에 맞춰서 제작된 프레임워크가 uWSGI입니다.
오래된 uwsgi를 삭제한다.
mv /usr/bin/uwsgi /usr/bin/uwsgi-old
새롭게 uwsgi를 설치해준다.
pip install uwsgi
ln -s /usr/local/bin/uwsgi /usr/bin/uwsgi
uwsgi로 해당 어플리케이션을 실행한다.
uwsgi -s /tmp/uwsgi.sock --module yourapplication --callable app --venv .venv
파라미터를 매번 입력하기 번거로우므로 다음과 같으 ini파일을 작성해 저장해 놓고 실행 할 수 있다.
[uwsgi]
chdir=/home/ubuntu/helloWorld
chmod-socket=666
callable=app
module=app
socket=/tmp/uwsgi.sock
virtualenv=/home/ubuntu/helloWorld/.venv
윗 처럼 작성한 후 다음 명령어로 실행한다.
uwsgi <filename> &
https://edykim.com/ko/post/connecting-flask-uwsgi-to-nginx/(출처)
nginx
- nginx는 기존의 apache같은 웹 서버입니다. 기존 apache 서버와 다른 점은 nginx 는비동기 이벤트 기반으로 만들어졌고, apache 서버는 동기식, 프로세스 또는 쓰레드 기반으로 만들어졌습니다. apache서버에 비해서메모리를 적게가져간다는 장점이 있습니다.
apt-get을 통해 설치
apt-get install nginx-full
/etc/nginx/sites-available/default 파일을 열어 설정을 해준다.
server {
listen 8080;
server_name helloworld.haruair.com;
location / {
try_files $uri @helloworld;
}
location @helloworld {
include uwsgi_params;
uwsgi_pass unix:/tmp/uwsgi.sock;
}
}
위 설정을 통해 nginx로 들어오는 모든 요청을 uWSGI로 보내고
또 돌려받아 nginx를 통해 클라이언트에 전달하게 된다. nginx를 재구동하면 적용된다.
/etc/init.d/nginx restart
- Python의 객체에 데이터 모델을 정의하고 이를 데이터베이스와 매핑해주는 것을 ORM(Object Relaition Model)이라고 합니다. 덕분에 코드는 특정 데이터베이스에 종속되지 않고, 기본 객체 만으로 데이터를 기술할 수 있기 때문에 조금 더 OOP 스러운 코드를 작성할 수 있습니다.
Python에서 ORM으로 많이 쓰이는 것 중 SQLAlchemy가 있는데, 이를 Flask에서 플러그인 처럼 사용하기 쉽게 만들어진 Flask-SQLALchemy가 있습니다.
패키지 설치
(venv) PS flask_blog> pip install flask_sqlalchemy
Jinja2는 파이썬에서 가장 많이 사용되는 템플릿 엔진 중 하나입니다. Django의 템플릿 시스템에서 영감을 얻었지만 템플릿 작상자에게 더 강력한 도구 세트를 제공하는 표현 언어로 확장했습니다. 또한 보안이 중요한 애플리케이션을 위해 샌드박스 실행 및 선택적 자동 이스케이프를 추가합니다.
Flask 템플릿 렌더링 방법
기본적으로 Flask는 애플리케이션 폴더 안에 위치한 templates 서브폴더에서 템플릿을 검색한다.
**for문의 구조** {% for <개별요소> in <리스트> %} <실행코드> {% endfor %} **for문의 예시** {% for body in table['tbody'] %} <tr> {% set index = body[0] %} {% for i in range(body|length) %} {% if i == 1 %} <td> <a href="{{ url_for('manager.item', id=[index]) }}"> {{ body[i] }} </a> </td> {% else %} <td> {% if body[i] == '' %} - {% else %} {{ body[i]|replace('\\n', '<br>')|safe }} {% endif %} </td> {% endif %} {% endfor %} </tr> {% endfor %}
for문의 구조
{% for <개별요소> in <리스트> %}
<실행코드>
{% endfor %}
for문의 예시
{% for body in table['tbody'] %}
<tr>
{% set index = body[0] %}
{% for i in range(body|length) %}
{% if i == 1 %}
<td>
<a href="{{ url_for('manager.item', id=[index]) }}">
{{ body[i] }}
</a>
</td>
{% else %}
<td>
{% if body[i] == '' %}
-
{% else %}
{{ body[i]|replace('\n', '<br>')|safe }}
{% endif %}
</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
include
css 나, 자바스크립트를 가져오는 header의 부분이나 상단의 navigation 부분, 하단의 footer 부분이 그러한데 일일히 모든 템플릿에 넣어 주기는 힘들다. 그래서 jinja2 에서는{% include %} 를 통해서 하나의 html 에서 다른 html 을 가져 올 수 있도록 해준다. 단순히 가져오는 것이라고 생각 할 수 있지만 내부적으로는 랜더링된 결과를 리턴한다고 한다.
include의 다른 형태
리스트의 형태로 template를 지정할 수 있다. 첫번째 HTML파일을 찾지 못하면 두번째 HTML 파일을 보여주고 두번째 파일도 없고 ignore missing 이라는 옵션이 켜져있으면 에러를 내뱉지 않는다.
{% include ['첫번째.html', '두번째.html'] %} {% include ['첫번째.html', '두번째.html'] ignore missing %}
{% include ['첫번째.html', '두번째.html'] %}
{% include ['첫번째.html', '두번째.html'] ignore missing %}
block/extends(템플릿의 상속)
flask 템플릿은 계층 구조를 지원한다. 하나의 웹사이트는 일반적으로 동일한 테마를 갖는다. 각각의 페이지는 동일한 구성요소를 갖는데 이를 매번 html 파일에 삽입하게 되면 구성요소를 변경할 때, 모든 파일에 수정사항을 반영해야 한다.
사용되는 동일한 구성요소는 base.html파일에 넣어두고, 나머지 페이지들은 이를 상속(extends) 받아서 사용하도록 하였다. 이를 통해 base.html 파일 하나를 변경함으로써 전 페이지에 변경사항을 적용할 수 있다.
응용 형태
@web.app_errorhandler(404)
def page_not_found(e):
if request.accept_mimetypes.accept_json and \
not request.accept_mimetypes.accept_html:
response = jsonify({'error': 'not found'})
response.status_code = 404
return response
return render_template('error/layout.html',
contents='error/404.html'), 404
404.html
<!-- 404 Error Text -->
<div class="text-center">
<div class="error mx-auto" data-text="404">404</div>
<p class="lead text-gray-800 mb-5">Page Not Found</p>
<p class="text-gray-500 mb-0">{{ info }}</p>
<a href="/">← Back to Home</a>
</div>
링크/정적파일
url_for()
템플릿에 직접 링크하는 것 처럼 URL을 작성하는 것은 간단한 라우팅 방법이지만 , 이는 원하지 않는 의존성을 생성하여 링크가 깨질 수 있다. 이러한 문제를 해결하기 위해 플라스크에서는 url_for() 헬퍼 함수를 제공하여 애플리케이션 URL맵에 저장된 정보를 통해 URL을 생성한다.
**기본형태** url_for('index') # '/' url_for('index', _external=True) # '<http://localhost:5000>' url_for('user', name='john', _external=True) # '<http://localhost:5000/user/john>' url_for('index', page=2) # '/?page=2' **예시** <form method="post" action="{{ url_for('buyer.new') }}"> ***정적인 파일도 url_for()을 사용해 불러 올 수 있다.** <link href="{{ url_for('static', filename='vendor/datatables/dataTables.bootstrap4.min.css') }}" rel="stylesheet">
기본형태
url_for('index') # '/'
url_for('index', _external=True) # 'http://localhost:5000'
url_for('user', name='john', _external=True) # 'http://localhost:5000/user/john'
url_for('index', page=2) # '/?page=2'
예시
<form method="post" action="{{ url_for('buyer.new') }}">
*정적인 파일도 url_for()을 사용해 불러 올 수 있다.
<link href="{{ url_for('static', filename='vendor/datatables/dataTables.bootstrap4.min.css') }}" rel="stylesheet">
물리적 매체를 통해서 데이터 비트를 전송하기 위해 요구 되는 기능들을 정의하며 케이블 연결 장치 등 전송에 필요한 두 장치 간의 실제 접촉과 같은 기계적, 전기적 특성에 대한 규칙을 정의 한다.
전송 단위 : 프레임(Frame) 프로토콜 : 이더넷, MAC, PPP 등 장비 : 브릿지 스위치
데이터 링크 계층(Layer 2)
두 개의 개방 시스템들 간의 효율적이고 신뢰성 있는 정보 전송을 할 수 있도록 하며 오류의 검출과 회복을 위한 오류 제어 기능을 수행한다. 또한, 송신측과 수신측의 속도 차이를 해결하기 위해 흐름 제어(stop-and-wait & sliding window 방식으로 처리할 수 있는 패킷의 양보다 많은 경우) 기능을 하며 프레임의 시작과 끝을 구분하기 위한 프레임의 동기화 기능을 수행한다.
전송단위 : 프레임(Frame) 프로토콜 : 이더넷, MAC, PPP 등 장비 : 브릿지, 스위치
네트워크 계층(Layer 3)
다중 네트워크 링크에서 발신자로부터 목적지까지 책임을 가진다. 이전 계층인 데이터 계층은 노드 vs 노드 전달을 감독하는 것이고 네트워크 계층은 시작점에서 목적지까지 성공적으로 전달 되도록 하는 역할을 수행한다.
전송단위 : 패킷(Packet) 프로토콜 : IP, ICMP 등 장비 : 라우터, L3 스위치
전송 계층(Layer 4)
전체 메시지를 종단 vs 종단(End-to-End, 발신지에서 목적지)간 제어와 에러를 관리한다. 패킷의 전송이 유효한지 확인하고 전송에 실패된 패킷을 다시 보내는 것과 같은 신뢰성있는 통신을 보장한다. 주소 설정, 오류 및 흐름 제어, 다중화를 수행한다.
전송단위 : 세그먼트(Segment) 프로토콜 : TCP, UDP 등 장비 : 게이트웨이, L4 스위치
세션 계층(Layer 5)
양 끝단의 응용 프로세스가 통신을 관리하기 위한 방법을 제공한다. 동시송수신(Duplex), 반이중(Half-Duplex), 전이중(Full-Duplex) 방식의 통신과 함께 체크 포인팅과 유후, 종료, 다시 시작 과정 등을 수행한다. 통신 세션을 구성하며 포트 번호를 기반으로 연결한다.
프로토콜 : NetBIOS, SSH, TLS
표현 계층(Layer 6)
응용 계층으로부터 받은 데이터를 하위 계층인 세션 계층에 보내기 전에 통신에 적당한 형태로 변환하고 세션 계층에서 받은 데이터는 응용 계층에 맞게 변환하는 역할을 수행한다. 코드 변환, 구문 검색, 데이터 압축 및 암호화 등의 기능을 담당한다.
프로토콜 : JPG, MPEG, SMB, AFP
응용 계층(Layer 7)
응용 프로세스와 직접 관계하여 일반적인 응용 서비스를 수행한다. 응용 프로세스 간의 정보 교환, 전자메일, 파일전송 등의 서비스를 제공한다.
프로토콜 : DNS, FTP, HTTP
HTTPS 프로토콜이란?
웹 브라우저와 웹서버 간에 메세지 교환 프로토콜. 즉, 일종의 대화 규칙이며, 교환 방식은 복잡한 바이너리 데이터가 아닌 단순 텍스트를 통해 이루어진다.
HTTP의 취약점(보안문제)을 보완하기 위해 주고받는 모든 메시지를 SSL 프로토콜로 암호화하며, 암호화 방식에 쓰이는 Key의 종류로는 크게 대칭과 비대칭 둘로 나뉘게 된다.
대표적인 웹 보안 취약점
1. 인젝션(Injection)
SQL 인젝션, OS 인젝션 등의 취약점은 신뢰할 수 없는 데이터가 서버로 전달되는 명령어의 일부로서 보내질 때 발생할 수 있다. 공격자의 악의적인 데이터는 예상하지 못하는 결과를 초래할 수 있다. 예를 들어 데이터베이스에서 회원 정보를 전부 가져오도록 인젝션을 날릴 수도 있다.
위의 만화에 대해 설명하자면, 저 학교에서 입력한 명령은 다음과 같을 것이다.
INSERT INTO students (이름) VALUES ('학생 이름');
여기서 "Robert'); DROP TABLE students;--"학생을 "학생 이름" 자리에 넣을 경우 다음과 같은 명령문이 된다.
INSERT INTO students (이름) VALUES ('Robert');DROP TABLE students;--');
첫 번째 줄에서는 Robert라는 학생이 입력되었지만, 두 번째 줄에서 학생들의 데이터가 있는 테이블을 제거한다. 그리고 세 번째에서는 뒤에 오는 내용을 모두 주석 처리한다. 결과적으로 ‘모든 학생 기록을 삭제한다.’라는 뜻의 명령문이 완성된다.
인젝션 공격 같은 경우는 공격 난이도가 낮은 데 반해서 공격 피해가 심각하다는 점에서 굉장히 중요하다.
2. 인증 및 세션관리 취약점
인증이나 세션 관리가 제대로 되어 있지 않은 웹 애플리케이션의 경우 공격자에게 취약한 세션 값을 제공하여 다른 사람의 권한을 얻도록 할 수 있다. 예를 들어 인증 관리에서 실수를 하여 쿠키 값을 변조했더니 다른 사람의 아이디로 로그인이 되거나 하는 경우가 실제로도 비일비재한다. 다른 사용자의 권한을 얻을 수 있다는 점에서 개인 정보 등의 측면에서 굉장히 위협적인 공격이 될 수 있다.
다음의 사례가 대표적인 취약점 사례이다.
사용자 인증 정보가 저장될 때 해시 혹은 암호화를 사용하여 보호되지 않을 때
세션 ID가 성공적인 로그인 이후에 교체되지 않을 때
아이디, 비밀번호, 세션 ID 등이 암호화되지 않은 연결을 통해서 전송될 때
세션 ID가 URL에 노출될 때
예를 들어 URL에 자신의 세션 ID가 그대로 노출되어 있는 상황이지만 클라이언트는 이를 인지하지 못하고 친구에게 해당 URL 정보를 보낼 수 있습니다. 이 때 친구는 URL을 확인하고 해당 세션으로 로그인을 할 수도 있는 것이다.
공격의 난이도는 평균적인 수준이지만 영향도는 인젝션(Injection) 공격과 마찬가지로 심각한 수준에 이른다.
3. 크로스 사이트 스크립팅(XSS)
XSS 공격은 웹 사이트에서 서버와 통신하는 부분에서 스크립트 문장을 심어서 공격을 하는 해킹 유형이다. 대표적으로 게시판의 게시글을 작성했을 때 서버 단에서 사용자가 입력한 게시글의 정보를 제대로 필터링 하지 않거나 아예 필터링을 하지 않는 경우 다양한 특수 문자를 포함한 스크립트 문장을 심어서 서버로 전송할 수 있다. 이러한 방법을 악용하여 다양한 공격이 가능하다.
기존의 웹브라우저는 전자 문서를 염두에 두고 고안된 시스템이기 때문에 내용이 바뀌면 페이지 새로고침을 해서 내용을 새롭게 변경해야 되는 정적인 시스템이였다.
그러다 Ajax 개념이 도입되면서 모든 것이 바뀌었다. Ajax는 웹브라우저와 웹서버가 내부적으로 데이터 통신을 하게 된다. 그리고 변경된 결과를 웹페이지에 프로그래밍적으로 반영함으로써 웹페이지의 로딩 없이 서비스를 사용할 수 있게 한다.
Ajax는 Asynchronous JavaScript and XML의 약자다. 한국어로는 비동기적 자바스크립트와 XML 정도로 직역할 수 있는데 자바스크립트를 이용해서 비동기적으로 서버와 브라우저가 데이터를 주고 받는 방식을 의미한다. 이 때 사용하는 API가 XMLHttpRequest이다. 그렇다고 꼭 XML을 사용해서 통신해야 하는 것은 아니다. 사실 XML 보다는 JSON을 더 많이 사용한다.
HTTP 프로토콜이란?
인터넷상에서 데이터를 주고 받기 위한 서버/클라이언트 모델을 따르는 프로토콜(상호 간에 정의한 규칙)이다.
데이터를 주고 받기 위한 각각의 데이터 요청이 서로 독립적으로 관리가 된다. 즉 이전 데이터 요청과 다음 데이터 요청이 서로 관련이 없다.
이러한 특징 덕택에 서버는 세션과 같은 별도의 추가 정보를 관리하지 않아도 되고, 다수의 요청 처리 및 서버의 부하를 줄일 수 있는 성능 상의 이점이 생긴다.
HTTP 프로토콜은 일반적으로 TCP/IP 통신 위에서 동작하며 기본 포트는 80번이다.
HTTP 접근 제어(CORS)란?
CORS는 무엇인가?
다른 도메인으로부터 요청될 경우, 일반적인 HTTP 요청이 아닌 cross-origin HTTP 요청으로 처리하게 된다.
브라우저는 보안상의 이유로 cross-origin HTTP 요청을 제한하게 된다.
이유는 단순히 same-origin 정책이다.
이러한 불편함으로 인해, 시간이 지나 W3C에서 대안으로 CORS 메커니즘을 내놓은 것이다.
CORS는 어떻게 동작되는 건가?
CORS는 라이브러리 혹은 구현 기술이 아닌 방침이라고 보면된다.
CORS는 브라우저의 정보를 읽을 수 있도록 서버에게 알려주도록 허용하는 HTTP 헤더를 추가함으로써 동작한다.
RESTful 설계란?
REST가 무엇인가?
REST는 분산 시스템 설계를 위한 아키텍처 스타일이다.
아키텍처 스타일이라는건 쉽게 말하면 제약 조건의 집합이라고 보면 된다.
REST는 URI를 통해 자원을 표시하고, HTTP METHO를 이용하여 해당 자원의 행위를 정해주며 그 결과를 받는 것을 말한다.
RESTful은 무엇인가?
RESTful은 위의 제약 조건의 집합(아키텍처 스타일, 아키텍처 원칙)을 모두 만족하는 것을 의미한다.
REST라는 아키텍처 스타일이 있는거고 RESTful API라는 말은 REST 아키텍처 원칙을 모두 만족하는 API라는 뜻이다.
SQL Subquery란?
쿼리 안에 있는 쿼리. Where/From/Select 절 안에 들어가는 쿼리.
서브쿼리는 하나의 쿼리문 안에 포함된 또 하나의 쿼리문으로(중첩문) 메인쿼리가 서브쿼리를 포함하는 종속적 관계
문법은 서브쿼리를 괄호로 묶어서 사용한다.
Order By절은 사용불가하며 연산자 오른쪽에 사용해야 한다.
서브쿼리의 반환값에 따른 서브쿼리
단일 행 서브쿼리 : 서브쿼리의 결과가 1행
다중 행 서브쿼리 : 서브쿼리의 결과가 여러 행
다중 컬럼 서브쿼리 : 서브쿼리의 결과가 여러 컬럼
SQL Join의 종류
두 개 이상의 테이블이나 데이터베이스를 연결하여 데이터를 검색한다.
보통 primary key 혹은 Foreign key로 두 테이블을 연결한다.
연결하려면 적어도 하나의 컬럼은 서로 공유 되고 있어야한다.
1) 이너 조인(Inner Join)
교집합. 기존 테이블과 조인한 테이블의 중복 값을 보여주는데 결과값은 교집합만 검색
Sele
ct <별칭.칼럼>, <별칭.칼럼> From <기준테이블 별칭> Inner Join <조인테이블 별칭> On <기존테이블 별칭>.<기준키> = <조인테이블 별칭>.<기준키> And <기존테이블 별칭>.<기준키> = <조인테이블 별칭>.<기준키> 예) Select A.NAME, B.AGE From EX_TABLE A Inner Join JOIN_TABLE B On A.NO_EMP = B.NO_EMP And A.NO_DEPT = B.NO_DEPT
Select <별칭.칼럼>, <별칭.칼럼> From <기준테이블 별칭>
Inner Join <조인테이블 별칭>
On <기존테이블 별칭>.<기준키> = <조인테이블 별칭>.<기준키>
And <기존테이블 별칭>.<기준키> = <조인테이블 별칭>.<기준키>
예)
Select
A.NAME, B.AGE From EX_TABLE A
Inner Join JOIN_TABLE B
On A.NO_EMP = B.NO_EMP
And A.NO_DEPT = B.NO_DEPT
2) 아우터 조인(Left/Right Outer Join)
기존 테이블 값 + 교집합
Select <별칭.칼럼>, <별칭.칼럼> From <기준테이블 별칭> Left Outer Join <조인테이블 별칭> On <기존테이블 별칭>.<기준키> = <조인테이블 별칭>.<기준키> And <기존테이블 별칭>.<기준키> = <조인테이블 별칭>.<기준키> 예) Select A.NAME, B.AGE From EX_TABLE A Left Outer Join JOIN_TABLE B On A.NO_EMP = B.NO_EMP And A.NO_DEPT = B.NO_DEPT
Select <별칭.칼럼>, <별칭.칼럼> From <기준테이블 별칭>
Left Outer Join <조인테이블 별칭>
On <기존테이블 별칭>.<기준키> = <조인테이블 별칭>.<기준키>
And <기존테이블 별칭>.<기준키> = <조인테이블 별칭>.<기준키>
예)
Select
A.NAME, B.AGE From EX_TABLE A
Left Outer Join JOIN_TABLE B
On A.NO_EMP = B.NO_EMP
And A.NO_DEPT = B.NO_DEPT
3) 풀 아우터 조인(Full Outer Join)
합집합
Select <별칭.칼럼>, <별칭.칼럼> From <기준테이블 별칭> Full Outer Join <조인테이블 별칭> On <기존테이블 별칭>.<기준키> = <조인테이블 별칭>.<기준키> And <기존테이블 별칭>.<기준키> = <조인테이블 별칭>.<기준키> 예) Select A.NAME, B.AGE From EX_TABLE A Full Outer Join JOIN_TABLE B On A.NO_EMP = B.NO_EMP And A.NO_DEPT = B.NO_DEPT
Select <별칭.칼럼>, <별칭.칼럼> From <기준테이블 별칭>
Full Outer Join <조인테이블 별칭>
On <기존테이블 별칭>.<기준키> = <조인테이블 별칭>.<기준키>
And <기존테이블 별칭>.<기준키> = <조인테이블 별칭>.<기준키>
예)
Select
A.NAME, B.AGE From EX_TABLE A
Full Outer Join JOIN_TABLE B
On A.NO_EMP = B.NO_EMP
And A.NO_DEPT = B.NO_DEPT
4) 크로스 조인(Cross Join)
모든 경우의 수(N*M)
Select <별칭.칼럼>, <별칭.칼럼> From <기준테이블 별칭> Cross Join <조인테이블 별칭> 예) Select A.NAME, B.AGE From EX_TABLE A Cross Join JOIN_TABLE B
Select <별칭.칼럼>, <별칭.칼럼> From <기준테이블 별칭>
Cross Join <조인테이블 별칭>
예)
Select
A.NAME, B.AGE From EX_TABLE A
Cross Join JOIN_TABLE B
5) 셀프 조인(Self Join)
하나의 테이블을 여러번 복사해서 조인
Select <별칭.칼럼>, <별칭.칼럼> From <테이블명 별칭1>, <테이블명 별칭2>
Select <별칭.칼럼>, <별칭.칼럼> From <테이블명 별칭1>, <테이블명 별칭2>
데이터베이스 트랜젝션이란?
데이터베이스의 상태를 바꾸는 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산들을 의미
모든 명령어의 성공 또는 실패를 한번에 처리 흔한 예로 계좌입금에서 일어날 수 있는 오류등을 생각해보면 좋다.
하나의 트랜잭션으로 관리하면 계좌에 입금하는 기능이 실패 했을 경우, 철수의 계좌에서 돈이 다시 입금되어야한다.(이를 Rollback이라고 한다.)
데이터베이스의 외래키와 무결성 제약 조건
데이터베이스의 외래키
외래키는 두 테이블을 서로 연결하는 데 사용되는 키
외래키가 포함된 테이블을 자식 테이블이라고 하고 외래키 값을 제공하는 테이블을 부모 테이블이라한다.
MySQL: CREATE TABLE Orders ( OrderID int NOT NULL, OrderNumber int NOT NULL, PersonID int, PRIMARY KEY (OrderID), FOREIGN KEY (PersonID) REFERENCES Persons(PersonID) ); SQL Server / Oracle / MS Access: CREATE TABLE Orders ( OrderID int NOT NULL PRIMARY KEY, OrderNumber int NOT NULL, PersonID int FOREIGN KEY REFERENCES Persons(PersonID) );
MySQL:
CREATE TABLE Orders (
OrderID int NOT NULL,
OrderNumber int NOT NULL,
PersonID int,
PRIMARY KEY (OrderID),
FOREIGN KEY (PersonID) REFERENCES Persons(PersonID)
);
SQL Server / Oracle / MS Access:
CREATE TABLE Orders (
OrderID int NOT NULL PRIMARY KEY,
OrderNumber int NOT NULL,
PersonID int FOREIGN KEY REFERENCES Persons(PersonID)
);
무결성의 제약조건
개체 : 테이블에 있는 모든 행들이 유일한 식별자를 가질 것을 요구한다.(같은 값 X)
참조 : 외래키 값은 NULL이거나 참조 테이블의 PK값이여야함
영역 : 한 칼럼에 대해 NULL 허용 여부와 자료형 , 규칙으로 타당한 데이터 값을 지정
HTTP 프로토콜을 이용하게 되는 웹 사이트에서는 웹 페이지에 특정 방문자가 머무르고 있는 동안에 그 방문자의 상태를 지속시키기 위해 쿠키와 세션을 이용한다.
세션
특정 웹사이트에서 사용자가 머무르는 기간 또는 한명의 사용자의 한번의 방문을 의미한다.
세션에 관련된 데이터는 서버에 저장된다.
웹 브라우저의 캐시에 저정되어 브라우저가 닫히거나 서버에서 삭제 시, 사라진다.
쿠키에 비해 보안성이 좋다.
쿠키
사용자 정보를 유지할 수 없다는 HTTP의 한계를 극복 할 수 있는 방법이다.
인터넷 웹 사이트의 방문 기록을 남겨 사용자와 웹 사이트 사이를 매개해주는 정보이다.
쿠키는 인터넷 사용자가 특정 웹서버에 접속할 때, 생성되는 개인 아이디와 비밀번호, 방문한 사이트의 정보를 담은 임시파일로써, 서버가 아닌 클라이언트에 텍스트 파일로 저장되어 다음에 해당 웹서버를 찾을 경우 웹 서버에서는 그가 누구인지 어떤 정보를 주로 찾았는지 등을 파악할 때 사용 된다.
쿠키는 클라이언트 PC에 저장되는 정보이기 때문에, 다른 사용자에 의해서 임의로 변경이 가능하다.(정보유출 가능, 세션 보다 보안성이 낮은 이유)
Get과 Post의 차이점
Get
클라이언트에서 서버로 데이터를 전달할 때, 주소 뒤에 "이름"과 "값"이 결합된 쿼리 스트링 형태로 전달한다.
주소창에 쿼리 스트링이 그대로 보여지기 때문에 보안성이 떨어진다.
길이에 제한이 있다.(전송 데이터에 한계가 있다.)
Post 방식보다 상대적으로 전송 속도가 빠르다.
Post
일정크기 이상의 데이터를 보내야 할 때 사용한다.
서버로 보내기 전에 인코딩하고, 전송 후 서버에는 다시 디코딩 작업을 한다.
주소창에 전송하는 데이터의 정보가 노출 되지 않아 Get방식에 비해 보안성이 높다.
속도가 Get방식보다 느리다.
쿼리 스트링(문자열)데이터 뿐만 아니라, 라디오 버튼, 텍스트박스 같은 객체들의 값도 전송 가능하다.
차이점
Get은 주로 웹 브라우저가 웹 서버에 데이터를 요청 할 때 사용한다.
Post는 웹 브라우저가 웹 서버에 데이터를 전달하기 위 해 사용한다.
Get을 사용하면 웹 브라어저에서 웹서버로 전달되는 데이터가 인코딩 되어 URL에 붙는다.
Post 방식은 전달되는 데이터가 보이지 않는다.
Get 방식은 전달되는 데이터가 255개의 문자를 초과하면 문제가 발생할 수 있다.
웹 서버에 많은 데이터를 전달하기 위해서는 Post방식을 사용하는 것이 바람직하다.
URL Encoding이란?
문자나 특수문자를 웹 서버와 브라우저에서 보편적으로 허용되는 형식으로 변화하는 메커니즘이다.
URL은 ASCII 문자 집합을 사용하여 인터넷을 통해서만 전송할 수 있다.
URL은 종종 ASCII 세트 외부의 문자를 포함하기 때문에 URL은 유효한 ASCII 형식으로 변환되어야 한다.
URL 인코딩은 안전하지 않은 ASCII 문자를 "%" 다음에 두 개의 16진수로 대체한다.
URL은 공백을 포함할 수 없다. URL 인코딩은 일반적으로 공백을 더하기 (+) 기호 또는 % 20으로 바꾼다.
고로, 아스키 이외의 문자는 다 인코딩 해야된다. (한글, 일본어, 중국어, 독일어, ... )
JSON(JavaScript Object Notation)의 약자로 JavaScript에서 객체를 만들 때 사용하는 표현식을 의미한다. 이 표현식은 사람도 이해하기 쉽고 기계도 이해하기 쉬우면서 데이터의 용량이 작다. 이런 이유로 최근에는 JSON이 XML을 대체해서 설정의 저장이나 데이터를 전송등에 많이 사용된다.
라이브러리란 자주 사용되는 로직들을 재활용, 유통 가능하도록 만든 로직들의 묶음을 의미합니다. 자바스크립트의 세계에는 많은 라이브러리들이 있다. prototype, jQuery, YUI 등등 구글트랜드로 검색을 해보면 현재는 jQuery가 가장 많은 사용자를 가지고 있다. jQuery를 이용하면 순수한 자바스크립트로 코딩하는 것 보다 10배 이상 생산성을 높일 수 있다. 또 jQuery는 파생된 라이브러리들을 가지고 있다. jQuery UI는 jQuery기반의 GUI 라이브러리이다. 이것을 이용해서 윈도우 에플리케이션과 같은 기능성의 UI를 만들 수 있다.
최근에는 jQuery Mobile라는 이름의 모바일 라이브러리를 출시해서 모바일용 웹에플리케이션을 만드는데도 많은 도움을 주고 있다.
CSS의 미디어쿼리란?
미디어 쿼리(mediaqueri)는 사이트에 접속하는 장치에 따라 특정한 CSS 스타일을 사용하도록 도와주는 소프트웨어 모듈이다. 미디어 쿼리를 이용한 사이트는 웹 사이트에 접속하는 기기에 따라서 레이아웃이 바뀌게 된다. 즉, PC로 접속하면 모니터 화면에 맞게, 스마트폰으로 접속하면 스마트폰 화면에 맞게 레이아웃이 변경되는 것이다. 웹 문서의 스타일을 정의할 때, 즉 CSS 코드를 작성할 때 미디어쿼리 모듈을 사용해 주는 것이 일반적인 사용 방법이다.
클래스 메소드는 클래스에서 호출되고 인스턴스 메소드가 첫번째 파라미터로 자신의 인스턴스를 self로 전달하는 것과 달리 자신의 클래스를 파라미터로 전달한다. 인스턴스 메소드에서는 인스턴스에 국한하여 데이터를 사용하지만 클래스 메소드는 인스턴스가 공유하는 클래스 데이터를 사용할 수 있다.
class Language: default_language = "English" def __init__(self): self.show = '나의 언어는' + self.default_language @classmethod def class_my_language(cls): return cls() @staticmethod def static_my_language(): return Language() def print_language(self): print(self.show) class KoreanLanguage(Language): default_language = "한국어" >>> from language import * >>> a = KoreanLanguage.static_my_language() >>> b = KoreanLanguage.class_my_language() >>> a.print_language() 나의 언어는English >>> b.print_language() 나의 언어는한국어
class Language:
default_language = "English"
def __init__(self):
self.show = '나의 언어는' + self.default_language
@classmethod
def class_my_language(cls):
return cls()
@staticmethod
def static_my_language():
return Language()
def print_language(self):
print(self.show)
class KoreanLanguage(Language):
default_language = "한국어"
>>> from language import *
>>> a = KoreanLanguage.static_my_language()
>>> b = KoreanLanguage.class_my_language()
>>> a.print_language()
나의 언어는English
>>> b.print_language()
나의 언어는한국어
Docstring란?
Docstring은 코드의 문서화에 도움이 되는 문자열이다. """ 주석 내용 """ 을 사용하여 작성하며 모듈 파일 처음이나 함수, 클래스 선언 다음라인에 주로 작성한다.
return 키워드 대신 yield키워드를 사용하는 함수다. 배열이나 리스트와 같이 반복가능한 값들을 생성해내며 값을 반환할때 모든값을 반환하는 것이 아닌 한 개의 값을 반환한다.
def num_gen(): for i in range(3): yield i g = num_gen() # 제너레이터 객체 생성 num1 = next(g) num2 = next(g) num3 = next(g) print(num1, num2, num3)
def num_gen():
for i in range(3):
yield i
g = num_gen() # 제너레이터 객체 생성
num1 = next(g)
num2 = next(g)
num3 = next(g)
print(num1, num2, num3)
코루틴
제네레이터는 yield를 사용해서 값을 발생시키지만 코루틴은 제네레이터의 무한루프문 안에서 값을 전달받아 사용된다.
while True: # 코루틴을 계속 유지하기 위해 무한 루프 사용 x = (yield) # 코루틴 바깥에서 값을 받아옴, yield를 괄호로 묶어야 함 print(x) co = number_coroutine() next(co) # 코루틴 안의 yield까지 코드 실행(최초 실행) co.send(1) # 코루틴에 숫자 1을 보냄 co.send(2) # 코루틴에 숫자 2을 보냄 co.send(3) # 코루틴에 숫자 3을 보냄
while True: # 코루틴을 계속 유지하기 위해 무한 루프 사용
x = (yield) # 코루틴 바깥에서 값을 받아옴, yield를 괄호로 묶어야 함
print(x)
co = number_coroutine()
next(co) # 코루틴 안의 yield까지 코드 실행(최초 실행)
co.send(1) # 코루틴에 숫자 1을 보냄
co.send(2) # 코루틴에 숫자 2을 보냄
co.send(3) # 코루틴에 숫자 3을 보냄
—
파이썬에서의 메모리 추가/삭제 방법
파이썬은 가비지 컬렉션(Garbage Collection)이 메모리를 관리 해주기 때문에 사용자가 따로 관리할 필요가 없다. 가비지 컬렉션은 객체를 참조하는 다른 객체 또는 위치가 늘어날수록 해당 객체의 reference count는 증감하게 되고, reference count가 0이 되면 객체는 메모리에서 해제하는 식으로 메모리를 관리한다.
이것은 반환한다None(예외를 발생시키지ID가 유효하지 않은 경우).이 경우 세션에서 ID가 수동으로 제거되고 처리가 계속됩니다.
사용자 클래스
사용자를 나타내는 데 사용하는 클래스는 다음 속성 및 메서드를 구현해야합니다.
is_authenticatedTrue사용자가 인증 된 경우, 즉 유효한 자격 증명을 제공 한경우이 속성이 반환되어야합니다.인증 된 사용자 만의 기준을 충족합니다login_required.is_active이 속성은True활성 사용자 인 경우 인증되는 것 외에도 계정을 활성화했거나 일시 중지하지 않았거나 응용 프로그램이 계정을 거부 한 조건을반환해야합니다.비활성 계정은 로그인 할 수 없습니다 (물론 강제로).is_anonymousTrue익명 사용자 인 경우이속성이 반환되어야합니다.(실제 사용자는False대신돌아와야합니다.)get_id()이 메소드는unicode이 사용자를 고유하게 식별하는user_loader콜백을반환해야하며콜백에서 사용자를로드하는 데 사용할 수 있습니다.참고이이 것을해야한다일unicode- ID가 기본적 인 경우int또는 다른 유형, 당신은으로 변환해야합니다unicode.
사용자 클래스 구현을보다 쉽게하기 위해 from을 상속하면UserMixin이러한 모든 속성 및 메서드에 대한 기본 구현이 제공됩니다.(필요하지는 않습니다.)
@app.route('/login',methods=['GET','POST'])deflogin():# Here we use a class of some kind to represent and validate our# client-side form data. For example, WTForms is a library that will# handle this for us, and we use a custom LoginForm to validate.form=LoginForm()ifform.validate_on_submit():# Login and validate the user.# user should be an instance of your `User` classlogin_user(user)flask.flash('Logged in successfully.')next=flask.request.args.get('next')# is_safe_url should check if the url is safe for redirects.# See http://flask.pocoo.org/snippets/62/ for an example.ifnotis_safe_url(next):returnflask.abort(400)returnflask.redirect(nextorflask.url_for('index'))returnflask.render_template('login.html',form=form)
경고 :반드시next매개 변수값을 확인해야합니다.그렇지 않으면 응용 프로그램이 열린 리디렉션에 취약합니다.구현 예는이 Flask Snippet을is_safe_url참조하십시오.
그렇게 간단합니다.그런 다음current_user모든 템플릿에서 사용할 수있는프록시를 사용하여 로그인 한 사용자에게 액세스 할 수 있습니다.
{% if current_user.is_authenticated %} Hi {{ current_user.name }}! {% endif %}
@login_manager.unauthorized_handlerdefunauthorized():# do stuffreturna_response
인증 헤더를 사용하여 로그인
주의
이 방법은 더 이상 사용되지 않습니다.request_loader대신 아래를사용하십시오.
때로는AuthorizationAPI 요청과 같은 헤더를사용하여 기본 인증 로그인을 지원하려고합니다.헤더를 통한 로그인을 지원하려면header_loader콜백을 제공해야합니다.이 콜백은user_loader사용자 ID 대신 헤더 값을 허용한다는 점을 제외하면 콜백과 동일하게 작동해야합니다.예를 들면 다음과 같습니다.
기본적으로Authorization헤더 값은header_loader콜백으로전달됩니다.AUTH_HEADER_NAME구성에사용 된 헤더를 변경할 수 있습니다.
요청 로더를 사용한 사용자 정의 로그인
때로는 헤더 값이나 쿼리 인수로 전달 된 API 키와 같은 쿠키를 사용하지 않고 사용자를 로그인하려고합니다.이 경우request_loader콜백을사용해야합니다.이 콜백은user_loaderuser_id 대신 플라스크 요청을 수락한다는 점을 제외하면 콜백과 동일하게 작동해야합니다.
예를 들어,Authorization헤더를사용하여 URL 인수와 기본 인증 모두에서 로그인을 지원하려면다음을 수행하십시오.
@login_manager.request_loaderdefload_user_from_request(request):# first, try to login using the api_key url argapi_key=request.args.get('api_key')ifapi_key:user=User.query.filter_by(api_key=api_key).first()ifuser:returnuser# next, try to login using Basic Authapi_key=request.headers.get('Authorization')ifapi_key:api_key=api_key.replace('Basic ','',1)try:api_key=base64.b64decode(api_key)exceptTypeError:passuser=User.query.filter_by(api_key=api_key).first()ifuser:returnuser# finally, return None if both methods did not login the userreturnNone
익명 사용자에 대한 사용자 정의 요구 사항이있는 경우 (예 : 권한 필드가 필요함) 익명 사용자를 작성하는 호출 가능 (클래스 또는 팩토리 기능)을 제공 할 수 있습니다LoginManager.
login_manager.anonymous_user=MyAnonymousUser
나를 기억
기본적으로 사용자가 브라우저를 닫으면 플라스크 세션이 삭제되고 사용자가 로그 아웃됩니다."Remember Me"는 사용자가 브라우저를 닫을 때 실수로 로그 아웃되는 것을 방지합니다.이것은사용자가 로그 아웃 한 후 로그인 양식으로 사용자의 사용자 이름 또는 비밀번호를 기억하거나 미리 채우는 것을 의미하지는않습니다.
“Remember Me”기능은 구현하기 까다로울 수 있습니다.그러나, 플라스크 - 로그인은 거의 투명하게 - 그냥 통과remember=True받는login_user전화.쿠키는 사용자의 컴퓨터에 저장되며, Flask-Login은 해당 쿠키가 세션에없는 경우 해당 쿠키에서 자동으로 사용자 ID를 복원합니다.쿠키가 만료되기까지의 시간은REMEMBER_COOKIE_DURATION구성으로 설정하거나에 전달할 수 있습니다login_user.쿠키는 변조 방지 기능이므로 사용자가 쿠키를 변조 (예 : 다른 사람의 사용자 ID를 자신의 위치에 삽입)하는 경우 쿠키가 존재하지 않는 것처럼 쿠키가 거부됩니다.
이 수준의 기능은 자동으로 처리됩니다.그러나 애플리케이션이 중요한 데이터를 처리하는 경우 추가 인프라를 제공하여 기억 쿠키의 보안을 강화할 수 있습니다.
대체 토큰
사용자 토큰을 기억 토큰의 값으로 사용한다는 것은 로그인 세션을 무효화하기 위해 사용자의 ID를 변경해야한다는 것을 의미합니다.이를 개선하는 한 가지 방법은 사용자 ID 대신 다른 사용자 ID를 사용하는 것입니다.예를 들면 다음과 같습니다.
이렇게하면 사용자가 비밀번호를 변경할 때 사용자의 대체 ID를 임의로 생성 된 새 값으로 자유롭게 변경할 수 있으므로 이전 인증 세션이 유효하지 않게됩니다.대체 ID는 여전히 사용자를 고유하게 식별해야합니다. 두 번째 사용자 ID로 생각하십시오.
새로운 로그인
사용자가 로그인하면 해당 세션이 "새로 고침"으로 표시되어 실제로 해당 세션에서 인증되었음을 나타냅니다.세션이 삭제되고 "기억하기"쿠키로 다시 로그인하면 "비 신규"로 표시됩니다.login_required신선도를 구분하지 않으므로 대부분의 페이지에 적합합니다.그러나 개인 정보 변경과 같은 민감한 조치에는 새로 로그인해야합니다.(비밀번호 변경과 같은 작업은 항상 비밀번호를 다시 입력해야합니다.)
login_manager.refresh_view="accounts.reauthenticate"login_manager.needs_refresh_message=(u"To protect your account, please reauthenticate to access this page.")login_manager.needs_refresh_message_category="info"
또는 새로 고침을 처리하기 위해 고유 한 콜백을 제공하여 :
@login_manager.needs_refresh_handlerdefrefresh():# do stuffreturna_response
위의 기능은 쿠키 도둑으로부터“Remember Me”토큰을 보호하는 데 도움이되지만 세션 쿠키는 여전히 취약합니다.Flask-Login에는 세션 보호 기능이있어 사용자의 세션 도난을 방지 할 수 있습니다.
LoginManager및 앱구성에서 세션 보호를 구성 할 수 있습니다.활성화 된 경우basic또는strong모드에서 작동 할 수 있습니다.상의를 설정하려면LoginManager, 설정된session_protection속성을하는"basic"나"strong":
login_manager.session_protection="strong"
또는 비활성화하려면 :
login_manager.session_protection=None
기본적으로"basic"모드에서 활성화됩니다.그것은 설정하여 응용 프로그램의 설정에서 비활성화 할 수 있습니다SESSION_PROTECTION에 대한 설정을None,"basic"또는"strong".
세션 보호가 활성화되면 각 요청마다 사용자 컴퓨터의 식별자 (기본적으로 IP 주소 및 사용자 에이전트의 보안 해시)가 생성됩니다.세션에 연관된 식별자가 없으면 생성 된 식별자가 저장됩니다.식별자가 있고 생성 된 식별자와 일치하면 요청이 정상입니다.
식별자가basic모드에서일치하지 않거나세션이 영구적 일 경우 세션은 단순히 새로 고침되지 않은 것으로 표시되며 새로 로그인해야하는 모든 것 때문에 사용자가 다시 인증해야합니다.(물론, 유효한 경우 새 로그인을 사용하고 있어야합니다.)
strong비 영구 세션의 모드에서 식별자가 일치하지 않으면전체 세션 (및 기억 토큰이있는 경우)이 삭제됩니다.
API에 대한 세션 쿠키를 사용하지 않도록 설정
API 인증시 Flask Session 쿠키 설정을 비활성화 할 수 있습니다.이렇게하려면 요청에 설정 한 플래그에 따라 세션 저장을 건너 뛰는 사용자 정의 세션 인터페이스를 사용하십시오.예를 들면 다음과 같습니다.
fromflaskimportgfromflask.sessionsimportSecureCookieSessionInterfacefromflask_loginimportuser_loaded_from_headerclassCustomSessionInterface(SecureCookieSessionInterface):"""Prevent creating session from API requests."""defsave_session(self,*args,**kwargs):ifg.get('login_via_header'):returnreturnsuper(CustomSessionInterface,self).save_session(*args,**kwargs)app.session_interface=CustomSessionInterface()@user_loaded_from_header.connectdefuser_loaded_from_header(self,user=None):g.login_via_header=True
이렇게하면 사용자가를 사용하여 인증 할 때마다 플라스크 세션 쿠키를 설정할 수 없습니다header_loader.
현지화
기본적으로 사용자가 로그인해야 할 때 메시지를 표시하는LoginManager데 사용flash됩니다.이 메시지는 영어로되어 있습니다.당신은 현지화를 필요로하는 경우, 설정localize_callback의 속성LoginManager들이 전송되기 전에 이러한 메시지 호출 할 수있는 기능을flash예를 들어,gettext.이 함수는 메시지와 함께 호출되고flash대신반환 값이 전송됩니다.
로그인 페이지로 리디렉션하기위한 URL을 만듭니다.login_view제공되는경우URL 만 반환합니다.next_url그러나 제공되는경우next=URL로그인보기가 해당 URL로 다시 리디렉션 될 수 있도록 쿼리 문자열에 매개 변수가 추가됩니다.Flask-Login의 기본 무단 핸들러는 로그인 URL로 리디렉션 할 때이 기능을 사용합니다.사용 된 호스트 이름을 강제하려면 호스트로 설정하십시오FORCE_HOST_FOR_REDIRECTS.요청 헤더 Host 또는 X-Forwarded-For가있는 경우 외부 사이트로 리디렉션되지 않습니다.
매개 변수 :
login_view(str) – 로그인보기의 이름입니다.또는 로그인보기의 실제 URL입니다.