[학.알.17.실.개.기] 6장 난수~9장 YAML

Chaejung·2022년 2월 14일
0
post-thumbnail

<이기곤, 학교에서 알려주지 않는 17가지 실무 개발 기술_문자열 인코딩부터 웹 필수 지식까지, 한빛미디어>

6장 난수

p.93 유사 난수 알고리즘은 여러 종류가 있습니다. 그러나 대부분 프로그래밍 언어와 프레임워크에서 가장 대중적인 알고리즘인 메르센 트위스터Mersenne Twister로 난수를 생성합니다.

메르센 트위스터 ?

유사난수 생성기로, 기존 생성기들의 문제점들을 피하면서 매우 질이 좋은 난수를 빠르게 생성할 수 있도록 설계되었다. (중략) 난수의 품질에도 불구하고, 메르센 트위스터는 암호학적으로 안전한 유사난수 생성기가 아니다. 즉 난수의 특성(주기, 난수 범위)을 알고 있을 때 유한한 수의 난수만으로 현재 생성기의 상태를 알아 낼 수 있으며, 그 뒤에 나올 난수를 예측해 낼 수 있다. 암호학적으로 안전한 유사난수 생성기를 얻기 위해서는 해시 함수를 사용해야 하지만 난수의 생성 속도가 낮아진다.
(출처: 위키백과)

난수 생성 속도 비교

읽고난 뒤 느낀 점

공정해 보이는 난수라는 개념이 새로웠다. 난수가 말 그대로 랜덤한 결과를 보여주지만 사용자 경험에 따라 난수를 제어한다면 뽑는 순서에 따라 확률이 높아지도록 만들 수 있는 것이다. 아쉬운 것이 있다면, 모바일 게임에서 흔히 말하는 전설 아이템(0.01%의 확률)은 앞서 말한 난수를 제어하는 기법인 셔플백으로 구현할 수 없다는 것이다.

7장 해시 함수

p.111 ~또한 상용 프로그램이나 서비스에서는 메가, 기가바이트 단위의 데이터(이미지, 동영상 등)의 무결성을 검사하기 위해 해시 함수를 사용합니다.

무결성 ?

정밀성, 정확성, 완전성, 유효성의 의미로 사용되며, 데이터 베이스의 정확성을 보장하는 문제를 의미한다. 예를 들어, 데이터 무결성(data integrity)이라 하면 데이터를 보호하고, 항상 정상인 데이터를 유지하는 것을 말하고,(중략)
(출처:[네이버 지식백과] 무결성 [integrity] (컴퓨터인터넷IT용어대사전, 2011. 1. 20., 전산용어사전편찬위원회))

p.111 SHA-256 또는 SHA-512 해시 함수를 사용하면 비밀번호와 같은 민감한 데이터를 안전하게 저장할 수 있습니다. 하지만 두 함수는 해시 값을 계산하는 비용이 매우 크므로, 해커가 무차별 대입 공격brute force attack 또는 서비스 거부 공격denial-of-service-attack(DDOS)과 같이 매우 많은 요청을 동시에 보낼 경우 쉽게 서비스 장애가 발생합니다.

무차별 대입 공격 ?

조합 가능한 모든 경우의 수를 다 대입해보는 것이다. 최적화나 효율과는 거리가 멀다. 단순한 방법으로 보이기도 하지만 사실 정확도 100%를 자랑한다. 이론적으로 모든 가능한 수를 점검해 보니 실수가 없다.
(출처: [네이버 지식백과] 브루트 포스 공격 [Brute Force Attack] (ICT 시사상식 2017, 2016.12.20))

서비스 거부 공격 ?

시스템 또는 서비스의 정상적인 운영을 방해하는 모든 행위. 빠르고 쉬우며 공격 결과를 즉시 확인이 가능하며, 반복하여 발생한다는 특징이 있다.
(출처: [네이버 지식백과] 서비스 거부 공격 (국방과학기술용어사전, 2021.05.31))

재밌을 것 같아서 만들어본 로그인 코드

해시 함수에서 비밀번호를 해시 함수 형태로 저장하는 예제와
정규 표현식에서 비밀번호 검사 예제를 보고
합치면 재밌을 것 같아서 만들어 보았다.

비밀번호 조건

  • 8글자 이상
  • 소문자, 대문자 1글자 이상 포함
  • 숫자 1글자 이상 포함
  • 특수문자(!@#$%^&*()) 1글자 이상 포함

로그인 조건

  • 비밀번호 5회 입력 오류 시 계정 삭제

코드

import hashlib
import re

# 계정을 담아둘 딕셔너리
hash_map = {}

# 비밀번호 해시 함수
def computeSHA256(str):
    hasher = hashlib.sha256()
    hasher.update((str+'my_salt').encode('utf-8'))
    return hasher.hexdigest()

# 비밀번호 검사 함수
def check_password(password):
    result = re.search(r'.{8,}',password)
    if not result:
        print("최소 8글자 이상이어야 합니다.")
        return
    result = re.search(r'[a-z]+', password)
    if not result:
        print("최소 1개 이상의 소문자가 필요합니다.")
        return
    result = re.search(r'[A-Z]+', password)
    if not result:
        print("최소 1개 이상의 대문자가 필요합니다.")
        return
    result = re.search(r'[0-9]+', password)
    if not result:
        print("최소 1개 이상의 숫자가 필요합니다.")
        return
    result = re.search(r'[@#$%^&*()+=]',password)
    if not result:
        print("최소 1개 이상의 특수 문자(@#$%^&+=)를 포함해야 합니다.")
        return
    print("비밀번호 검증에 성공했습니다.")
    return True

while True:
    # 초기 화면
    print('ID를 입력하세요: ')
    user_id = input()
    
    while True:
        # 만약 계정이 있다면
        if user_id in hash_map: 
            print('반갑습니다. {0}님!'.format(user_id))
            break
        # 만약 계정이 없다면
        print('비밀번호를 입력하세요: ')
        password = input()
        # 조건에 맞는 비밀번호인지 검사 
        if check_password(password): break

    if user_id in hash_map:
        for i in range(1, 6):
            print('비밀번호를 입력하세요: ')
            password= input()
            if hash_map[user_id] == computeSHA256(password):
                print('{0}: 비밀번호가 일치합니다.'.format(user_id))
                print('로그인 성공했습니다.')
                break
            else:
                # 비밀번호 오류 시 5회까지 반복적으로 물어보기
                print('{0}: 비밀번호가 일치하지 않습니다.'.format(user_id))
                print('비밀번호 {0}회 오류. 5회 오류 시 계정이 삭제됩니다.'.format(i))
        print('비밀번호 5회 오류로 계정이 삭제되었습니다. 다시 가입해주세요.')
        del hash_map[user_id]
    else:
        # 조건에 맞는 비밀번호라면 새롭게 비밀번호 설정 완료
        hash_map[user_id]=computeSHA256(password)
        print('{0}: 비밀번호를 설정했습니다.'.format(user_id))
    
    print(hash_map)

결과 출력 화면

8장 JSON

p.120 몽고DB와 같은 NoSQL 데이터베이스는 JSON과 거의 동일한 BSON을 공식 규격으로 사용합니다. 또한 MySQL과 같은 관계형 데이터베이스에서도 정형화되지 않은 데이터를 보관할 시 JSON을 선호합니다. 물론 관계형 데이터베이스의 장점인 인덱싱을 활용할 수 없으므로, 인덱싱, 쿼리 기능을 활용하려면 저장된 JSON 데이터를 스키마가 정의된 테이블로 옮기는 작업이 필요합니다.

데이터베이스의 종류

SQL

엑셀에 가깝다. 열과 행을 미리 정해두어야 한다.
장점은 분석하기가 빠르지만 단점은 중간에 수정하기가 힘들다는 것.
ex. MS-SQL, MySQL, 오라클

NoSQL(NotOnlySQL)

한 줄 한 줄이 딕셔너리 형태로 데이터가 들어간다.
ex. MongoDB

p.123 키 문자열을 한글로 했을 때 불편한 예를 하나 들면, JSON 데이터를 객체로 직렬화/역직렬화해주는 기능을 사용할 때 직접 키와 멤버 변수를 이어주게 코드를 작성해야 하는 번거로움이 있습니다.

직렬화/역직렬화 ?

p.128 파이썬, 자바, C#과 같은 고수준 언어high-level language에서 제공한 JSON 라이브러리는 읽어 드린 JSON 데이터를 클래스, 맵, 리스트 등의 객체로 변환해주는 기능이 있으며 이를 역직렬화deserialization라고 합니다. 반대로 클래스, 맵, 리스트 데이터를 JSON 문자열로 바꿔주는 기능은 직렬화serialization라고 합니다.

p.129 키를 검사할 때는 키 존재 여부 외 키에 대응하는 값이 올바른 형태인지도 함께 검사해야 합니다. 또한 키가 필요한지, 생략할 수 있는지, 어떤 값을 기본값으로 사용할 것인지, 제대로 설정되는지도 검사해야 합니다. 이러한 로직은 디버깅 환경에서만 동작하는 assert를 사용하여 JSON 메시지가 올바른 형태인지, 필요한 키가 모두 있는지 검사하는 게 좋습니다.

assert ?

https://wikidocs.net/21050

assert는 개발자가 프로그램을 만드는 과정에 관여한다. 원하는 조건의 변수 값을 보증받을 때까지 assert로 테스트할 수 있다.
이는 단순히 에러를 찾는 것이 아니라 값을 보증하기 위해 사용된다.
(출처: <핵심만 간단히, Hello World! 파이썬 3, https://wikidocs.net/21050)

assert {False} #AssertError 발생

p.129

# float_value가 3 이상 3.2 미만인지 검사하는 코드
assert(3<=float_value<3.2)
#str_value가 null이 아니고 문자열 길이가 0 이상인지 검사하는 코드
assert(str_value and len(str_value)>0)

읽고나서 느낀 점

JSON을 첫 프로젝트에서 외부 API를 사용할 때 참 많이 봤었는데,
그때 어려움을 겪었던 부분을 명확히 짚어줘서 흥미로웠다.
당시에는 단지 데이터가 워낙 다양함과 동시에 초보인 나의 문제라고만 생각했는데, JSON을 다룰 때 주의할 점인 '키 값'의 존재 유무, 형태 파악 이 부분을 다음부터 더욱 유심히 살펴봐야겠다는 생각이 들었다.

9장 YAML

읽고나서 느낀 점

YAML의 대부분은 JSON으로 호환이 가능하다고 하여 자세히 살펴보진 않았으나, 일단 이런 형태의 데이터도 있다는 것만 짚고 넘어가겠다.

profile
프론트엔드 기술 학습 및 공유를 활발하게 하기 위해 노력합니다.

0개의 댓글