2021.04월.읽음 - 학교뿐 아니라 보통은 회사에서도 알려주지 않는듯.. 게다가 보통의 경우 내용들은 들어보고 무엇인지는 알아도 명확하게 아는 개발자는 정말 한정된 것 같습니다. 내부적인 것은 몰라도 프로그래밍하는데에는 일반적으로 문제가 덜 되는 컴퓨터 세상이 되어 그런것 아닐까 싶지만.. 좋은 내용을 쉽게 잘 풀어 설명해주시는 좋은 책입니다.
1부 소프트웨어를 지탱하는 기술
1장 문자열 인코딩
2장 다국어 처리
3장 날짜와 시간
4장 정규 표현식
5장 범용 고유 식별자
6장 난수
7장 해시 함수
2부 데이터 처리 기술
8장 JSON
9장 YAML
10장 XML
11장 프로토콜 버퍼
12장 Base64
13장 데이터 압축(zlib)
3부 웹을 지탱하는 기술
14장 HTTP
15장 RESTful API
16장 HTTPS
17장 OAuth 2.0
1부 소프트웨어를 지탱하는 기술
1장 문자열 인코딩
- 문자열 인코딩이란, 아스키 코드(ASCII), EUC-KR(CP949), 유니코드(UTF-8, UTF-16, UTF-32)
- 문자 집합(Charset) : 사용할 수 있는 문자들의 집합. 유니코드, ISO-8859, ASCII
- 문자열 인코딩 : 문자를 코드로 표현하는 방식. UTF-8, UTF-16, UTF-32
- 아스키 코드표
- EUC-KR 문자 집합 : 완성형. 한글 문자 표현 2 byte, ASCII 문자 표현 1byte. CP949는 EUC-KR를 확장하여 더 많은 문자 표현하도록 한 문자 집합.
2장 다국어 처리
- i18n이란, i18n 적용하기: gettext
- i18n : 다국어 지원을 위해 만든 국제 표준. internationalization을 줄여서 i18n으로 표시.
- Localization = l10n, Globalization = g11n
- 다양한 플랫폼과 프레임워크에 맞춘 i18n 프로그램이나 플러그인을 활용할 수 있습니다.
3장 날짜와 시간
- 타임 스탬프, 단조 시간, 실제 시간, 타임 존
- 타임 스탬프(Timestamp)는 컴퓨터가 시간을 표현하기 위해 사용하는 값.
- 타임 스탬프 값은 1970년 1월 1일 0시 0분 0초부터 1초 단위로 계속 증가.
- 단조 시간(Monotonic time)은 운영체제 또는 CPU와 같은 하드웨어에서 직접 계산하는 시간.
- 실제 시간(Real time = Wall clock) : 실제 시간도 컴퓨터가 직접 계산하지만 시간 서버로부터 주기적으로 값을 가져와서 동기화.
- 타임존 : 한국은 UTC+9시간이 기준시간.
4장 정규 표현식
- 정규 표현식(Regular Expression)은 주어진 문자열 속에서 특정 패턴을 가진 문자열을 찾을 때 사용.
- 특정 문자열 : super <'super' 문자열 찾기>
- 특정 문자 여러개 : [super] <s, u, p, e, r 모든 문자 찾기]
- 소문자 : [a-z], 대문자 : [A-Z], 대소문자 : [a-zA-Z]
- 숫자 1개 : [0-9], 대소문자+숫자 : [a-zA-Z0-9], 소문자+숫자+쉼표+길이3자 : [a-z0-9,]{3}
- 소문자 문자열 : [a-z]+
- 문자열의 시작 : ^super <super로 시작하는 문자열 찾기>
- 문자열의 끝 : man$ <man으로 끝나는 문자열 찾기>
- 정규 표현식 처리속도는 꽤 느린편이므로 특정 웹페이지나 RESTful API처럼 특정 시간 내에 응답을 해야하는 경우 등은 정규 표현식 대신 파서(Parser) 라이브러리를 사용하는게 좋음.
- 참고 : RegExr (웹기반 정규표현식 테스트)
5장 범용 고유 식별자
- UUID 구조, 버전
- 범용 고유 식별자(Universally Unique IDentifier, UUID) : 컴퓨터 시스템 내에서 고유한 객체를 식별하기 위해 사용하는 값.
- UUID 구조 : 16진수 32개와 하이픈(-) 4개. '8개-4개-4개-4개-12개' <하이픈은 생략 가능>
- 1234ABCD-1234-1234-1234-123456789ABC' = '1234ABCD123412341234123456789ABC'
- UUID 저장시에는 하이픈 제외한 16진수만 저장. 총16bytes(128bit) 사용됨.
- 많은 식별자가 필요하지 않을 때는 일부 값만 랜덤하게 생성해서 사용. 'innosoft-1234-1234-...'
- UUID 버전1 : 컴퓨터 맥 주소와 타임스탬프 값 기반 UUID 생성 <더이상 사용 안 함>
- UUID 버전2 : 규모 큰 시스템 환경 고려 자릿수 일부를 site-defined로 남겨둠. <더이상 사용 안 함>
- UUID 버전3 : 네임스페이스와 문자열을 해시 함수를 사용 UUID로 변환. MD5기반.
- UUID 버전5 : 네임스페이스와 문자열을 해시 함수를 사용 UUID로 변환. SHA-1 기반.
- UUID 버전4 : 가장 많이 사용하는 UUID 버전. 버전 표기하는 4비트 제외 나머지 122비트 모두 무작위 생성.
6장 난수
- 유사 난수, 암호학적으로 안전한 난수, 공정한 난수(셔플 백)
- 유사 난수(Pseudo random) : 난수표, 난수 알고리즘, 알고리즘 초기화에 사용할 시드(Seed)값으로 생성한 난수.
- 알고리즘 대신 열 잡음, 광전자 등 신호의 노이즈를 이용해 시드가 불필요한 HRNG(Hardware random number generator)를 사용하기도 함.
- 충분한 수(624개)의 난수 확보시 다음 난수 예측 및 시드값 역 예측 가능. 암호학적 관점에서 불안전.
- 타임스탬프 시드값 사용하면 시간에 따라 비슷한 난수가 생성될 확률 큼.
- <포켓몬스터>의 루프(loop) 또는 랜덤 어뷰즈(RNG abuse), <에픽세븐>의 특정시간 동일 아이템 얻는 문제.
- 암호학적으로 안전한 난수(Secure random) - 생성속도 느리지만 시드값 사용하지 않아 예측 불가능.
- 리눅스/유닉스는 /dev/urandom 파일 읽은 값 사용, 윈도우는 BCryptGenRandom() 함수에서 반환값 사용.
- 공정한 난수(셔플 백) : 당첨 제비 3개와 꽝 제비 7개를 넣고 적당히 섞은 후, 뽑는 순서만 난수를 적용하는 방식.
- 전체 요소가 많거나 확률이 희박한 경우 모든 경우의 수를 담기 위해 필요한 컨테이너 크기가 커지는 단점.
- 랜덤박스 : 예측할 수 없고 암호학적으로 안전한 난수 사용 필요. 유사 난수를 사용해야 한다면 선형적으로 증가하거나 감소하지 않으며 예측할 수 없는 시드 값을 사용.
- 전투 규칙 : 치명타가 발생하지 않으면 다음 공격의 치명타를 높이는 방법. 또는 셔플 백 등.
7장 해시 함수
- 해시 함수(Hash function) : 임의의 입력값을 고정된 길이의 해시 값으로 변환하는 함수.
- 입력값: 문자,숫자,바이너리 등 거의 모든 형태. 변환후 데이터 값을 해시 값(바이너리 형태)
- 비밀번호 검증, 데이터가 변하지 않았음을 보장<해시 함수가 암호화를 제공하지는 않음>
- MD5(Message-digest algorithm5): 해시 충돌 취약점 확인됨.
- SHA-1(Secure Hash Algorithm-1): 해시 충돌 취약점 확인됨.
- SHA-2(Secure Hash Algorithm-2): SHA-224, SHA-256, SHA-384, SHA-512 (SHA-256이상 권장)
- 대규모 사용자 기반 서비스라면 멀티 코어 활용하는 Blake2b 해시 함수 고려.
- 솔트(Salt) 기술: 입력받은 비번등에 특수 문자열을 더하여 해시 함수에 사용.
- 바이너리 데이터의 무결성 검증 : 파일에 대한 해시 값을 만들었으므로, 동일 파일을 서버에 저장할 필요없이 해시 값만 저장. MurmurHash3처럼 암호학적으로 민감하지 않되 성능 빠른 해시 함수 고려..
- 해시 값을 키로 사용 : 데이터가 많다면 충돌 가능성이 낮은 해시 함수 고려.
- 생일 역설(Birthday paradox) : 23명 모이면 같은 생일일 확률 50%, 57명이면 99%가 넘음.
- 시스템에 따른 고려 사항: 1) 입력값의 크기 2) 보안 수준 3) 해시값의 용도
2부 데이터 처리 기술
8장 JSON
- JSON(JavaScript Object Notation) : 숫자, 문자, 참 또는 거짓 등 여러 형태의 데이터를 키(Key)와 값(Value)으로 구조화된 객체(Object)에 담아 처리하는 규격.
- 몽고DB와 같은 NoSQL 데이터베이스는 JSON과 거의 동일한 BON을 공식 규격으로 사용.
- JSON 규격: UTF-8 인코딩만 허용. BOM 허용하지 않음. 주석 지원하지 않음.
- 주석필요시 XML이나 YAML 고려.
- 키 문자열은 Ascii 코드만 사용을 추천. 객체 직렬화//역직렬화시 추가 코드 작업이 필요하게 됨.
- 오류 줄이기: 1) try-catch 2) 사용전 key 검사 3) interlock 및 assert()
- 단점: 1) 텍스트 기반에 기인한 불필요한 트래픽 오버헤드 2) 텍스트 기반에 기인한 메시지 호환성(오타 및 수정 등) 유지의 어려움
9장 YAML
- YAML(Yet Another Markup Language): 이메일 양식에서 힌트를 얻어 만든 '사람이 쉽게 읽을 수 있는' 데이터 규격.
- YAML 특징: 주석 지원, 유니코드(UTF-8, UTF-16, UTF-32) 지원, 앵커(Anchors)와 별칭(Aliases)
- 앵커와 별칭: *, &, <<를 활용하여 값 참조
- 민감한 정보들은 레디스(Redis, Remote Dictionary Server)와 같은 키-값 저장소에 보관하고, YAML 동적 생성이나 RESTful API 서버로부터 값을 받아 사용하자.
10장 XML
- XML : 웹에서 규격화된 데이터를 효율적으로 주고받기 위해 만든 마크업 언어.
- XML은 문자 인코딩을 직접 지정할 수 있으나 인코딩 정보가 파일 안에 있어서 파일 인코딩 정보를 미리 알고 있어야 함.
- 태그, 요소, 속성
11장 프로토콜 버퍼
- 스키마 파일, 인터페이스 코드, 메시지 객체
- 프로토콜 버퍼(Protobuf, Protocol Buffers): 구글에서 만든 데이터 직렬화 규격. 바이너리 기반 규격.
- 프로토콜 버퍼 사용 방법
- .proto: syntax="proto3";, message, string, int64, bytes, enum, repeated, map, oneof(추상화계층), Any
- protoc.exe(프로토콜버퍼 컴파일러): protoc-3.x.x-win64.zip
- protobuf(Protobuf 라이브러리): protobuf-python-3.x.x.zip
- 스키마 파일(.proto) -> 컴파일러(protoc) -> 인터페이스 코드(.py) -> 프로젝트
- ↑
- Protobuf 파이썬 라이브러리 ------'
- 프로토콜 버퍼를 JSON으로 변환하는 의 경우 바이트 데이터가 Base64로 인코딩됨.
12장 Base64
- Base64 인코딩/디코딩, URL-Safe Base64
- Base64: 바이너리 데이터를 아스키 코드 일부와 일대일로 매칭되는 문자열로 단순 치환하는 인코딩 방식. (높은 확률로 ==로 끝나는 문자열), 문자열 -> 비트화 -> Base64 코드표 기반 인코딩
- 기존 데이터 길이보다 30%정도 늘어나지만, 바이너리 데이터를 문자열 기반 데이터로 취급할 수 있어 유용함.
- JSON 데이터에 이미지 파일을 포함하려는 경우 등: 이미지를 Base64로 인코딩하여 UTF-8과 호환 가능한 문자열로 처리.
- Base64 인코딩: 위키백과 베이스64, 패딩('=','=='):3바이트로 나눈 나머지만큼 패딩추가.
- Base64 디코딩: 인코딩 역순. 단지복원 데이터의 형태를 알 수 없기에 형태를 같이 기입.
- { "type": "image", "data": "ewPKIsH..." }
- 오늘날 스트림 데이터 처리를 위해 Base64를 주고받는 환경은 거의 없고, RTMP(Real Time Messaging Protocol)이나 HLS(HTTP Live Streaming)등으 동영상 프로토콜을 활용함.
- URL-Safe Base64: URL 주소에서 사용할 수 없는 문자들을 치환하여 사용
- - + → - 로 / → _ 로 = → . 로 (URL주소는 길이를 알기 때문에 패딩을 생략)
- HTTP로 큰 파일을 보내야 한다면 HTTP 멀티 파트 기능 고려.
13장 데이터 압축(zlib)
- zip, zlib, DEFLATE, INFLATE
- zlib는 상용 프로그램에서도 라이선스 비용 없이 사용할 수 있는 가장 많이 사용하는 무료 압축 라이브러리.
- HTTP또는 WebSocket 프로토콜은 DEFLATE 통신 기본 지원하지만, 브라우저와 Nginx같은 웹 서버 프로엠워크에서 해주므로 알아채기 어려울 뿐.
- zlib 라이브러리 자체는 표준이 아니지만, 라이브러리에서 DEFLATE 압축 표준을 지원하며 사실상 표준에 가까운 라이브러리로 자리잡음.
- 압축(Compression): 데이터의 공통된 부분을 찾아 하나로 묶어 그 정보를 저장하는 행위
- DEFLATE 알고리즘은 공통 부분 찾기위해 L777 알고리즘 사용.
- 이렇게 찾은 정보를 허프만 부호화(Huffman Coding)알고리즘으로 무손실 압축.
- INFLATE 알고리즘으로 압축 해제
- 손실 압축(Loss compression), 무손실 압축(Lossless compression) : 당연히 DEFLATE는 무손실압축. 압축률(Compression ratio), 압축 레벨(Compression level) 1~ 10단계, 압축 속도(Compression speed), 압축 해제 속도(Decompression speed), 체크섬(Checksum)
- UDP등 무결성이 보장되지 않는 경우 CRC32등으로 데이터의 무결성을 확인하는 것이 좋음.
- ADLER32는 CRC32보다 빠른 체크섬 방식.
3부 웹을 지탱하는 기술
14장 HTTP
- 무상태성, HTTP 서버, 세션과 쿠키, 스티키 세션, CORS, 아파치와 Nginx
- HTTP(HyperText Transfer Protocol): 서버와 클라이언트가 텍스트, 이미지, 동영상 등의 데이터를 주고받을 때 사용하는 프로토콜.
- 무상태성(Stateless): 요청 메시지를 보내기 직전까지 대상 컴퓨터가 연결 가능한지, 메시지를 응답할 수 있는 상태인지 알 수 없는 상태. [vs Stateful Protocol(ex. TCP)]
- 간단한 HTTP 서버: GET / HTTP/1.1\r\n <요청 메서드> <URL 경로> <HTTP 버전>\r\n
- HTTP 요청
- 요청 메서드: GET, POST, DELETE, PUT
- URL, DNS, URI(Uniform Resource Identifier): 특정 자원 위치
- 요청헤더: Host, Accept, User-Agent, Content-Type, Content-Length, Connection:keep-alive
- 메시지 바디
- HTTP 응답: HTTP/1.0 200 OK, 상태코드
- 세션과 쿠키: GDPR(General Data Protection Regulation, 유럽연합 일반 데이터 보호 규칙)
- 스티키 세션(Sticky session): 하나의 브러우저는 하나의 웹 서버에만 연결. (로드밸런스 서비스의 쿠키 문제 해결)
- CORS(Cross-origin resource sharing, 교차 출처 리소스 공유): HTTP 서버의 웹 페이지, 이미지나 API 등을 특정 호스트로 접속한 웹 브라우저만 사용할 수 있게 제한하는 정책.
- Same origin policy(동일 출처 정책)으로 인해 다른 서브 도메인 간 리소스 공유가 어려워지는 문제 해결.
- CORS 단순 요청: 요청 정보가 간단해 별다른 보안 검증이 필요하지 않은 교차 출처 리소스 공유.
- CORS 사전 요청: 추가적인 보안 검증이 필요한 요청.
- 아파치와 Nginx
- 웹 서버: 요청 처리, 정적 파일 캐시, 로드 밸런스 기능 지원, 압축 및 보안 기능 등등..
- Ngix 권장: 수평적 확장에 유리한 단일 스레드, 이벤트 기반, More than 아파치 다중 사용자 처리 입증.
15장 RESTful API
- RESTful API(Representational state transfer): 분산 시스템을 위한 소프트웨어 아키텍처의 한 형태.
- 애저 API 디자인 가이드 문서
- 글쓰기 API: http://localhost:5000/v1/posts, 메서드(POST, PUT/PATCH, DELETE)
- API 테스트: 포스트맨(Postman)
- 단일 글 읽기: GET http://localhost:5000/v1/posts/<글 번호>
- 여러 글 읽기: http://127.0.0.1:5000/v1/posts?size=<글 개수>
- 글 업데이트 API: PUT http://127.0.0.1:5000/v1/posts/<글 번호>
- 글 삭제 API: DELETE http://127.0.0.1:5000/v1/posts/<글 번호>
- 고려사항
- OAuth 표준 인증과 인가 기능
- DDOS 또는 클라이언트 버그로 Too many Call: 분당 API 호출 제한 정책
16장 HTTPS
- HTTPS 핸드셰이킹
- HTTPS(HyperText Transfer Protocol over Secure Socket Layer): TCP대신 TLS(Transport Layer Security) 프로토콜 기반
- 예전에는 SSL(Secure Sockets Layer) 프로토콜을 사용했으나 너무 많은 취약점으로 더이상 사용하지 않음. 이름을 그대로 사용하는 경우라도 내부는 TLS 기반
- 신뢰할 수 있는 인증서 발급 기관 목록: https://www.checktls.com/showcas.html
- TLS 버전: 1TLS 1.0(지원중단), TLS 1.1(지원중단), TLS 1.2, TLS 1.3
- 메시지 암호 키 교환: RSA(비공개키로 인한 보안 이슈로 1.3부터는 지원하지 않음), DHE -> ECDHE, PFS(Perfect Forward Security, 비밀 키가 노출돼도 과거에 주고받은 메시지가 안전한 특성)
- 인증서(X.509): CA(Certificate Authority, 인증 기관)
- 무료 SSL 인증서 발급: letsencrypt. 유효기간 3개월이지만 갱신 자동화 기능 제공.
- 신뢰 체인(Chain of trust, 연쇄 신뢰): 각 인증서가 서로 신뢰 관계에 있는 것.
17장 OAuth 2.0
- OAuth 1.0a vs OAuth 2.0
- OAuth: 데이터를 간편하고 안전하게 주고받기 위해 만들어진 표준.
- 리소스 서버(resource server)만 액세스 토큰(access token) 발급.. 일정 시간후 폐기(revoke)
- OAuth 1.0a: API를 사용하는 클라이언트의 권한 및 인증 역할 모두 수행. 안전하지만 복잡.
- 서명(signature), 요청 토큰(request token)등 직접 구현 필요.
- OAuth 2.0: 구조 간단 사용하기 쉬움. 하지만 가로채기 형태의 공격에 취약.
- 보완 방법은 개발자의 몫: HTTPS위에서 OAuth 2.0 사용 등
- 용어
- 리소스 소유자(resource owner): = 최종 사용자(end-user). 상황에 따라 백엔드 서버 등
- 주의점: 사용자의 권환 검증
- 리소스 클라이언트(resource client)
- 주의점: 액세스 토큰 관리, 공식 SDK 사용, 클라이언트 ID 및 시크릿 관리, HTTPS 사용
- 인가 서버(authorization server): 액세스 토큰과 인가 코드를 관리하는 서버.
- 주의점: 액세스 토큰 관리. 리소스 클라이언트 응답 처리
- 리소스 서버(resource server): 리소스 관리 및 API 제공 주체
- 주의점: 액세스 토큰 권한 검사, 클라이언트 데이터 검증
- OAuth 2.0 동작 구조
- 리소스 소유자(resource owner): = 최종 사용자(end-user). 상황에 따라 백엔드 서버 등
- JWT(JSON Web Token): 인가 서버 대신 토큰 안에 인가 정보를 포함하여 부하 줄이는 방법.
'[감상실] > 도서 | 책 | 동기부여' 카테고리의 다른 글
[책] 네이버 모두와 스마트스토어 (0) | 2021.05.06 |
---|---|
[책] Notion 업무와 일상을 정리하는 새로운 방법 노션 (0) | 2021.04.08 |
[책] 죽을 때까지 코딩하며 사는 법 (0) | 2021.04.06 |
[책] 미국주식 스몰캡 인사이드 2021 (0) | 2021.04.06 |
[책] 마흔 전에 일천재가 되는 40가지 법칙 (0) | 2021.04.05 |