Computer >> 컴퓨터 >  >> 프로그래밍 >> Ruby

Ruby와 Sinatra로 나만의 링크 단축 서비스 만들기

Ruby 실력을 연습하면서 재미있는 작은 프로젝트를 찾고 계신다면, 정확히 올바른 곳에 오셨습니다.

오늘은 여러분과 함께 '링크 단축 서비스'를 처음부터 끝까지 직접 만들어 보겠습니다.

링크 단축 서비스란?

한 번쯤은 본 적이 있을 겁니다. 다음과 같은 형태의 짧은 링크 말이죠.

https://t.co/eKBRm2tTUF

이 URL에 접속하면 원래의 긴 URL로 자동으로 이동(리디렉션)됩니다.

그런데 어떻게 이런 일이 가능할까요?

핵심 아이디어는 아주 간단합니다. 위 예시의 eKBRm2tTUF 같은 짧은 코드를 데이터베이스에서 원본 URL과 미리 매칭해 두는 것입니다.

개념은 단순하지만, 해결해야 할 문제가 몇 가지 있습니다. 이 짧은 코드는 어떻게 생성할까요? 그리고 전체 URL과 어떻게 연결할까요?

지금부터 하나씩 알아보겠습니다!

첫걸음: Sinatra로 시작하기

이번 프로젝트에서는 Sinatra를 사용합니다. 별도의 설정 없이 바로 개발을 시작할 수 있기 때문입니다.

그리고 일반적인 SQL 데이터베이스 대신 조금 다른 방식을 사용해 볼 텐데요, 무엇인지는 조금 뒤에 공개하겠습니다. 🙂

먼저 초기 코드부터 살펴볼까요?

require 'sinatra'

get '/:url' do
  "The URL is #{params[:url]}"
end

get '/' do
  "Send a POST request to register a new URL."
end

post '/' do
  "New URL added: #{params[:url]}\n"
end

총 3개의 액션, 즉 라우트(route)로 구성된 아주 간단한 Sinatra 앱입니다.

애플리케이션에 접속하면 'POST 요청을 보내 새 URL을 등록하세요'라는 메시지가 표시됩니다.

어떻게 POST 요청을 보낼 수 있을까요?

Postman 같은 브라우저 확장 도구를 사용해도 좋지만, 이런 작업에는 curl을 추천합니다.

curl은 거의 모든 운영체제에서 설치할 수 있는 유용한 커맨드라인 도구로, 터미널에서 Sinatra 앱과 손쉽게 통신할 수 있습니다.

curl로 POST 요청 보내기

따라 하고 계신다면 Sinatra 앱이 실행 중이고, curl이 설치되어 있을 겁니다.

이제 다음과 같이 POST 요청을 보내 보세요.

curl localhost:4567 --data "url=rubyguides.com" -X POST

터미널에 'New URL added' 메시지가 출력되면 성공입니다!

다음 단계는 이 URL을 더 짧은 URL로 매핑하는 것입니다. 어떻게 하면 될까요?

URL 매핑하기

매핑 방법은 여러 가지가 있습니다. 무작위 문자열을 사용하거나, 해시 함수를 적용하거나, 특정 인코딩 방식을 활용하는 방법 등이죠.

여기서는 무작위 문자열 방식을 사용해 보겠습니다.

LETTERS = Array('a'..'z')

def generate_short_url
  Array.new(6) { LETTERS.sample }.join
end

이 코드는 소문자 알파벳 중에서 무작위로 6글자를 뽑아 짧은 코드를 생성합니다. 이렇게 만든 '짧은 코드'가 원본 URL과 단축 URL을 연결하는 열쇠가 됩니다.

다른 구현 방식이 궁금하다면 관련 영상도 함께 확인해 보세요.

그다음은 무엇일까요?

생성된 코드를 어딘가에 저장해 두어야, 사용자가 단축 URL에 접속했을 때 올바른 원본 주소로 리디렉션할 수 있습니다.

간단한 'NoSQL' 데이터베이스: PStore

이 프로젝트에는 최대한 단순한 저장 방식이 필요했습니다.

파일보다 단순한 게 있을까요? Ruby 표준 라이브러리에 포함된 PStore 클래스를 사용하면 파일 기반으로 데이터를 손쉽게 관리할 수 있습니다. 우리 앱처럼 작은 프로젝트에는 딱입니다.

코드를 살펴보겠습니다.

require 'pstore'

class ShortURL
  def self.save(code, original)
    store.transaction { |t| t[code] = original }
  end

  def self.read(code)
    store.transaction { |t| t[code] }
  end

  def self.store
    @store ||= PStore.new("short_urls.db")
  end
end

여기서 주목할 부분이 몇 가지 있습니다.

먼저 PStore 객체에 접근하기 위한 store 메서드가 있고, 데이터를 저장하는 save 메서드와 읽어오는 read 메서드가 있습니다.

PStore는 해시(hash)처럼 동작하지만, 한 가지 차이점이 있습니다. 모든 읽기·쓰기 작업은 반드시 transaction 블록 안에서 이루어져야 합니다.

이제 Sinatra 앱을 업데이트해서 ShortURL 클래스를 사용해 보겠습니다.

require 'sinatra'

get '/:url' do
  redirect "https://" + ShortURL.read(params[:url])
end

get '/' do
  "Send a POST request to register a new URL."
end

post '/' do
  code = generate_short_url
  ShortURL.save(code, params[:url])

  "New URL added: localhost:4567/#{code}\n"
end

이것으로 끝입니다! 이제 동작하는 링크 단축 서비스가 완성되었습니다.

꿀팁: shotgun 젬(gem)을 사용하면 코드를 수정할 때마다 Sinatra 앱이 자동으로 재시작되어 개발이 훨씬 편해집니다.

물론 아직 남은 과제가 있습니다.

  • 새 URL을 등록할 때마다 curl을 쓰지 않도록 웹 폼(form) 추가하기
  • 데이터베이스에 없는 URL을 요청했을 때 안내 메시지 표시하기
  • 중복 코드 검사를 통해 기존 URL이 덮어써지지 않도록 처리하기

이 부분들은 여러분의 숙제로 남겨두겠습니다. 🙂

마무리

이번 글에서는 Ruby, Sinatra, 그리고 PStore를 활용해 링크 단축 애플리케이션을 만드는 방법을 배웠습니다. 또한 HTTP 클라이언트인 curl로 POST 요청을 보내는 방법도 함께 익혔죠.

더 많은 사람들이 배울 수 있도록 이 글을 친구들에게 공유하는 것도 잊지 마세요!