본문 바로가기
CS/BackEnd

학교에서 알려주지 않는 17가지 실무 개발 기술

by Diligejy 2022. 5. 3.

 

https://coupa.ng/bMwVE7

 

한빛미디어 학교에서 알려주지 않는 17가지 실무 개발 기술 +미니수첩제공

COUPANG

www.coupang.com

 

p.22

개발자들은 문자열 인코딩 외 문자 집합(charset)이라는 용어도 함께 사용합니다. 엄격하게 구분하면 문자 집합은 사용할 수 있는 문자들의 집합을 말합니다. 유니코드, ISO-8859, ASCII 등이 이에 해당합니다.

 

반면 문자열 인코딩은 문자를 코드로 표현하는 방식을 일컫습니다. 예를 들어, 유니코드라는 문자 집합을 표현하는 문자열 인코딩은 UTF-8, UTF-16, UTF-32 등이 있습니다. 그러나 흔히 문자 집합과 문자열 인코딩을 혼용해서 사용합니다.

 

p.23

과거에는 7비트 2진수만 사용했지만, 현대 운영체제들은 성능 향상과 편의를 위해 8비트(1바이트)를 사용하여 아스키 코드를 표현합니다. 성능 향상과 관련해 더 자세한 내용이 궁금하다면, 메모리 4바이트 정렬memory 4-byte alignment에 대해 찾아보길 바랍니다.

 

p.26

CP949는 EUC-KR을 확장한 문자 집합으로 EUC-KR과 같은 문자열 인코딩이나, 더 많은 문자를 표현할 수 있습니다. 오늘날에는 EUC-KR로 표기하더라도 실제로는 CP949 문자 집합을 사용하는 경우가 많습니다.

 

p.27

영문자 'Hello'를 출력할 때 아스키 코드와 동일하게 5바이트를 사용했지만, 한글 '안녕하세요'를 출력하기 위해서는 10바이트를 사용했습니다. EUC-KR로 아스키 코드 영역에 있는 글자를 표현할 때는 1바이트를 사용하지만, 한글 문자를 표현할 때는 2바이트를 사용하기 때문입니다.

 

이처럼 문자열 인코딩에서는 실제 문자열 길이가 버퍼 길이와 다른 경우가 많습니다. 실제 문자열 길이는 사람 눈에 보이는 문자 길이에 해당하고, 버퍼 길이는 컴퓨터가 문자를 표현하는 데 사용한 바이트 수를 의미합니다. 여기서 버퍼는 메모리에 할당한 공간을 뜻합니다(예를 들어 변수를 선언해 숫자나 문자열 값을 넣거나, 새로운 객체를 생성하는 행위 등 모두 버퍼가 필요합니다). 그래서 실제 문자열 길이와 컴퓨터에 할당하는 버퍼 크기는 항상 다를 수 있다는 점을 꼭 기억하시길 바랍니다.

 

개발 환경에서는 실제 문자열 길이와 컴퓨터가 할당하는 버퍼 크기를 동일하게 취급해 생기는 버그가 생각보다 많습니다. 문자열을 취급할 때는 어떤 문자열 인코딩 방식을 쓰는지 반드시 알아야 하고, 가능한 같은 문자열 인코딩을 사용하는 것이 좋습니다.

 

p.29

보통 일반적인 문자는 3바이트 내로 처리되며, 4바이트 영역에는 이모지(에모지)같은 문자가 있습니다. 고대 문자 같은 것을 사용하지 않는 한 5바이트 이상을 쓰는 경우는 거의 없습니다.

 

p.35

UTF-16과 UTF-32는 바이트 순서 표시byte order mark(BOM)을 사용합니다. BOM은 문자열 가장 맨 앞 2바이트에 0xFEFF(유니코드 U+FEFF)로 표기하여 사용한다는 것을 의미합니다. 또한 0xFE와 0xFF 중 어떤 문자가 먼저 오는지에 따라 리틀 엔디언little endian(LE)와 빅 엔디언big endian(BE)으로 나뉩니다. 그래서 두 방식에 따라 문자열 인코딩 시 바이트 데이터를 조합하는 순서가 바뀌게 됩니다. 

 

BOM을 이용하여 바이트 표현 순서를 정하는 이유는, CPU 설계에 따라 바이트 값을 처리하는 순서가 다르기 때문입니다. 같은 0xFEFF를 CPU가 읽을 때 리틀 엔디언 방식은 0xFF 다음 0xFE을 읽으며, 빅 엔디언 방식은 0xFE 다음 0xFF를 읽습니다.

 

p.36

'Hello', '안녕하세요' 문자열 출력 결과에 UTF-16은 0xFF가 먼저 나왔으므로 리틀 엔디언(UTF-16-LE) 인코딩으로 볼 수 있습니다. 리틀 엔디언은 뒷자리부터 읽으므로 0x48, 0Xc5를 0xC548로 읽습니다. 오늘날 대부분의 개인 컴퓨터는 리틀 엔디언 방식을 사용합니다.

 

UTF-8에는 BOM이 없었습니다. 그 이유는 무엇일까요? UTF-8도 BOM이 없었습니다. 그 이유는 무엇일까요? UTF-8도 BOM에 해당하는 값이 있지만(0xEF, 0xBB, 0xBF). 1바이트 단위로 글자를 변환하기 때문에, 글자를 읽는 순서가 달라도 영향을 받지 않습니다. 따라서 UTF-8은 BOM을 사용할 필요도 없고, 권장하지도 않습니다. 대부분의 라이브러리나 프로그램은 UTF-8 문자열이나 파일을 읽을 때 BOM을 발견해도 무시하고 넘어갑니다. 심지어 JSON 규격은 BOM을 허용하지 않습니다.

 

p.39

UTF-16 기반 환경에서, UTF-8을 사용할 때는 사용 영역을 명확히 구분하는 게 좋습니다. 예를 들어 자바 기반 웹 서비스는 기본적으로 UTF-16을 사용하되, 외부(데이터베이스와 브라우저 간) 통신 시 UTF-8로 변환하여 사용하는 게 좋습니다.

 

p.40

- MySQL의 UTF-8 타입에는 utf8과 utf8mb4가 있습니다. utf8은 3바이트까지 정상으로 처리하나, 4바이트 영역 문자는 처리하지 못합니다. 따라서 UTF-8과 완벽히 호환되는 문자 집합을 쓰고 싶다면 utf8mb4를 써야 합니다. 이는 MySQL 설정에서 변경할 수 있습니다.

- 국내에서 만든 서비스를 연동할 때는 EUC-KR을 사용하는 경우가 있으니 주의해야 합니다. 예를 들어 집필 시점에서 KG Inicis 결제 모듈은 결제 요청 내역을 EUC-KR로 인코딩해야 합니다.

 

p.42

i18n은 다국어를 지원하기 위해 만든 표준으로 국제화의 첫 문자(i)와 마지막 문자(n) 사이에 18개 문자가 있다는 것을 의미합니다. i18n을 사용하면 프로그램이 출력할 문장을 코드로부터 분리하고, 코드 수정이나 재컴파일 없이 시스템/브라우저 설정에 따라 적절한 언어를 출력할 수 있습니다.

 

p.43

i18n의 또 다른 장점은 더 이상 사용하지 않는 문장이나 누락된 문장들을 자동으로 감지한다는 점입니다. 이런 특징으로 별다른 조치 없이 실제로 사용하는 문장만 번역할 수 있고, 누락 검사도 필요하지 않습니다. 문장 파일에 있는 문장들은 개발 이후, 또는 개발과 별개로 다듬거나 번역하면 되기 때문에 개발 작업과 별개로 진행이 가능하다는 장점도 있습니다.

 

p.202

Base64는 바이너리 데이터를 아스키 코드 일부와 일대일로 매칭되는 문자열로 단순 치환하는 인코딩 방식입니다.

 

Base64를 사용하는 큰 이유는 바이너리 데이터를 텍스트 기반 규격으로 다룰 수 있기 때문입니다.

 

p.225

HTTP는 여러 다른 기술과 함께 사용됩니다. 대표적으로는 JSON 등을 HTTP와 함께 사용하는 RESTful API가 있으며, 이 기술은 데이터를 보다 쉽고 효율적으로 주고받기 위해 탄생했습니다. JSON이 범용적으로 사용되기 전에는 XML과 HTTP를 함께 사용하는 SOAP도 있었습니다.

 

오늘날에는 데이터를 안전하게 주고받기 위해 HTTP에 전송 계층 보안(Transport Layer Security - TLS)을 더해 만든 HTTPS 프로토콜을 사용합니다. 보안이 중요한 만큼 모바일 기기 통신이나 웹 서비스 통신의 경우에는 HTTP가 아닌 HTTPS만 사용하도록 권고하는 추세입니다. 

 

p.227

클라이언트는 어떤 이유로든 서버로부터 일정 시간 안에 HTTP 응답을 받지 못하면 타임아웃timeout(응답 없음)으로 간주하고 요청을 실패한 것으로 처리합니다. 실무 환경에서는 실제로 서버가 제대로 처리를 했음에도 불구하고 응답을 보내는 도중의 시간에 클라이언트가 실패로 간주하고 재시도하는 경우도 많습니다.

 

타임아웃 시간과 최대 재시도 횟수는 전체 로직에서 서버 응답이 지닌 중요성이나 서버의 평균적 부하, 실패 확률 등을 따져보고 결정해야 합니다. 클라이언트(또는 최종 사용자)가 기다려야 하는 최대 시간이 사용자 관점에서 이해할 수 있는 수준인지도 고려해야 합니다.

 

여기서 이해할 수 있는 수준이란 무엇이고 최대 시간은 몇 초가 적당할까요? 웹페이지에 접속하는 사용자를 예로 들어봅시다. 사용자는 5초 이상 기다려도 웹 페이지가 열리지 않으면, 계속 기다리는 대신 새로 고침(F5)을 누르거나, 웹 브라우저를 종료한 후 다시 접속할 것입니다. 이 관점에서 보면 재시도 횟수는 한 번으로도 충분하며, 최대 요청 타임아웃 시간은 5초로 설정하는 것이 사용자 관점에서 '이해할 수 있는 수준'이 될 것입니다.

 

p.228~229

TCP는 텍스트가 아닌 바이너리 데이터를 사용하지만, HTTP는 TCP 프로토콜 기반에 텍스트 기반의 HTTP 헤더와 메시지까지 사용하기 때문에 패킷 크기가 상대적으로 큽니다. 반면 TCP 패킷 크기는 상대적으로 가벼워서 많은 사용자를 처리할수록 HTTP보다 TCP가 더 빠를 수밖에 없습니다.

 

HTTP는 각 요청이 소켓 1개를 점유하기 때문에 큰 문제가 생기지 않지만, TCP는 모든 요청이 소켓 1개를 사용하기 때문에 모든 요청이 1개의 소켓 안에서 섞이게 됩니다. 그래서 별도로 요청 ID와 같은 식별자를 사용하지 않으면 각 요청에 해당하는 응답을 구분할 수 없습니다. 또한, 프로토콜에서 응답이 왔는지 확인할 방법을 제공하지 않기 때문에 타임아웃 기능도 직접 구현해야 합니다.

 

오늘날 주로 사용하는 모바일 네트워크에서 TCP를 사용할 때는 더욱 조심해야 합니다. 연결이 자주 끊어지기 때문에 재연결을 시도할 때 안정적으로 제어할 로직을 직접 구현해야 합니다.

 

정리하면, TCP는 HTTP보다 상대적으로 빠르지만 개발자가 연결 상태를 직접 관리해야 해서 로직이 복잡할 수밖에 없습니다. HTTP는 로직이 간단하지만 TCP보다 느립니다.

 

서버와 클라이언트가 주고받는 메시지 양이 많다고 반드시 TCP를 사용할 필요는 없습니다. 서버는 늘리면 그만이고, 주문 처리, 로그인을 위한 인증 과정 등 연결 부분을 제외한 실질적인 서버의 동작을 실행하는 시간 자체는 TCP나 HTTP 모두 비슷하여 큰 차이가 없기 떄문입니다.

 

p.232

요청 줄은 반드시 다음과 같은 규격이어야 합니다.

 

<요청 메서드> <URL 경로> <HTTP 버전>\r\n

 

p.233

GET 메서드는 읽기 요청에 해당하므로 메시지 바디를 넣을 수 없습니다. 대신 요청 주소에 ?와 & 문자를 구분자로 사용하는 쿼리 파라미터를 추가할 수 있습니다.

 

? 문자는 첫 번째 파라미터를 구분할 때, & 문자는 파라미터 사이를 구분할 때 사용합니다. 

 

p.234

POST 메서드는 클라이언트에서 서버로 데이터가 포함된 요청을 보낼 때 사용합니다. 일반적으로는 ID와 비밀번호로 로그인을 하거나 상품을 장바구니에 담고 주문을 요청하는 과정 등에서 POST 메서드를 사용합니다.

 

p.234

중요한 점은, URL 주소는 '사람이 기억하기 쉽게'만든 식별자에 불과합니다. 두 컴퓨터가 실제로 통신할 때는 IP를 사용하기 때문에 통신을 위해서는 URL을 IP주소로 변환하는 작업이 필요합니다.

 

주소 변환 작업은 도메인 네임 시스템(domain name system - DNS)를 통해 할 수 있습니다. 그래서 웹 브라우저와 같은 클라이언트는 URL이 아닌 DNS로부터 받은 IP주소로 실제 접속을 요청합니다. 하나의 URL이 여러 IP주소를 가질 수도 있습니다. 클라이언트가 IP 주소를 요청할 때마다 DNS가 여러 IP 주소 중 하나를 보내주게 되므로 서버 부하를 줄일 수 있습니다. 이 기능은 DNS 라운드 로빈(round robin) 또는 DNS 로드 밸런싱(load balancing)이라고 합니다.

 

p.235

HTTP 버전은 HTTP 표준을 정의하는 버전으로, 버전에 따라 사용할 수 있는 기능이나 통신 방법이 조금씩 다릅니다.

 

현재 가장 많이 사용하는 HTTP 버전은 1.0, 1.1과 2.0이 있습니다. 1.1 버전은 1.0버전보다 효율적인 연결을 위해 소켓 재사용을 요청하는 keep-alive 헤더추가와 언어 및 인코딩 지원을 위한 헤더 등이 추가됐습니다. 그래서 오늘날은 대부분 1.1버전의 HTTP를 사용합니다.

 

그러나 1.1버전은 하나의 요청에 하나의 응답만 보낼 수 있습니다. 웹 페이지 하나를 보려면 적게는 2MB, 많게는 10MB 데이터와 크고 작은 여러 요청이 필요합니다. 만약 이 파일들을 요청할 때, 한 번이 아닌 수십 개의 요청으로 나눠 받는다면 비효율적일 것입니다. 

 

웹페이지 하나를 보기 위해 수십 번을 요청해야 하는 문제를 해결하고자, 한 번의 요청에 수십 개의 응답을 병렬로 보낼 수 있도록 개선하고 불필요한 오버헤드를 제거한 것이 바로 2.0버전입니다.

 

https://krksap.tistory.com/1152

 

Http 프로토콜 버전별 정리

Http 프로토콜 버전별 정리 http프로토콜은 가장 많이 쓰이는 프로토콜인데 1.0, 1.1, 2, SPDA 이정도가 가장 많이 쓰이는 것 같다 요즘은. 크롬 개발자 도구에서 프로토콜 찍어보면 이런식으로 나온다

krksap.tistory.com

p.238

User-Agent 헤더를 가져올 때는 운영체제, 브라우저 종류, 버전 정보에 따라 값이 바뀔 수 있다는 점을 염두에 두어야 합니다. 특히 인터넷 익스플로러의 경우 운영체제와 브라우저 버전별로 판별해야 할 값이 달라지므로 주의해야 합니다.

 

구글은 Useg-Agent에 불필요한 값(운영체제 정보 등)이 너무 많고, 마케팅 용도로 사용자를 추적하는 데 사용되기 때문에 사생활 침해 우려가 있어서 점진적으로 이 값을 사용하지 않고 폐기하기로 밝혔습니다. 대신 본래 목적인 디버깅과 브라우저 사용 현황 추적에 필요한 정보만 담아 이를 클라이언트 힌트(Client Hint)헤더에 넣을 것이라 밝혔습니다.

 

p.243

Flask 프레임워크는 HTTP/1.1 버전을 지원하지 않습니다. 1.1버전을 사용하기 위해서는 '14.8 아파치와 Nginx'를 참고해서 HTTP 서버를 사용해야 합니다. 그러나 기능을 개발하는 개발 초기 단계에는 1.0버전을 사용해도 큰 상관이 없습니다.

 

p.244

코드 및 메시지 의미
200 OK 요청이 성공했을 때
201 Created 리소스를 성공적으로 생성했을 때
301 Move Permanently 주소 이전. 클라이언트는 301 응답을 받는 즉시 새 주소로 이동함. 즉 서버 이동이라 불리며 새 주소는 location 헤더 값
400 Bad Request 올바르지 않은 요청을 보냈을 때
401 Unauthorized 접근 권한이 없을 때(접근하기 위해 인증이 필요하다는 뜻과 같음)
404 Not Found 서버가 제공하지 않는 주소나 존재하지 않는 주소로 요청을 보낼 때
405 Method Not Allowed 입력한 메서드를 허용하지 않을 때
500 Internal Server Error 모두 웹 서버 내부 또는 웹 서버를 구성하는 다른 내부 서버에서 에러가 발생할 때 (이때 클라이언트가 할 수 있는 게 없음)
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout

p.245

상태라는 개념이 존재하지 않는 HTTP는 보낸 요청에 대한 응답은 구분할 수 있어도, 이전에 어떤 요청을 보냈는지를 구분할 수 없습니다. 즉, 서버는 각 요청이 새로운 클라이언트로부터 온 것인지, 기존에 연결을 맺었던 클라이언트인지 알 수 없습니다. 모든 요청이 독립적으로 소켓 1개를 사용하고, 모든 요청은 다른 요청과 독립적이기 때문입니다.

 

요청 헤더의 Host값을 사용하면 구분이 가능하지만 완벽하진 않습니다. IP와 포트 주소만으로는 NAT 환경, 클라이언트의 포트 재사용과 같은 상황을 구분할 수 없기 때문입니다.

 

이 문제를 해결하기 위해 HTTP 웹 서버는 쿠키와 세션 ID를 사용해 클라이언트를 구분합니다. 쿠키를 사용하면 클라이언트가 새 요청을 보낸 것인지, 이전에 보낸 요청이 있었는지 구분할 수 있습니다.

 

p.246

아파치와 Nginx를 모두 이용해 웹 서비스를 구축했다면, 두 서버 간 통신 시 서로 사용하는 세션 ID 값이 달라 기존 연결이 있다는 것을 인식하지 못할 수 있습니다. 이때 OAuth 토큰 등을 이용해 새 연결인지, 기존에 연결을 맺은 클라이언트인지 확인해야 합니다.

 

p.247

일반적으로 웹 서버는 데이터를 크게 두 가지 형태로 분류해서 다룹니다.

 

첫 번째는 임시 데이터입니다. 일정 기간이 지나면 메모리 할당을 해제하고 사용하지 않습니다. 두 번째는 영구적 데이터입니다. 데이터베이스와 같은 곳에 보관해 사용합니다.

 

쿠키와 세션ID의 경우는 첫 번째 형태(임시 데이터)에 해당하고, 두 값으로 접근할 수 있는 정보는 두 번째 형태(영구적 데이터)에 해당합니다. 단, 자동 로그인 구현을 위해 세션ID를 일정 기간 동안 영구적 데이터로 취급할 때도 있습니다.

 

서버가 세션ID와 같은 쿠키 정보를 오래 가지고 있으면, 메모리 할당 외에 잠재적으로 생길 수 있는 여러 보안 문제가 발생할 수 있습니다. 특히, 쿠키를 탈취해 공격하는 기법에 노출될 수 있습니다.

 

대부분의 웹 서비스는 쿠키를 생성할 때 만료 시간도 함께 지정합니다. 만료 시간이 지나면 쿠키는 자동으로 삭제되므로 로그인을 했던 유저는 자동으로 로그아웃이 될 것입니다. 만약 로그인하지 않은 상태로 장바구니에 물건을 넣었던 사람이라면, 장바구니 정보가 사라지기 때문에 다시 장바구니에 물건을 담아야 합니다.

 

p.248

세션ID를 키로 하는 자료구조 컨테이너(맵 또는 해시 맵)를 사용 중이라면, LRU(Least Recently Used)알고리즘을 사용해 만료 시간이 지난 컨테이너 데이터를 지워야 합니다. 그렇지 않으면 서버가 종료되기 전까지 메모리에 데이터가 남아있게 됩니다.

 

p.251

스티키 세션(sticky session)은 이러한 구조를 보완하기 위한 기능입니다. 이 기능을 활성화하면 하나의 브라우저는 하나의 웹 서버에만 연결하게 됩니다. 로드밸런스는 첫 요청, 즉 쿠키가 없는 요청이 들어올 때 쿠키에 값을 등록하고 웹 서버를 지정한 다음, 이후 요청이 올 때 세션 값을 기준으로 다시 연결할 웹 서버를 구분합니다.

 

스티키 세션을 사용할 때는 세션 유지 기간도 함께 설정하게 됩니다. 세션 유지 기간은 웹 서버에서 사용하는 쿠키 만료 시간보다 길게 설정하는 게 좋습니다. 만약 세션 유지 기간이 쿠키 만료 시간과 비슷하거나 짧을 경우, 웹 서버에 쿠키가 남아 있음에도 스티키 세션 기간이 끝나 다른 웹 서버로 요청이 갈 수 있습니다.

 

p.255~256

개발자가 HTTP 표준에 부합한 웹 서버를 처음부터 만드는 것은 매우 어렵고 비효율적인 일입니다. 단순히 요청을 처리하는 것 외에도 정적 파일 캐시, 로드 밸런스 기능 지원, 압축 및 보안 기능 등 고려해야 할 게 너무 많기 때문입니다.

 

다행히 HTTP 표준에서 정의하는 기능을 바로 사용할 수 있는 웹 서버 소프트웨어가 있습니다. 바로 아파치(Apache)와 Nginx입니다. 아파치는 20년 전부터 사용해온 웹 서버로 안정성이 입증됐고 인증이나 많은 기능을 제공합니다. Nginx는 아파치보다 뛰어난 성능과 가벼운 구조로 많은 인기를 끌어 범용적인 웹 서버로 자리 잡았습니다.

 

아파치는 사용자 수가 늘어날수록 처리가 비효율적인 다중 프로세스 구조를 사용합니다. 반면 Nginx는 스티키 세션에서 이야기했던 수평적 확장에 유리한 단일 스레드와 이벤트 기반으로 동작하고, 아파치보다 많은 사용자를 처리할 수 있다는 게 입증됐습니다. 아파치나 Nginx 중 선호하는 것을 사용해도 무방하지만, 유지 보수 목적 또는 개발 환경이 아파치를 강제하는 상황이 아니라면 Nginx 사용을 권장합니다.

 

Flask 프레임워크는 HTTP/1.1 버전을 지원하지 않고 처리 성능 또한 나쁜 편입니다. 그래서 1.1 지원을 위해 Nginx를 함께 사용해야 하며, HTTP요청을 효율적으로 처리하게 돕는 WSGI 표준 모듈 (uWSGI, gUnicorn 등)을 추가로 사용해야 합니다.

 

p.258

RESTful API는 서버와 클라이언트가 메시지를 주고받을 때 가장 많이 사용하는 통신 규격입니다. REST란 representational state transfer의 약자로 분산 시스템을 위한 소프트웨어 아키텍처의 한 형태를 가리키며, RESTful이란 REST의 조건을 만족한다는 뜻입니다. 요청 주소와 메서드(GET, POST 등), JSON 규격을 이용하여 API를 정의하고 사람이 읽기 쉬운 형태이기 때문에 오늘날 가장 범용적으로 사용합니다.

 

https://docs.microsoft.com/ko-kr/azure/architecture/best-practices/api-design

 

웹 API 디자인 모범 사례 - Azure Architecture Center

플랫폼 독립성과 서비스 진화를 지원하는 웹 API 설계를 위한 모범 사례를 알아봅니다.

docs.microsoft.com

p.259

API를 사용하는 입장에서 호환성을 고려할 수 있도록 모든 API에는 버전을 명시하는 게 좋습니다. 호환성이 깨지면 사용자에게 이를 알리는 것보다 새로운 버전(v2)의 API를 만든 다음, 충분한(6개월 이상) 기간을 두고 두 버전 모두 사용할 수 있게 하는 것이 좋습니다. 이전 버전에 대한 지원은 중단하고 이를 사용자에게 알려 사용하는 사람이 충분한 기간을 두고 새 버전을 사용할 수 있게 하는 것이 좋습니다.

 

p.274

실무에서 만들 API는 공개 API가 아닌 이상 형식이 크게 중요하지 않지만 일관성을 지키는 것은 정말 중요합니다. 글 읽기 API 응답 메시지에 포함된 글 내용을 "posts" 객체로 감쌌던 이유도, 단일/여러 글 읽기 API에서 항상 JSON배열을 사용한 것도, 클라이언트가 일관성 있는 API에 쉽게 익숙해질 수 있고 코드를 재사용할 수 있게 설계했기 때문입니다.

 

p.276

HTTPS(HyperText Transfer Protocol over Secure Socket Layer)는 서로 다른 두 컴퓨터가 네트워크를 통해 안전하게 메시지를 주고받기 위해 만든 프로토콜입니다. HTTPS는 TCP대신 전송계층보안(TCP - Transport Layer Security) 프로토콜을 기반으로 하는 HTTP라고 이해하면 됩니다. 여기서 이야기하는 TLS는 OLI 7계층 중 네 번째에 해당하는 전송 계층의 TCP 프로토콜을 기반으로 동작하는 보안 프로토콜입니다.

 

TLS가 등장하기 전까지는 TLS 대신 보안 소켓 계층(SSL - Secure Socket Layer) 프로토콜을 사용했습니다. 오늘날 SSL은 너무 많은 취약점으로 더 이상 사용하지 않지만, 여러 문서나 OpenSSL 등의 라이브러리는 SSL 이름을 계속 사용합니다. 이러한 문서나 라이브러리에서 사용하는 SSL은 TLS와 같다고 생각하면 됩니다.

 

p.277

HTTPS는 4계층에서 동작하는 TLS와 달리, 더 높은 7계층에서 동작합니다. 그래서 키를 안전하게 교환하는 것 외에도 7계층 정보인 HTTP의 도메인 주소가 신뢰할 수 있는지 검사하는 기능도 제공합니다.

 

익스플로러, 크롬, 파이어폭스와 같은 웹 브라우저는 HTTPS 연결 과정에서 서버가 보낸 인증서를 받습니다. 인증서가 신뢰할 수 있는 기관에서 인증한 게 아니거나 인증 기간이 만료됐다면 연결을 허용하지 않습니다.

 

p.289

HTTPS를 소프트웨어 프레임워크에서 설정하는 것보다는 Nginx나 아파치와 같은 웹 서버에서 설정하는 것이 안전합니다. 두 서버 모두 HTTP 및 HTTPS 표준에 부합하는 많은 기능을 가지고 있고 이미지와 같은 정적 파일을 자동으로 캐시 처리하는 등의 좋은 기능이 있기 때문입니다.

 

p.289

TLS 1.0과 1.1 지원은 중단됐으므로 TLS 1.2 이상에 해당하는 암호화 목록을 사용해야 합니다. 그러나 TLS 1.2를 지원하지 않는 오래된 버전의 개발 플랫폼이나 하드웨어와 통신하는 것을 고려한다면 1.1 사용을 고민해보시길 바랍니다.

 

p.292

Restful API가 서로 다른 두 애플리케이션 간 데이터를 간편하게 전달하기 위해 만든 관례라면, OAuth는 데이터를 간편하고 안전하게 주고 받기 위해 만들어진 표준입니다.

 

OAuth는 ID와 비밀번호 대신 엑세스 토큰(access token)을 기반으로 사용자를 식별합니다. 이 토큰은 API를 제공하는 리소스 서버(resource server)만 밝릅할 수 있으며 일정 시간(대부분 1시간)이 지나거나 폐기(revoke)될 수 있습니다. 또한 모든 토큰은 필요한 권한만 지니게 할 수 있어서 OAuth를 이용하면 서버는 클라이언트의 접근 권한을 쉽게 제어할 수 있다는 장점이 있습니다.

댓글