이번이 첫 시도는 아니다. 필자는 1996년에 이 여정을 시작했고 이후 주기적으로 아이디어를 다듬었다. 2018년에는 실제 기능할 수 있는 가장 단순한 버전에 관한 기사를 썼다. 다양한 서비스에 대한 검색 URL을 몰아넣은 다음 각각의 자체 탭에서 각 서비스를 방문하는 형태의 웹 페이지다. 바보 같은 생각처럼 들릴 수도 있지만 도움이 되는 부분도 있어서 필자 외에도 사용하는 사람들이 생겼다.
물론 필자는 기반 API를 사용하고 결과를 정규화하고 이를 하나의 공통적인 뷰로 병합하고자 했다. 하지만 이렇게 하기 위해 온갖 API와 씨름해야 했는데 프로젝트가 가진 가치에 비해 난관이 너무 많았다. 이와 같은 작업을 해본 사람은 알겠지만 대부분의 서비스는 내가 선호하는 프로그래밍 언어를 위한 어댑터와 함께 검색 API를 제공한다. 그러나 각 서비스마다 API를 호출하고 결과를 페이지로 나누고 서식을 적용하는 각자의 방식이 있다. 이와 같은 차이점으로 인해 마찰이 발생한다. 결과를 일관적으로 다루기 위해서는 이 마찰을 극복해야 한다.
API 작업이 마찰 없이 된다면 많은 것이 가능해진다. 효과적인 메타검색이 그 중 하나다. 스팀파이프는 API 호출, 결과 페이지 구분, JSON 객체 압축 해제와 같은 작업에서 벗어날 수 있게 해준다. API를 대신 호출해주고 결과를 데이터베이스 테이블로 스트리밍해주므로 데이터 작업에만 온전히 집중할 수 있다. 즉, 메타검색 대시보드를 만들 때 직면하는 가장 큰 문제가 해결된다.
스키마로 수렴
다음 과제는 검색 결과를 공통된 스키마에 바인딩하는 것이다. SQL은 이를 위한 훌륭한 환경이다. 스크린캐스트의 대시보드를 만든 쿼리에는 SQL에 통달하지 않은 사람도 쓸 수 있는 3개의 스탠자가 포함된다. 모두 깃허브 문제를 검색하는 것과 동일한 패턴을 따른다.'github_issue' as type,
repository_full_name || ' ' || title as source,
to_char(created_at, 'YYYY-MM-DD') as date,
html_url as link,
substring(body from 1 for 200) || '...' as content
from
github_search_issue
where
$1 ~ 'github_issue'
and query = 'in:body in:comments org:github ' || $2
limit $3
파란색 항목은 데이터베이스 테이블의 열 이름이다(여기서는 스팀파이프의 깃허브 플러그인에 의해 만들어진 테이블 중 하나인 github_search_issue). 스팀파이프 허브는 테이블 열의 이름과 설명을 손쉽게 살펴볼 수 있게 해주며 테이블의 정보를 사용하는 방법에 대한 예를 보여준다.
이 데이터를 불러오는 데는 API 호출이나 JSON압축 해제가 불필요하므로 더 고차원의 검색 구문에만 집중할 수 있다. 여기에는 생각해야 할 부분이 많고, 소스 열을 공통 스키마로 맵핑하는 흥미롭고 재미있는(!) 과제도 있다.
빨간색 항목은 대시보드에 나타나는 열 이름이다. 이 대시보드의 경우 각 검색 결과가 type, source, date, link, content의 5개 열에 맵핑되도록 했다. SQL의 AS 절은 각 스탠자에서 스키마와 일치하도록 손쉽게 열 이름을 바꿀 수 있게 해준다.
전체 쿼리
이 대시보드의 전체 쿼리는 다음과 같다. 위와 같은 스탠자가 3개 있으며 각각은 CTE(공통 테이블 식)로 작성됐고 매개변수는 입력 변수에 해당한다. 그 외에는 거의 아무것도 없다! 각 스탠자는 API 기반 테이블을 쿼리하고(slack_search, github_search_issue, googleworkspace_drive_my_file) 열을 선택하고(변환할 수도 있음) 스키마에 맞게 결과에 별칭을 지정한다. 남은 것은 3개의 CTE에 UNION을 적용하는 것이 전부다. 이는 임시 테이블과 같은 역할을 하고 결과를 정렬한다.select
'slack' as type,
user_name || ' in #' || (channel ->> 'name')::text as source,
to_char(timestamp, 'YYYY-MM-DD') as date,
permalink as link,
substring(text from 1 for 200) as content
from
slack_search
where
$1 ~ 'slack'
and query = 'in:#steampipe after:${local.config.slack_date} ' || $2
limit $3
),
github_issue as (
select
'github_issue' as type,
repository_full_name || ' ' || title as source,
to_char(created_at, 'YYYY-MM-DD') as date,
html_url as link,
substring(body from 1 for 200) || '...' as content
from
github_search_issue
where
$1 ~ 'github_issue'
and query = ' in:body in:comments org:${local.config.github_org} ' || $2
limit $3
),
gdrive as (
select
'gdrive' as type,
replace(mime_type,'application/vnd.google-apps.','') as source,
to_char(created_time, 'YYYY-MM-DD') as date,
'https://docs.google.com/document/d/' || id as link,
name as content
from
googleworkspace_drive_my_file
where
$1 ~ 'gdrive'
and query = 'fullText contains ' || '''' || $2 || ''''
limit $3
)
select * from slack
union
select * from github_issue
union
select * from gdrive
order by
date desc
코드형 대시보드
많은 대시보드 시스템에서 이 쿼리를 사용할 수 있다. 예를 들어 메타베이스(Metabase)나 태블로(Tableau) 또는 다른 포스트그레스 클라이언트를 스팀파이프에 연결하고 여기서 보는 것과 같은 종류의 인터랙티브 대시보드를 만들 수 있다. 위젯과 설정이 사용자 인터페이스에서 처리되는 로우 코드 환경에서 이 작업을 할 수 있다. 스팀파이프의 대시보드 서브시스템은 코드형 인프라(IaC) 뿌리를 기반으로 하는 다른 접근 방식을 취한다. API에 대한 쿼리는 다른 모든 코드와 마찬가지로 버전 제어 리포지토리에서 관리되는 SQL 코드로 표현되어야 한다. 이러한 쿼리의 결과를 표시하는 대시보드 위젯도 마찬가지로 코드로 표현되어야 하는데, 여기서 언어는 테라폼의 HCL이다.메타검색 대시보드의 HCL 정의는 다음과 같다. 3가지 종류의 input 블록(source(다중 선택), search_term(텍스트), max_per_source(단일 선택, 기본값))을 선언한다. input 블록으로 훨씬 더 많은 일을 할 수 있다. 가령 이 문서에서 볼 수 있듯이 SQL 쿼리의 결과를 사용해 채울 수 있다. 다만 여기서는 그렇게 할 필요가 없다.
table 블록은 위에 정의된 쿼리를 사용하며, 전달되는 매개변수를 정의한다. wrap 인수는 텍스트가 많은 열의 가독성을 높인다.
그 외에는 더 살펴볼 만한 부분이 없고, 있어서도 안 된다. 코드로 대시보드를 구축하는 작업에 다량의 복잡한 코드가 필요하면 안 된다.
input "sources" {
title = "sources"
type = "multiselect"
width = 2
option "slack" {}
option "github_issue" {}
option "gdrive" {}
}
input "search_term" {
type = "text"
width = 2
title = "search term"
}
input "max_per_source" {
title = "max per source"
width = 2
option "2" {}
option "5" {}
option "10" {}
option "20" {}
}
table {
title = "search slack + github + gdrive"
query = query.metasearch
args = [
self.input.sources,
self.input.search_term,
self.input.max_per_source
]
column "source" {
wrap = "all"
}
column "link" {
wrap = "all"
}
column "content" {
wrap = "all"
}
}
}
묘기는 필요 없다
새 서브쿼리를 만들기 위해 SQL의 달인이 될 필요는 없듯이, HCL 전문가가 아니더라도 대시보드에 HCL을 추가할 수 있다. 소스를 추가하려는 경우 수십 개의 다른 플러그인 중에서 선택하면 된다. 플러그인은 매월 더 추가되며 모두는 아니지만 상당수가 검색 기능을 제공한다. 당연히 스팀파이프 쿼리를 사용해 손쉽게 찾을 수 있다.name
html_url
from
github_search_code
where
query = 'search org:turbot org:francois2metz org:ellisvalentiner org:theapsgroup'
and name ~ 'table'
and name ~ 'search'
order by
name
스팀파이프 샘플 리포지토리에는 여기에 나온 대시보드를 위한 코드와 함께 평가판 계정이 만료될 때 삭제한 젠데스크를 위한 부가적인 검색 스탠자도 포함돼 있다. 이 대시보드를 확장하면서 즐거운 시간을 보내기 바란다. 필요한 검색 API를 찾을 수 없는 경우 슬랙 커뮤니티를 방문해서 문의하면 된다. 필요한 플러그인을 누군가 이미 만드는 중일 수도 있다. 물론 직접 해결할 수도 있다. 새로운 플러그인으로 기본적인 HCL과 SQL을 다룰 수 있는 누구나 자유롭게 API를 활용하고 실제 문제를 해결할 수 있을 것이다.
editor@itworld.co.kr
함께 보면 좋은 콘텐츠
Sponsored
Surfshark
“유료 VPN, 분명한 가치 있다” VPN 선택 가이드
ⓒ Surfshark VPN(가상 사설 네트워크, Virtual Private Network)은 인터넷 사용자에게 개인 정보 보호와 보안을 제공하는 중요한 도구로 널리 인정받고 있다. VPN은 공공 와이파이 환경에서도 데이터를 안전하게 전송할 수 있고, 개인 정보를 보호하는 데 도움을 준다. VPN 서비스의 수요가 증가하는 것도 같은 이유에서다. 동시에 유료와 무료 중 어떤 VPN을 선택해야 할지 많은 관심을 가지고 살펴보는 사용자가 많다. 가장 먼저 사용자의 관심을 끄는 것은 별도의 예산 부담이 없는 무료 VPN이지만, 그만큼의 한계도 있다. 무료 VPN, 정말 괜찮을까? 무료 VPN 서비스는 편리하고 경제적 부담도 없지만 고려할 점이 아예 없는 것은 아니다. 보안 우려 대부분의 무료 VPN 서비스는 유료 서비스에 비해 보안 수준이 낮을 수 있다. 일부 무료 VPN은 사용자 데이터를 수집해 광고주나 서드파티 업체에 판매하는 경우도 있다. 이러한 상황에서 개인 정보가 유출될 우려가 있다. 속도와 대역폭 제한 무료 VPN 서비스는 종종 속도와 대역폭에 제한을 생긴다. 따라서 사용자는 느린 인터넷 속도를 경험할 수 있으며, 높은 대역폭이 필요한 작업을 수행하는 데 제약을 받을 수 있다. 서비스 제한 무료 VPN 서비스는 종종 서버 위치가 적거나 특정 서비스 또는 웹사이트에 액세스하지 못하는 경우가 생긴다. 또한 사용자 수가 늘어나 서버 부하가 증가하면 서비스의 안정성이 저하될 수 있다. 광고 및 추적 위험 일부 무료 VPN은 광고를 삽입하거나 사용자의 온라인 활동을 추적하여 광고주에게 판매할 수 있다. 이 경우 사용자가 광고를 보아야 하거나 개인 정보를 노출해야 할 수도 있다. 제한된 기능 무료 VPN은 유료 버전에 비해 기능이 제한될 수 있다. 예를 들어, 특정 프로토콜이나 고급 보안 기능을 지원하지 않는 경우가 그렇다. 유료 VPN의 필요성 최근 유행하는 로맨스 스캠은 인터넷 사기의 일종으로, 온라인 데이트나 소셜 미디어를 통해 가짜 프로필을 만들어 상대를 속이는 행위다. 이러한 상황에서 VPN은 사용자가 안전한 연결을 유지하고 사기 행위를 방지하는 데 도움이 된다. VPN을 통해 사용자는 상대방의 신원을 확인하고 의심스러운 활동을 감지할 수 있다. 서프샤크 VPN은 구독 요금제 가입 후 7일간의 무료 체험을 제공하고 있다. ⓒ Surfshark 그 외에도 유료 VPN만의 강점을 적극 이용해야 하는 이유는 다음 3가지로 요약할 수 있다. 보안 강화 해외 여행객이 증가함에 따라 공공 와이파이를 사용하는 경우가 늘어나고 있다. 그러나 공공 와이파이는 보안이 취약해 개인 정보를 노출할 위험이 있다. 따라서 VPN을 사용하여 데이터를 암호화하고 개인 정보를 보호하는 것이 중요하다. 서프샤크 VPN은 사용자의 개인 정보를 안전하게 유지하고 해킹을 방지하는 데 유용하다. 개인정보 보호 인터넷 사용자의 검색 기록과 콘텐츠 소비 패턴은 플랫폼에 의해 추적될 수 있다. VPN을 사용하면 사용자의 IP 주소와 로그를 숨길 수 있으며, 개인 정보를 보호할 수 있다. 또한 VPN은 사용자의 위치를 숨기고 인터넷 활동을 익명으로 유지하는 데 도움이 된다. 지역 제한 해제 해외 여행 중에도 한국에서 송금이 필요한 경우가 생길 수 있다. 그러나 IP가 해외 주소이므로 은행 앱에 접근하는 것이 제한될 수 있다. VPN을 사용하면 지역 제한을 해제해 해외에서도 한국 인터넷 서비스를 이용할 수 있다. 따라서 해외에서도 안전하고 편리하게 인터넷을 이용할 수 있다. 빠르고 안전한 유료 VPN, 서프샤크 VPN ⓒ Surfshark 뛰어난 보안 서프샤크 VPN은 강력한 암호화 기술을 사용하여 사용자의 인터넷 연결을 안전하게 보호한다. 이는 사용자의 개인 정보와 데이터를 보호하고 외부 공격으로부터 사용자를 보호하는 데 도움이 된다. 다양한 서버 위치 서프샤크 VPN은 전 세계 곳곳에 여러 서버가 위치하고 있어, 사용자가 지역 제한된 콘텐츠에 액세스할 수 있다. 해외에서도 로컬 콘텐츠에 손쉽게 접근할 수 있음은 물론이다. 속도와 대역폭 서프샤크 VPN은 빠른 속도와 무제한 대역폭을 제공하여 사용자가 원활한 인터넷 경험을 누릴 수 있도록 지원한다. 온라인 게임, 스트리밍, 다운로드 등 대역폭이 필요한 활동에 이상적이다. 다양한 플랫폼 지원 서프샤크 VPN은 다양한 플랫폼 및 디바이스에서 사용할 수 있다. 윈도우, 맥OS, iOS, 안드로이드 등 다양한 운영체제 및 디바이스에서 호환되어 사용자가 어디서나 안전한 인터넷을 즐길 수 있다. 디바이스 무제한 연결 서프샤크 VPN은 무제한 연결을 제공하여 사용자가 필요할 때 언제든지 디바이스의 갯수에 상관없이 VPN을 사용할 수 있다.