항해 1주차 회고 (WIL)

계리·2022년 9월 25일
0
post-thumbnail

항해 1주차 WIL List

  • 웹 개발 미니 프로젝트
  • API

웹 개발 미니 프로젝트

  • 사용한 언어 - Python, Javascript
  • 사용한 App - Flask Framwork, MongoDB, AWS EC2
  • jinja2, JWT

설계의 중요성

웹 개발 미니 프로젝트를 하면서 S.A 작성을 먼저 명확하게 끝내고 진행 해야 하는 것을 느꼈다. 우리 조는 어떤 기능까지 구현할 수 있을지에 대해 확신이 없다고 생각을 하면서 와이어프레임과 API 설계를 하다 보니 역할 분담에 대해서도 확실히 정하지 못하게 되고 "이런식으로 CSS 꾸며보고, 이런식으로 기능들을 구현 해보죠" 라는 식으로 회의를 마치고 각자 맡은 기능 구현을 시작을 했다. 그리고 뭔가 점점 산으로 가는 것 같은 느낌이 들었고 멘토님께서 와이어프레임과 역할분담을 확실히 해야 할 것 같다고 잡아주셨다.


문제 해결을 위한 노력

미니 프로젝트를 진행 하면서 오류가 발생 했지만 해결하지 못하고 프로젝트를 진행한 부분이 있어 아쉬움이 남았었다. git에 배포된 프로젝트를 내 PC로 pull 하고 나서 Flask에서 서버를 실행 하려고 하는데 설치된 패키지가 없다고 오류가 발생 했었다. 매니저님께 질문을 드리고 받은 답으로 python freeze를 이용하여 패키지 묶음 파일을 만들어서 배포 하여 터미널에서 명령어 "pip3 install -r requrements.txt"를 입력 했지만 적용이 되지 않았다. 구글링을 하여 다른 명령어를 입력 했지만 그래도 해결이 되지 않아 핑계일 수 있지만시간이 부족할 것으로 보여 먼저 패키지들을 직접 설치 하고 진행을 하게 되었다. 다음에는 먼저 해결 시도 후 못했을 때는 꼭 동료분들, 매니저님들에게 도움을 요청하여 문제를 해결 할 수 있도록 생각을 했다.


꾸준함과 정리

주특기(Spring)를 막 시작하면서 알고리즘에 비중을 많이 두는 것이 맞을까라는 의문점이 생겼다. 알고리즘도 중요하겠지만 나는 JAVA 개념이 더 중요하지 않나? 라는 생각이 계속 들면서 사실 알고리즘 문제 푸는 것에 대해 집중을 하지 못했었다. 그리고 기술 매니저님께 의문점에 대해 말씀을 드렸고 어느 정도 의문점이 풀렸다. JAVA 개념 공부 하면서 알고리즘 문제도 풀고 알고리즘 주차가 끝나고 하루에 한 개씩 풀어본다는 생각으로 꾸준하게 준비를 하는 것을 조언 해주시고 공부한 것들을 잘 정리 해놓는 것도 조언을 해주셨다. 다음 주 부터는 JAVA 개념과 알고리즘을 잘 분배해서 공부 하고 공부한 내용들을 잘 정리하도록 습관을 들이도록 해야겠다.


JWT(JSON Web Token)

JWT를 알아보기 전에 먼저 알아야할 것들

  • 인증, 인가
  • 쿠키
  • 세션
  • 토큰

인증과 인가

인증(authentication)

특정 서비스에 일정 권한이 주어진 사용자임을 증명 하는 것 또는 클라이언트 측의 신원을 증명하는 것

인가(authorization)

한 번 인증을 받은 사용자가 이후 서비스의 여러 기능들을 사용할 때 서버에서 사용자가 로그인 되어있음을 알아보고 허가 해주는 것 또는 클라이언트에게 특정리소스를 사용할 수 있도록 권한을 부여 해주는 것


인증의 대표적인 방식

쿠키(cookie)

특정 사이트를 방문 시 브라우저(클라이언트)가 서버에 요청을 보낸다. 그러면 서버는 브라우저에게 응답을 해주는데 응답에는 모든 데이터와 클라이언트가 찾던 페이지 정보가 있는데 이것들을 저장해서 사용할 수 있도록 매개 역할을 해준다. 즉 클라이언트에게 필요한 정보들을 옮겨 전달해주는 매개체이다.


쿠키를 사용하는 이유

예를 들어 ID, PW를 가지고 로그인 요청 후 별다른 ID, PW 없이 로그인이 된 상태에서 요청을 날릴 수 있다. 쿠키가 없다면 매번 요청을 할때마다 쿠키로 ID, PW를동시에 사용자가 날려야하는 번거로움이 생기게 된다.

하지만 아래의 쿠키의 단점들 때문에 쿠키만 온전히 인증에 사용하지는 않는다.

  • 쿠키는 노출이 되었을 때 ID, PW에 대한 민감 정보까지 다 노출이 되어 보안에 취약하다
  • 조작당해서 들어올 가능성이 있다
  • 웹 브라우저마다 쿠키에 대한 지원 형태가 다르기 때문에 다른 브라우저간의 공유가 불가능
  • 쿠키의 사이즈가 제한(4KB0되어있어 원하는 만큼의 충분한 데이터를 담을 수 없을 경우가 발생
  • 서버는 매번 ID, PW를 받아서 인증을 해야하는 불편함이 있어 조작된 데이터가 넘어오는 경우를 방지할 수 없다

세션(session)

사용자 인증에 대해 서버측에서 유저의 인증정보를 생성하고 클라이언트 측에 인증정보 ID를 전달하여 쿠키가 저장하는 방식이다. 전통적인 stateful 방식으로 클라이언트의 상태를 서버에 계속 유지하고 해당 정보를 통해 서비스를 이용하는 인증 방식

세션은 ID, PW를 주고받지 않고 인증 정보 자체를 특정 세션 저장소에 저장하고 이 값을 쿠키에 담아 클라이언트가 쿠키를 요청할 때마다 세션 저장소에 있는 정보랑 동일한지로 로그인을 확인하자가 주요 핵심이다

세션으로 인증하는 과정

  1. 클라이언트가 ID, PW로 서버에 로그인을 요청
  2. ID, PW로 인증 후 사용자를 식별할 특정 유니크한 세션 ID를 만들어 마치 자물쇠처럼 서버의세션 저장소에 저장
  3. 세션 ID를 특정한 형태(쿠키 또는 JSON)로 클라이언트에 다시 반환
  4. 이후 사용자 인증이 필요한 정보를 요청할 때마다 이 세션 ID를 쿠키에 담아 서버에 함께 전달
  5. 인증이 필요한 API일 때 서버는 세션 ID가 세션 저장소에 있는지 확인
  6. 있다면 인증 완료 후 API 처리, 없다면 401 에러 반환

만일 보안 문제가 발생하게 된다면(탈취당한 세션 ID 쿠키가 발생할 경우 등) 세션 저장소를 전부 지워버리면 된다. 세션 ID가 탈취당했어도 해당 세션 ID가 현재 지정된 세션 저장소를 모두 지워버리면 탈취된 세션 ID로 서버에 접근해도 인증될 수 없기 때문

그렇다면 세션 저장소가 어떠한 모종의 이유로 장애가 발생하면 인증 전체의 문제가 생겨 정상적인 사용자가 인증을 하지 못하는 상황도 발생


세션의 단점

HTTP의 장점 중 statless를 위배하게 될 수 있다는 점이 있다. 서버의 세션 저장소에 세션 ID 즉 상태를 저장하는 상황이기 때문에 stateful 하게 된다는 것이다. stateful의 단점은 서버에 상태를 저장해야 하기 때문에 서버를 늘리고 싶다고 생각할 때(scale out) 로그인 정보를 저장해야 하는 세션 저장소가 scale out 하기 이전의 서버에 있기 때문에 따로 다시 세션 ID를 저장해야 하는 번거로움이 발생하게 된다. 결국 중앙 세션 저장소를 필히 따로 만들어야 scaleout의 문제가 최소화 될 수 있다.

  • 세션 저장소의 문제가 발생하면 인증 체계가 무너져 이전에 다른 인증된 유저 또한 인증이 불가해진다
  • stateful 하기 때문에 HTTP의 장점을 발휘하지 못하고 scale out에 걸림돌이 발생한다
  • 세션 저장소가 필수적으로 존재하기 때문에 이를 사용하기 위해 비용이 든다
  • 세션 ID가 탈취당했을 때 대처는 가능하지만 클라이언트 인척 위장하는 보안의 약점이 있을 수 있다
  • 사용자가 많아질수록 메모리를 많이 차지하게 된다
  • 매번 요청 시 세션 저장소를 조회해야 한다

세션을 사용하면서 단점으로 꼽히는 것은 요청을 진행할 때마다 세션 저장소에 세션 ID를 조회하는 작업을 통해서 DB 접근이라는 로직이 한번 더 수행된다는 점 때문에 JWT를 사용하게 된다


JWT

JSON 포맷을 이용하여 사용자에 대한 속성을 저장하는 claim 기반의 웹 토큰 방식이다. 토큰 자체를 정보로 사용하는 self-containerd 방식으로 정보를 안전하게 전달한다. 주로 회원 인증이나 정보 전달에 사용된다.


토큰(token)

사용자의 인증에 대해 서버측에서 유저에게 토큰을 발급해주고 클라이언트 측에서는 토큰을 저장해서 요청시마다 토큰을 함께 서버에 전달하는 방식이다. 기존 쿠키나 세션 방식에서 사용했던 쿠키를 사용하지 않음으로 기존 발생 했던 취약점이 사라지고 stateless 상태로 상태를 유지하지 않아도 되기 때문에 확장성이 증가한다. 그리고 로그인 정보가 사용되는 분야를 확장함으로써 토큰을 사용하여 다른 서비스에 권한을 공유할 수 있다.

JWT는 하나의 인터넷 표준 인증 방식이다. 인증에 필요한 정보들을 token에 담아 암호화시켜 사용하는 token이다.

JWT는 서명된 토큰으로써 공개/개인 키를 쌍으로 사용하며 토큰에 서명할 경우 서명된 토큰은 개인 키를 보유한 서버가 서명된 토큰이 정상적인 토큰인지 인증할 수 있다


JWT 구조

  • Header
  • Payload
  • Signature


Hearder

{
	"typ": "JWT",
    "alg": "HS512"
}

보통 header에는 토큰의 타입이나 서명 생성에 어떤 알고리즘이 사용되었는지 저장한다.


Payload

{
	"sub": "1",
    "iss": "ori",
    "exp": 1636989718,
    "iat": 1636989718
}

Claim이라는 사용자에 대한 또는 토큰에 대한 property를 key - value 형태로 저장한다. Claim이란 토큰에서 사용할 정보의 조각이다.

  • iss(Issuer) : 토큰 발급자
  • sub(Subject) : 토근 제목 - 토근에서 사용자에 대한 식별 값이 됨
  • aud(Audience) : 토근 대상자
  • exp(Expiration Time) : 토근 만료 시간
  • nbf(Not Before) : 토근 활성 날짜(이 날짜 이전의 토큰은 활성화되지 않음을 보장)
  • iat(Issued At) : 토큰 발급 시간
  • JTI(JWT Id) : JWT 토큰 식별자(Issuer가 여러 명일 때 이를 구분하기 위한 값)

표준 스펙상 key의 이름은 3글자로 되어있다. 위의 7가지를 꼭 모두 포함할 필요는 없다. 상황에 따라 해당 서버가 가져야 할 인증 체계에 따라 사용하면 되기 때문이다.

표준 스펙 이외에도 필요하다 싶으면 추가해도 전혀 문제가 없다. 예를 들어서 Access Token과 Refresh Token을 구분하고 싶으면 "token_type" 이라는 커스텀한 Claim을 만들고 아래와 같이 "access token"으로 두어 구분 지어도 된다.

{
	"token_type": "access token"
}

여기서 중요한건 payload에 민감한 정보를 담지 않는 것이다. header와 payload는 JSON이 디코딩되어있을 뿐 암호화가 걸려있는 것이 아니기 때문에 누구나 JWT를 가지고 디코딩을 한다면 header나 payload에 담긴 값을 알 수가 있기 때문이다

header와 payload에도 암호화를 하면 되지 않을까? 라는 생각을 할 수도 있지만 암호화 자체만으로도 많은 리소스를 사용하기 때문에(HTTP 요청마다 한 번의 복호화가 더 추가 되는 셈이 된다) 신중하게 사용하는 것이 좋다

그래서 유출되었을 때 그나마 상관없는 비민감정보를 토큰에 담는 것이 기본 스펙이 되는 것이고 서버는 굳이 header나 payload에 암호화하지 않아도 되는 것이다.

Signature

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  
your-256-bit-secret

) secret base64 encoded

header를 디코딩한 값, payload를 디코당한 값을 위처럼 합치고 이를 your-256-bit-secrit 즉 서버가 가지고 있는 개인키를 가지고 암호화되어있는 상태로 보면 된다.
signature는 서버에 있는 개인키로만 암호화를 풀 수 있으므로 다른 클라이언트는 임의로 signatre를 복호화할 수 없다.

인증하는 과정

  • JWT 토큰을 클라이언트가 요청과 동시에 전달
  • 서버가 가지고 있는 개인키를 가지고 signature를 복호화한 다음 base64UrlEncode(header)가 JWT의 header값과 일치한 지, base64UrlEncode(payload)와 일치한 지 확인하고 일치하면 인증을 허용

만약 클라이언트가 payload에 담긴 식별자가 변조된 JWT로 요청을 하더라도 서버가 애초에 발급했던 signature 안의 payload와 다르기 때문에 인증이 불가능 해진다


JWT 장점
  • 이미 토큰 자체가 인증된 정보이기 때문에 세션 저장소와 같은 별도의 인증 저장소가 필수적으로 필요하지 않다
  • 세션과는 다르게 클라이언트의 상태를 서버가 저장해 두지 않아도 된다
  • signature를 공동 키 개인 키 암호화를 통해 막아두었기 때문에 데이터에 대한 보안성이 늘어난다
  • 다른 서비스에 이용할 수 있는 공통적인 스펙으로써 사용할 수 있다

API(Application Programming Interface)

응용 프로그램에서 사용할 수 있도록 운영체제나 프로그래밍 언어가 제공하는 기능을 제어할 수 있게 만든 인터페이스를 말한다


API는 점원이다

레스토랑에서 손님에게 주문 가능한(선택 가능한) 메뉴를 보여주고 손님이 고른 음식을 주방에 전달 후 음식이 나오면 고객에게 전달하는 '점원'이 API이다.


API는 어떻게 동작하는가

API 아키텍처는 일반적으로 요청을 보내는 애플리케이션을 클라이언트라고 하고 응답을 보내는 애플리케이션을 서버라고 한다 위에 레스토랑 예로 보면 손님이 클라이언트, 점원이 서버라고 보면 된다. 요리사는 요청에 맞는 서버 내부 로직을 수행하여 점원에게 전달하여 손님에게 요청한 것에 대한 응답을 해준다


API의 역할

  • API는 서버와 데이터베이스에 대한 출입구 역할을 한다
    • 데이터베이스에는 소중한 정보들이 저장되어 있는데 모든 사람들이 데이터베이스에 접근하지 못하도록 API가 방지를 해줘 허용된 사람들에게만 접근성을 부여한다
  • API는 애플리케이션과 기기가 원활하게 통신할 수 있도록 한다
    • 여기서 애플리케이션은 우리가 흔히 알고 있는 스마트폰 어플이나 프로그램들을 말한다. API는 애플리케이션과 기기가 데이터를 원활히 주고받을 수 있도록 돕는 역할을 한다
  • API는 모든 접속을 표준화한다
    • API는 모든 접속을 표준화하기 때문에 기계 / 운영체제 등과 상관없이 누구나 동일한 액세스를 얻을 수 있다. 쉽게 말해 API는 범용 플러그처럼 작동한다고 볼 수 있다.

API 작동 방식

  • SOAP API

    • 이 API는 단순 객체 접근 프로토콜을 사용한다. 클라이언트와 서버는 XML을 사용하여 메시지를 교환합니다. 과거에 더 많이 사용되었으며 유연성이 떨어지는 API이다.
  • RPC API

    • 이 API를 원격 프로시저 호출이라고 한다. 클라이언트가 서버에서 함수나 프로시저를 완료하면 서버가 출력을 클라이언트로 다시 전송한다.
  • Websocket API

    • Websocket API는 JSON 객체를 사용하여 데이터를 전달하는 또 다른 최신 웹 API 개발이다. WebSocket API는 클라이언트 앱과 서버 간의 양방향 통신을 지원한다. 서버가 연결된 클라이언트에 콜백 메시지를 전송할 수 있어 REST API보다 효율적이다.
  • REST API

    • 오늘날 웹에서 볼 수 있는 가장 많이 사용되고 유연한 API이다. 클라이언트가 서버에 요청을 데이터로 전송한다. 서버가 이 클라이언트 입력을 사용하여 내부 함수를 시작하고 출력 데이터를 다시 클라이언트에 반환한다.

네 가지 중 두 가지만 비교를 해보면 먼저

REST(Representational State Transfer) API

  • 네트워크를 통해서 컴퓨터들끼리 통신할 수 있게 해주는 아키텍처
  • 인터넷 식별자(URI)와 HTTP 프로토콜 기반
  • REST는 HTTP 프로토콜 덕분에 단순함이 핵심
  • 데이터 포맷은 브라우저 간 호환성이 좋은 JSON을 사용
  • GET, PUT, DELETE 등의 함수 집합을 정의

REST API의 주된 특징은 무상태이다. 무상태는 서버가 요청 간에 클라이언트 데이터를 저장하지 않음을 의미한다. 서버에 대한 클라이언트 요청은 웹 사이트를 방문하기 위해 브라우저에 입력하는 URL과 유사하다. 서버의 응답은 웹 페이지의 일반적인 그래픽 랜더링이 없는 일반 데이터이다

REST방식의 API라면 클라이언트 - 서버 모델로 구축되었다는 것을 의미하며 정보의 페이로드(실제 전달하려는 데이터)가 두 지점 사이를 왕복하게 된다


참고

https://brunch.co.kr/@jinyoungchoi95/1
https://blog.wishket.com/api%EB%9E%80-%EC%89%BD%EA%B2%8C-%EC%84%A4%EB%AA%85-%EA%B7%B8%EB%A6%B0%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8/
https://brunch.co.kr/@operator/65

profile
gyery

0개의 댓글