대부분 개념적으로 특정 키값에 대해 테이블 데이터를 붙이는 작업을 하기 때문에

Outer는 쳐다도 안 보고 Inner나 left join을 찾게 된다.

문제는 한 쪽 부분만 존재하게 되는 케이스이다.

예를 들어,

예약수와 조회수를 같이 보여줘야 한다고 치자.

논리적으로 예약수가 0이라도 조회수는 0이 아닐 가능성이 높다.

조회수를 count하는 방식에 따라 조회수가 0인데도 예약수가 0일 수도 있다.

[가령 특정 채널을 통해 들어오는 조회는 조회수 count가 안 되는 경우]

1. 양쪽이 모두 한쪽만 있는 가능성이 있음

2. 양쪽이 모두 키값에 대해 unique함

이러면 outer로 join해줘야 한다. 한 쪽이 unique하지 않다면 논리적으로 group by 해서 unique하게 만들고 작업하는 게 수월하다.

Query로 치면 Union All로 하면 된다.

 

보통 left join을 검색하면 이런 그림이 나온다

틀린 그림은 아니지만 이렇게 되면 마치 A의 row도 유지될 거라는 착각을 하게 된다.

정확히 이 그림이 의미하는 바는 'A의 정보'가 유지된다는 거지 구조가 유지된다는 의미는 아니다.

예를 들어, A의 키값에 대해 B에 2가지 상태값으로 row가 나뉘어져 있다면

A에 대해 여러 row가 매핑되면서 A의 row가 늘어나게 된다.

따라서 각 테이블 형식의 데이터를 키값으로 A에는 전혀 없는 B의 컬럼을 붙이는 과정이라도

둘 다 키값에 대해 같은 기준으로 묶여있는지 체크가 필요하다.

SQS: Simple Queue Service의 약자. AWS에서 나온 큐 서비스다. 큐를 쏴놓고 소진할 때까지 받으면 되기 때문에 멀티 프로세싱이나 로그 밸런싱 하기가 쉽다. FIFO로 할 건지 무작위로 할 건지 선택할 수 있다. 무작위로 하면 들어온 순서와 무관하게 큐를 준다. 매월 백만개까지는 무료라고 하니 로깅이나 마스터 정보 수준의 크기가 아니라면 가볍게 쓸만한 거 같다. 유료 수준으로 넘어가도 백만개당 0.5불 정도다.

Kafka: 아키텍쳐내에 여러 시스템이 등장하면서 데이터의 복잡성이 커지자 교통정리를 해주고 메시지, 이벤트에 대한 최적화, 로드 밸런싱이 필요해지게 되었다. 그래서 등장한 개념이 이벤트 트리거, 메시지 트리거들이다. 보통 이벤트 트리거들은 메시지를 따로 저장하기 때문에 캐싱이 되고 메시지 트리거 역할도 할 수 있다. 카프카는 이벤트 트리거로서 시스템 간의 데이터 transfer 주체를 producer, consumer로 나누고 내부에 topic - partition을 둠으로써 각 주체가 topic별 트리거링을 할 수 있게 해뒀다. consumer가 메시지를 요청(poll)하면 fetch가 돼있는 경우 fetch된 곳에서 자료를 갖다주며, 아닌 경우 partition에서 레코드를 갖다 준다.

케이스는 이러했다.

조회 수와 예약 수를 각각 뽑아서 하나의 view로 봐야 하는데

조회 수가 0이면서 예약 수가 0이 아닌 경우,

반대로 예약 수가 0이면서 조회 수가 0이 아닌 경우를 각각 봐야 했다.

이 경우 Join으로는 해결이 되지 않는다.

join은 어디까지나 기준 테이블이 존재하기 때문에, 기준 테이블에 없는 경우 출력되지 않는다.

[나의 경우 full outer join 같은 걸 시도해도 숫자가 맞지 않아 고생했다.]

 

먼저 Select가 대칭되는 모습을 만들어준다.

없을 경우 dummy 컬럼을 만들어 준다.

Select a, b, c, 0 as d from A

Union All

Select a, b, 0 as c, d from B

-----------------------------------

[최종]

Select a, b, c, d from

(Select a, b, c, 0 as d from A

Union All

Select a, b, 0 as c, d from B) as t

RPA를 하다보니 확장성 관련 외부 API를 많이 끌어와 쓰게 된다.

가령 Google Cloud Platform, MS AZURE 같은 AI 관련 기능, 웹툴 관련 기능도 있고

slack 같은 데스크톱앱 같은 것도 간단하게 앱을 만들고 OAuth 관련 기능만 활용하면 된다. [챗봇이나 noti 관련]

 

이런 것들을 활용하면서 OAuth가 무엇인가 궁금해져서 정리해 본다.

1. 나오게 된 이유

OAuth는 Open Authentication의 약어로 인증방식의 통합된 표준이라 볼 수 있다.

기존엔 아이디, 비밀번호 같은 걸 활용했으나 해당 정보는 상대적으로 보안이 취약한 구조였기 때문에

각 앱들이 API 서비스 등을 제공할 때 각각 인증하는 방식을 사용했었다.

그런 인증방식을 통합함으로써 여러 앱간 통합 인증도 가능하게 되었다.

(이래서 소셜 계정으로 로그인이 된다.)

+ 기존 방식에서는 서비스 사용 권한을 부여하기 위해서 그룹을 만들고 그 그룹내 각 아이디에 권한을 부여하거나

권한 그룹을 만들어 거기에 그 아이디를 소속시키는 형태였다.

그 권한이 부여된 아이디/패스워드를 뿌린다? 그럼 그냥 그 계정이 털리는 거다.

계정에 대한 컨트롤과 계정이 사용할 수 있는 서비스에 대한 컨트롤이 구분하기 어렵고 폐쇄적인 편이었다.

근데 OAuth는 그냥 열려있는 상태로 토큰만 갖고 있으면 해당 토큰에 부여된 서비스 요청을 할 수 있게 해놨다.

이런 자유도는 토큰을 통해 쉽고 빠르게 앱 생태계, 서비스를 확장시키도록 해주지 않았나 싶다.

 

"나 이런 서비스 만들고 싶은데 그럼 다른 곳에서 서비스하는 거 빌려와서 이리저리 활용해 봐야지"

=> IaaS, PaaS를 손쉽게 구매하고 내 앱 만들 확장성을 바로 구성

 

 

2. 인증 방식

기존 ID/PW를 쓰던 방식이 쿠키, 세션을 이용하는 것과는 달리 OAuth는 토큰을 이용한다.

콘솔계정의 사용자(개발자)는 앱[각주:1]이라는 개념을 만든다.

그러고 앱에 사용할 수 있는 관련 권한을 설정하고 토큰을 발행한다. [각주:2]

발행 시 토큰이 가질 수 있는 권한을 부여한다.

이후 OAuth 토큰을 요청하면 부여된 권한에 맞는 요청에 대해 API 기능[각주:3]을 하게 된다.

 

요컨대,

1. 앱 생성

2. 권한이 부여된 토큰 생성

3. 해당 토큰으로 요청하여 Access하고 API 기능 요청

하는 형태이다.

 

그래서 OAuth인증을 하라고 하면,

'일단 앱만들고 앱에 대한 토큰은 어디서 발행하는지 권한은 어떻게 되는지 볼까?' 로 접근하면 된다.

  1. 여기서 앱이라는 개념이 넓어지는데 단순히 우리가 사용하는 앱이 아니라 서비스를 사용하는 Back단의 주체까지 앱이라고 부른다. 어떤 면에선 권한을 부여하기 위한 개념적인 존재에 가깝다. [본문으로]
  2. 토큰 발행말고 Access Account를 따로 발급한다든가, API Key를 이용한다든가 할 수도 있다. 여기선 OAuth를 설명 [본문으로]
  3. 여기서 기능이라고 표현한 것은 단순히 정보 조회뿐 아니라 구글시트 쓰기, 드라이브 파일 삭제 등 API로 제공되는 것들을 모두 할 수 있기 때문 [본문으로]

CI/CD : 자동화된 통합(협업하는 프로젝트의 개발 테스트 등)과 자동화된 배포. Devops를 위한 개념. 기존에는 각자 Build하고 Test했다가 한번에 Commit하고 충돌나는 거 빼고 다시 테스트하고.... 하는 과정이 있었다고 한다. (그런 과정에서 보통 밤에 업로드하기 때문에 Nightly-Build라고 부르고, 소프트웨어 버전에서 Nightly라하면 실시간으로 업데이트 되는, 개발팀이 쓰는 최신 버전이라고 한다.) 그러다 Jenkins 같은 테스트 자동화, 배포 자동화를 한번에 관리해주는 툴들이 나오고, 많은 프로젝트와 서버에 관해 환경적인 다양성이 생기자 Docker같은 툴이 생겨났다.

Jenkins : 실시간으로 빠르게 개발, 테스트, 반영을 하려다 보니 각각 build하고 테스트하고 해서는 생산성이 나지 않게 되었다. 즉, 이런 프로세스 자체가 체계화되고 자동화될 필요가 생겼고 이를 위한 시스템이 Jenkins이다. 원래는 허드슨이라는 이름으로 먼저 생겼으나 그놈의 오라클이 인수해 버리면서, Jenkins로 독립해 오픈소스로 유지되고 있다. 테스트가 자동화 됐다고 하지만 테스트를 위해선 먼저 테스트 코드를 작성할 필요가 있다. 다만 그렇게 작성만 해놓으면 새롭게 Git 같은 곳에 commit이 쳐졌을 때 기능테스트를 거쳐 오류가 나면 오류가 났다 오류가 없으면 배포를 자동적으로 해주는 식이다. 개발자에따라 배포를 여러 서버에 해야 돼서 귀찮으니까 배포만 자동화하고 싶어서 쓰는 케이스도 있다.

docker : 테스트를 위해 각 서버의 환경(OS, 환경변수, 패키지, 라이브러리 등)을 각각 세팅하려다 보니 Host OS에서 중복되는 리소스들을 각 Guest OS에 세팅하고 각자 구동해야 하는 경우가 빈번했다. 그러다보니 테스트 자체의 속도도 느리고 테스트 환경을 새로 구축하는 것도 느렸다. 이때 고급 개발자들은 각 테스트를 할 수 있는 Container(일종의 정형화된 테스트베드)를 만들어 썼는데 이런 Container들을 비교적 쉽게 각 Layer로 모아 환경을 구축할 수 있는 것이 Docker이다. 그렇게 리소스를 같이 쓰게 되면서, 각자 Guest OS를 구동하고 돌렸던 hypervisor 방식보다 훨씬 효율적으로 테스트 환경을 구현할 수 있게 되었다.

TSDB : 시계열 데이터베이스. 기존 관계형 DB와의 차이점은 다른 key값을 거의 포기하고 timestamp 위주로 무조건 데이터를 쌓아버린다. 따라서 기존 관계형 DB처럼 예전 자료를 update하고 특정 자료를 찍어 Delete하는 데엔 약하지만 Select하고 새로운 자료를 Insert하는 데는 매우 빠르다. 즉, 실시간 데이터들(센서로부터 들어오거나 시계열 통계값을 바로바로 때리는 경우)을 처리하는 데 있어 강한 모습을 보인다. 또, 계속 병렬적으로 쌓아버리기 때문에 데이터가 방대해질수록 느려지는 관계형 DB와 달리 성능이 일률적이라고 한다. 대표적으로 2013년에 나온 InfluxDB가 있다. 자세한 구조는 따로 글 작성 예정.

NoSQL : 기존 관계형DB의 제약을 풀고 특정 데이터 형태에서 성능에 치중하기 위해 고안된 DB. TSDB도 NoSQL의 일종. NoSQL이라고 해서 SQL 언어를 아예 쓰지 않는 게 아니라서 Not only SQL이라고 하기도 한다. RDB의 수많은 규약들 중에 몇몇을 엄격하게 지키지 않거나 데이터의 분류를 다르게 하고 스키마가 없이 데이터를 Insert하는 등의 방식으로 성능을 극대화시킨다. 예를 들어, InfluxDB 같이 키-값으로 컬럼을 분류하고 데이터를 무조건 시간 순으로 찍어 넣는다든가, MongoDB처럼 정형화되지 않은 데이터(이미지, 테이블 등등)을 Document로 분류해서 넣어버린다든가, 혹은 Node, Label, Edge 등의 데이터 형태로 저장하는 Neo4J(그래프 데이터베이스) 등이 있다.

+ Recent posts