티스토리 뷰

 

  • 소개

캐치딜 서비스는 2019년 10월부터 시작된 토이프로젝트의 일환으로, 같은 대학 주니어 대학생 3명이서 똘똘뭉쳐 제작된 프로젝트입니다.

캐치딜은 여러 플랫폼(뽐뿌, 클리앙 등)에 퍼져있는 핫딜특가 데이터를 Selenium 크롤링을 통해 데이터를 수집해서 보여주는 서비스입니다.

 

 

  • 서버 선택의 기로

캐치딜을 처음 개발을 할 때 때 있어서 어떤 플랫폼 서버를 써야할지 큰 기로에 빠지게 되었습니다.

저는 서버를 선택함에 있어서 아래 사항을 중점으로 고민을 하게 됩니다.

 

  1. 가격이 합리적인가? (최대한 Low Price였으면 좋겠다.)

  2. Ruby를 기본으로 지원해주는가? (캐치딜은 웹서버가 Ruby on Rails 기반입니다.)

  3. 내가 쉽게 다룰 수 있는가?

개인적으로 저는 아래 두 플랫폼을 유심히 봤습니다.

Ruby를 지원하는 서버 후보군

일단 국내 서버플랫폼을 유심히 보지 않은 이유는

 

1. 비합리적인 가격

 * 국내 서버 플랫폼은 대부분 트래픽에 따른 가격이 책정이 됩니다, 예를들어 [월 10000원/5GB 트래픽] 서버를 구매했지만 3GB밖에 안썼어도 돈은 만원씩 내야 합니다.

2. Ruby를 지원하는 호스팅 업체는 극히 드뭄

3. 무료지원 부족 (AWS는 프리티어 및 학생에게 있어선 크레딧을 지원해서 무료로 서비스를 이용할 수 있게 합니다.)

 

이 3가지 때문이었습니다.

 

 

  • 처음 첫 서버의 시작은 헤로쿠

그리하여 어째어째 저는 Heroku를 선택하게 되었습니다.

Heroku를 선택한 이유는 다음과 같습니다.

 

  1. 일단 기본 사용은 무료 (유료 서버 사용에 있어 Github Student Pack 인증 시 매 달 고정적으로 7달러, 최대 2년 지원)

  2. 서버 배포의 자동화

  3. Ruby 지원

처음엔 무난하게 헤로쿠를 잘 써왔습니다.

하지만 헤로쿠를 쓰면서 점점 뭔가 문제에 봉착하게 됩니다.

 

1. Scheduler Job 시간 설정 선택권

헤로쿠에서는 Schedule Time을 내 마음대로 못정한다!

헤로쿠에서는 터미널에 Cronjob이 지원되질 않다보니 별도로 Scheduler 모듈을 설치해서 써야하는 문제점이 있습니다.

 부록  Scheduler Background Job [클릭]

하지만 이 Scheduler는 시간을 서버 관리자가 마음대로 정하질 못한다는 문제점이 있습니다.

 

2. 무료 Heroku 서버에서는 여러 Scheduler Job 수행이 불가

Heroku에서 무료로 제공해주는 서버 같은 경우는 하나의 Job이 실행되는 도중에는 다른 Job이 실행되질 못합니다.

Scheduler Job 같은 경우에는 동일 시간대에 여러개의 Job이 돌아갈 확률이 많습니다.

Job 상황 예시
13시 10분 Job : 크롤링 Job Running (소요시간 : 약 5분)
13시 11분 Job : 30일이 지난 옛날 데이터 삭제

하지만 위와같은 상황이 발생할 경우 13시 11분에 실행될 Job은 안돌아간다는 문제점이 발생합니다.

 

캐치딜은 크롤링 기술이 핵심으로 사용되는 컨텐츠인 만큼 크롤러를 관리하는 스케쥴러의 역할이 큽니다. 하지만 위와같은 상황으로 인해 크롤러의 부재가 발생되서는 안됩니다.

 

그래서 이 때 어쩔 수 없이 Heroku의 유료서버 서비스를 사용하기 시작합니다.

(단, 학생혜택을 통해 최대한 무료로 쓰는 선으로!)

 

3. Database를 마음대로 설정 불가

Heroku는 프로젝트를 배포만 하면 헤로쿠 내부에서 모든 설정이 자동으로 이루어집니다. 하지만 이 것이 장점이자 단점이 될 줄은 꿈에도 몰랐던게, Database 설정에 대해서도 내 마음대로 설정을 못하고 Heroku 내에서 강제로 설정이 됩니다. 그렇다보니 외부에서 Heroku DB 내로 접근을 할 수 없다는 문제점이 있었습니다.

 

외부에서 헤로쿠 DB와 Remote Connect 하는 방법이 있을 것 같긴 하지만, 이미 이걸 생각해내기엔 늦은 상황이었습니다.

 

4. 비용

결정적으로 Heroku에서 다른 서비스로 서버를 옮기게 된 계기입니다.

앞서 말했다 싶이 Heroku는 Github Student Pack을 인증 시, 지금 사용하는 서비스가 유료 서비스일지라도 기본 호스팅 비용에 대해선 7달러 내에서는 무료로 지원해주는 지원제도가 있습니다.

 

확실히 서버에 대해서는 지원을 받았습니다,

그런데 여기서 문제가 터집니다.

Heroku Scheduler 모듈은 무료서버를 사용 시, 금액이 부가가 되진 않았습니다. 그렇다보니 저는 모듈 사용에 있어서도 무료로 사용할 수 있을 줄 알았습니다.

그런데 유료서버로 전환 이유 웬걸! 돈이 부과가 되고 있었습니다.

 

그래가지고 저는 고지서를 보자마자 충격을 받고 바로 AWS로 갈아타게 되었습니다..ㅠㅠ

 

 

  • AWS로 이전, 더 깊어지는 서버 최적화의 고민

일단 AWS를 선택하게 됨에 있어 얻게되는 이점은 다음과 같습니다.

 

  1. 대학 웹메일 인증 시, AWS Credit 100달러 지급 (Credit은 매 달 받는 청구서에서 극 일부 서비스를 제외하고 크레딧으로 대체 가능)

  2. 서버 사용금액에 있어사전에 서비스를 계약하는게 아닌, 일단 쓰고 나중에 서비스를 사용한 만큼 돈이 부과

  3. 개발에 필요한 다양한 기술의 AWS 서비스를 사용할 수 있음. (데이터 저장서버, 호스팅 서버, DB서버 등)

  4. 트래픽, 메모리, 용량 등 서버 스펙이 부족하다 싶으면 유동적으로 늘리거나 줄일 수 있음.

다음으로 이전하게 된 AWS는 과거에도 많이 써왔다 보니 큰 어려움 없이 쓸거라 믿어왔습니다.

일단 AWS에서 역시 최대한 저비용을 고려하여 EC2 서버는 t2.micro 서비스를 이용했습니다.

 

 

하지만.. 저스펙의 한계일까요...

AWS EC2에서 서버도 돌리고, 크롤링에 대해 Scheduler Job도 돌릴려 하니까 메모리 부족 문제가 생기게 됩니다..ㅠ

 

Selenium 크롤링에서 메모리를 많이 쓰이다 보니 발생되는 현상입니다..ㅠ

진짜 저 메모리 부족 문제를 해결할려고 Sidekiq(Queue Background Job) 기법도 써봤지만.. 아무것도 먹히지 않아서 어떻게 해야 할지에 대해 약 2일동안 고민에 빠지게 됩니다..

 

 

  • AWS Lamabda의 도입

Lambda 써볼레?

같이 개발하던 Front-End 형으로부터 람다를 써보는게 어떻냐는 제안을 받게 됩니다.

 

Catchdeal 소개 (렌더링) 페이지 및 Restful API 통신과 Database를 EC2가 맡고, 데이터베이스를 크롤링 수집하는 CronJob 작업에 대해서만 AWS Lambda를 돌리는쪽으로 기획을 구상하게 됩니다.

 

하지만 AWS Lamabda에 대해서는 제 개발인생에 있어 처음 도전하는 서비스이다 보니 처음부터 뭘 어떻게 배워야 할지 감이 안잡혔습니다.

더군다나 람다는 작년부터 Ruby 지원이 시작이 되었다 보니, Ruby 기반으로 작성된 AWS Lamabda 관련 자료도 거의 없다싶이 해서 너무 막막했었습니다.

 

레일즈 개발자 톡방에서도 조언을 구해보는데.. 다양한 답이 나왔습니다.

Ruby + DockerRuby on Jets라는 서버리스 프레임워크 라는 답을 얻게 되었는데, 저는 이 때 Ruby on Jets라는 웹프레임워크를 그냥 이름에 끌려서(?) 선택하게 되었습니다!

 

하지만 Ruby on Jets 같은 경우는 살짝 문제가 있었습니다. 한국어 자료가 너무 없다싶이 해서 (공부할 때 당시엔 당근마켓 연사자료 하나가 다였음) 첫 시작에서 살짝 버벅거리긴 했지만.. 다행히도 Rails와 거의 다를 바 없는 프레임워크여서 후에 배울땐 다행히도 잘 배울 수 있었습니다.

더군다나 직접 Ruby on Jets를 개발하신분이 친절하게 영어판으로 Document 자료를 다 만들어주신 덕분에 해당 프레임워크를 큰 틀 선에서 배우는데에도 한 3-5일 밖에 안걸린 것 같습니다.

 

Ruby on Jets 같은 경우는 AWS Lamabda로 프로젝트 배포에 있어 모든 설정을 자동으로 해주는 정말 매력적인 서버리스 프레임워크였습니다. 그렇다보니 혼자서 노가다를 하면서 설정할 필요 없이, 단순히 명령어 한 줄 만으로 AWS Lambda 내 모든 설정이 자동으로 이루어져서 큰 배움 없이 정말 편리하게 개발을 할 수 있었습니다.

 

이제 한 3-5일 정도 배우고 난 뒤, 크롤링 작업에 대해 AWS Lambda로 분리를 해서 사용해보니 이제는 EC2 서버에 메모리 부족 없이 쾌적하게 잘 돌아가는것이 확인되었습니다.

 

그리고 이 좋은건 저만 몰래 알 순 없는법! 마침 한국에 Ruby on Jets 자료도 없다싶이 해가지고 열심히 헤딩해서 알아낸 지식, 알짜베기 지식을 블로그에 작성해냈습니다.

 

 관련 개발지식 연결고리 

1. Ruby on Jets : 소개

2. Ruby on Jets : Lambda 스케쥴링 Job

3. Ruby on Jets : AWS Lambda에서 Selenium 크롤링

4. Ruby on Rails : 다른 AWS EC2 서버 내의 Database와 Remote Connect 하기

5. AWS Lambda : 계층(Layer)의 이해

6. Ruby on Jets : 환경변수 등록

7. Ruby on Jets : AWS Lambda 배포

 

또한 AWS Lambda 같은 경우는 24시간 서버가 돌아가는게 아닌, 제가 시간만 정하면 크롤링 작업이 자동적으로 돌아갈 수 있게 하고, 작업이 돌아가는데 할애된 Time/Memory에 대해서만 비용이 부과되는 개념이라 비용적으로서도 너무 친절했습니다!

 

 

  • 앞으로 풀어나가야 할 과제

1. AWS Lambda 공부 및 효율적인 비용부과 Way

AWS Lambda 같은 경우는 제가 스스로 0부터 셋팅을 해본 경험이 없다 보니, 내부 구조에 대해서도 계속 공부하면서 더 알아가봐야 할 것 같습니다. AWS Lambda에서 자체적으로 제공하는 기능 중, 제가 눈치채지 못한 숨겨진 편리한 기능이 있을 수도 있고, 그 속에서 비용이 어느 부분에서 올라가거나 내려가는지에 대해 공부하는게 최대의 관건 같습니다.

 

잘 모르고 AWS Lambda를 사용하다간, 비용이 훅 간다!

저번 1월달 요금고지서를 보니까 제가 뭣도 모르고 AWS Lambda를 이것저것 만지고, 너무 자주 Job을 돌리는 바람에 엄청난 비용이 나오게 되었습니다..ㅠㅠ (비용은 다행히 Credit으로 대체되었습니다...)

 

2. Ruby on Jets, 널 더 알고싶어.

Ruby on Jets는 Ruby on Rails와 비슷하면서도 뭔가 다른게 참 많은게, Jets에서 Gem을 설치하면 안돌아가는것도 몇 개 있습니다.

또, Jets에서는 코드가 잘 돌아가지만 AWS Lambda에서는 안돌아가는 코드가 있기도 합니다.

(이것때문에 30분을 고생함..)

@hash = {"user_0"=>{"userId"=>"23", "bookmarkCount"=>6}, "user_1"=>{"userID"=>"42", "bookmarkCount"=>3}}

## Ruby on Jets에서는 정상적으로 돌아가나, AWS Lambda에서는 안돌아감.
@hash.each_with_index do |userData, index|
  puts userData["user_#{index}"]
end

## 다음과 같이 수정 시, Ruby on Jets/AWS Lambda 둘 다 정상 작동.
@hash.values.each do |userData|
  puts userData["userId"]
end

 

그리고 계속 파고들면 파고들수록 뭔가 AWS Lambda를 자동으로 쉽게 설정해주는 기능들이 많이 익혀지게 되더라고요. 이런 숨겨진 기능에 대해서도 계속해나아가서 알아봐야 할 것 같습니다!

 

 

  • 앞으로의 서버 분리 : 더더더 서버분리

 부록  Scaling to 100k Users

Server Ver 1.

Server Ver. 1

극 초창기에 운용되었던 과거의 서버 운영방식입니다.

처음에는 모든 기능을 AWS EC2에 때려박은 채로 시작되었습니다.

 

하지만 앞서 얘기했다 싶이 Cron Job 활용에 있어 메모리 부족 문제가 발생하게 되어 위와같은 방식은 비효율적이란걸 깨닫게 됩니다.

 

물론 EC2 서버의 하드웨어 성능(메모리, CPU 등)을 높이면 되긴 하나, 그래도 다른 효율적인 선택지가 있는 현 시점에서는 정말 비효율적입니다.

 

Server Ver 2.

 

Server Ver. 2

현재(2020. 2. 11 기준) 캐치딜의 서버 상태입니다. 현재는 캐치딜이 스케쥴러+Crawl JobDatabase+웹서버 로 분리되어 운영되고 있습니다.

하지만 캐치딜은 적은 트래픽을 대상으로 서버를 돌릴 때 있어선 위 상태의 구조도 나쁘진 않지만, 나중에 트래픽이 증설되게 되면 분명 서버 운영에 있어 한계에 다다를 것 같습니다.

 

Server Ver 3.

Server Ver. 3

앞으로 이상적으로 바라보고있는 다음단계의 서버 구조입니다.

이제 캐치딜을 소개하는 인트로페이지와 Rest API를 분리를 하는게 다음 서버구조의 목표입니다.

 

사실 API 통신 및 캐치딜 소개 페이지를 보여줌에 있어선 서버가 24시간 동안 살아있을 필요 또한 없습니다.

그렇다보니 서버에 있어서도 현재 24시간 운용이 되는 EC2 서버 방식에서 서버에 접근했을 때만 잠깐 서버가 켜지는 AWS Lambda로 이동할까 고민중에 있습니다.

 

AWS EC2 VS RDS (출처 : BENSPIN GLOBAL blog)

현재 EC2로 Database 서버를 돌리는 것에 대해서 주변에서 부정적인 반응을 보이는데, 저도 마음같아서는 RDS로 바꾸고 싶습니다..ㅠ 하지만 RDS는 아무래도 서버의 모든 관리(백업, scale, 관제 등)에 있어 AWS에서 자동화 지원(Paas)을 해주다보니 이러한 장점 덕분에 EC2로 서버를 돌리는 것 보다 비싼게 현실입니다..

 

현재 RDS를 돌리기엔 아직 서버의 관리까지 못맡을정도로 바쁜 편도 아니고, 백업이야 제가 좀 고생은 하지만 Rails 내 Gem(모듈)을 통해 주기적으로 할 수 있고, 결정적으로 비용적으로 큰 부담 때문에 아직 RDS가 아닌 EC2를 통해 서버를 돌리고 있습니다.

하지만 나중에 서버도 크게 확장되고, 백엔드 관리에 있어 서버의 영역을 제 스스로 관리하기에 있어 힘들 경우 AWS EC2 → AWS RDS로 갈아타는 고민은 해봐야 할 것 같습니다.

 EC2 VS RDS 부록 
AWS RDS vs EC2 차이점, 간단히 파악하기
AWS EC2/RDS 상용 Database(Oralce) 사용 시 정리

 

Server Ver. 4

Server Ver. 4

누구나 서버에 빠른 요청을 하게 될 시, 빠른 응답을 원합니다.

사실 지금도 괜찮은 반응 속도이긴 하나, 더 빠른 응답은 과연 얼마나 빠를지 궁금하고, 욕심이 생기더라고요.

 

서버도 서버이지만, 내부 퍼포먼스에 있어서도 Redis 와 같은 캐싱 기능을 도입하는 부분에 대해서도 새로 배워나가고, 이를 적용해야 하는게 제게있어 또 하나의 과제가 될 것 같습니다.

 

 

  • 내부 코드의 효율적인 관리

개인적으로 내부 코드에 대해서도 크게 신경써야 한다고 생각이 됩니다.

그 대표적인 케이스로서는 바로 SQL N+1 입니다.

SQL N+1 문제

위 상황은 유저 앞으로 보내진 푸쉬알람 리스트를 조회하는 API 통신 과정입니다.

하지만 좌측 SQL Query를보면.... 정말 불편합니다. 뭔가 쓸데없이 계속 Select 구문이 호출되고 있습니다.

위 현상이 바로 SQL N+1 의 대표적인 예시입니다.

과거에 저도 왜 저렇게 코드를 짰는지 모르겠는데 어느 날 우연히 저렇게 코드를 잘못짰단 것을 확인하게 됩니다.

 

위와같은 SQL N+1은 테이블 내 데이터가 적을때야 크게 상관은 없을텐데, 만약 데이터가 몇천개, 아니 몇 만개를 조회해야 한다면 위와같은 방식은 너무 비정상적이면서도 과도한 내부 탐색 퍼포먼스로 인해 서버가 다운될 우려가 있습니다.

 

위와같은 문제에 대한 해결법은 테이블 조인입니다.

 부록  Ruby on Rails : Table JOIN

테이블 조인은 2개 이상의 테이블 내 공통점이 있는 에트리뷰트(컬럼)를 기준으로 하여 2개의 이상의 테이블을 하나로 합친 후 결과를 보여주는 방식입니다.

 

이 방법을 이용하면 위처럼 반복적인 테이블 조회과정 없이 단 한번의 과정으로 조건에 맞는 데이터의 결과를 가져올 수 있습니다.

 

SQL N+1이 완화된 Query

이제 위 방법을 이용하면 아까는 9.0ms 이상 걸리던 시간이 4.1ms 로 크게 단축됩니다.

이러한 케이스처럼 내부 코드 알고리즘도 크게 신경쓰는것도 하나의 과제입니다.

 

그리고 더 나아가, Table View에 대해서도 새로이 공부해나가야 할 것 같습니다.

 부록 
[DB기초] 뷰(View)란 무엇인가? + 간단한 예제
View vs Join

Table View에 있어서도 데이터 탐색속도가 좋다는 얘기를 들어가지고 아직 확정적으로 View를 할지 결정을 하진 않았지만, View VS Join에 대해 좀 더 알아보고, View가 성능에 더 좋을 것 같다 싶으면 해당 부분에 대해서도 고민해봐야 할 것 같습니다.

 

 

  • 마무리

서버는 정말 민감하면서도 쉽지 않은 친구인 것 같습니다.

일단 어느 플랫폼이 합리적인 가격인지를 알아야하는건 기본이고, 또한 서버 내부에서도 언제 과부화가 될지 모르니.. 항상 경계해야 할 녀석입니다. 그리고 서버가 죽지 않도록 내부코드 역시 효율적으로 설계를 해야하면서도, 서버 아키텍쳐를 설계함에 있어서 현재의 상황(비용, 현재의 트래픽 상황 등)에 고려해서 잘 설계를 해야 하는것도 하나의 과제입니다. (이래서 마이크로서비스 라는게 나왔나 봅니다.)

 

또한 서버는 컨텐츠의 심장이기도 하니 언제든지 로그를 체크하면서 예의주시를 해야 합니다.

세상은 계속해서 서버의 효율적인 관리를 위해 서버 로그를 집계해주는 Data Dog 같은 툴들도 많이 나오고 있습니다.

후에 있어선 이런 관리툴에 대한 공부도 자세히 해나가야 할 것 같습니다.

댓글
  • 프로필사진 ㅁㄴㅇ 안녕하세요, 질문이있는데 람다 비용이 많이나오셨다고했는데 왜 NAT gateway hour 이부분도 흰색으로 강조표시를하신건가요??
    람다랑 같이 엮여있는건가요?
    2020.02.06 10:26
  • 프로필사진 마음 따뜻한 개발자, 나른한 하루 안녕하세요! 댓글 남겨주셔서 감사합니다!
    원래 처음에 람다를 쓸 때 있어서 DB와의 통신에 있어 보안을 고려하고자 고정IP 사용을 위해 NAT Gateway(VPC)를 사용하려 했었습니다.

    그런데.. 이게 가격이 너무 쌔고, 또 굳이 고정IP를 쓸 필요가 없어가지고 그냥 안쓰는쪽으로 했습니다ㅠ

    감사합니다!
    2020.02.06 10:44 신고
  • 프로필사진 팽펑 좋은 글 감사합니다! 한 가지 궁금한 점이 있는데요, 처음에 어떻게 프로젝트를 기획하게 되신건지 알고 싶습니다.
    핫딜을 모아주는 서비스가 기존에 없는 것을 보고 "아 이거 되겠다"고 접근하게 되신건가요? 아니면 기존에 비슷한 서비스가 있지만 이러이러한 부분에서 "좀 더 좋은 서비스를 제시할 수 있겠다"고 생각하여 시작하게 되신건가요? 혹은 다른 이유인가요? 너무 궁금합니다 !! :)
    2020.02.14 08:58 신고
  • 프로필사진 마음 따뜻한 개발자, 나른한 하루 안녕하세요! 제가 기획자가 아니여서 자세히 답변드리긴 어려우나, 기획자분께 여쭤본 결과 처음에는 팽펑님께 말씀하신 전자의 방향으로 진행이 되었으나, 나중에 알고보니 이미 비슷한 컨텐츠가 있단걸 알게되었습니다! 하지만 똑같은 컨텐츠일지라도 좀 더 편의기능을 늘리는쪽을 공략함으로서 후자의 방향으로 나아가게 되었습니다!

    감사합니다 :D
    2020.02.14 11:33 신고
  • 프로필사진 -둘기 잘읽었습니다 ㅎㅎ 2020.02.18 10:41 신고
  • 프로필사진 마음 따뜻한 개발자, 나른한 하루 헣 안녕하세요! 부족한 글 읽어주셔서 감사합니다! 2020.02.18 21:37 신고
댓글쓰기 폼
공지사항
Total
14,757
Today
19
Yesterday
77
링크
TAG
more
«   2020/02   »
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
글 보관함