read

지난 10년간 웹 개발 환경은 비약적으로 발전했다. 1990~2000년대 초반에는 PHP 등이 널리 쓰이다가, 2000년 초중반부터 엔터프라이즈 환경을 중심으로 Java 기반의 프레임워크들이 등장하기 시작했다. Struts, Spring 등의 ‘웹 프레임워크’가 등장했고, iBatis, Hibernate 등의 ORM 도구들이 등장하면서 많은 개발자들을 SQL로부터 (어느 정도) 해방시켜주었다.

2000년대 중후반에는 Ruby on Rails가 등장하여 웹 프레임워크의 혁신을 이끌었고, 비슷한 시기에 언어별로 유사한 웹 프레임워크들이 우후죽순 등장했다. Python에서는 TurboGear, Django 등이 등장했고, 웹용 언어의 큰 형님인 PHP도 CakePHP을 위시하여 최근의 Symfony, Laravel 같은 프레임워크들을 보유하게 되었다.

Gmail의 성공적인 개발로 Ajax가 주목받기 시작했고, Javascript가 점점 중요한 역할을 차지하게 되었다. SPA가 유행하면서 Backbone.js, Angular.js, Ember.js 등 여러 클라이언트 프레임워크들도 나오기 시작했고, Node.js의 등장으로 서버와 클라이언트를 동일한 언어로 작성하는게 가능해졌다.

개발언어 이외에도, 코드 변경 관리 도구는 CVS/SVN에서 Git, Mercurial 등의 DCVS 도구로 중심 축이 이동했고, DevOps가 중요하게 여겨지면서 Chef, Puppet, Ansible 등의 도구들도 주목을 받기 시작했다. 아주 최근에는 Docker를 중심으로 컨테이너 기반의 배포도 새 영역을 구축해 나가고 있고, MS는 공격적으로 Docker 기반 가상화 기업들을 인수하고 있다.

모두 10여년 사이에 일어난 변화다.

실제로 OGQ에서도 Python/Django를 사용하고, 코드 저장소는 Git/Bitbucket을 사용하며, Chef를 사용하는 AWS Opsworks를 통해 서버들을 관리하여 접속량에 따라 auto-scaling을 수행한다. Redis를 캐시 서버로 사용하고, RabbitMQ를 message queue로 사용한다. 당연히 웹서버는 Apache가 아닌 Nginx를 사용하고, 서버 모니터링은 AWS CloudWatch를 사용해서 관찰한다. 서버에서 500번대 에러가 발생하면 stacktrace와 함께 메일이 발송되어 어떤 오류인지 즉각적으로 파악할 수 있고, 특정 수치 이상으로 오류량이 많아지면 메신저로 알람을 받는다.

그런데, 한국의 소위 홈페이지 외주 제작 현장에서는 이러한 변화가 별로 감지되지 않는다. 거의 10년 전 수준에서 머무르고 있는 것 같다. 아직도 홈페이지 하면 게시판(BBS)을 이야기하는 경우도 있고, 좀 낫다 싶은 곳이 워드프레스(Wordpress)를 사용하는 정도인 것 같다.

개발 언어를 물어보면 90% 이상이 PHP이고, 프레임웤을 사용하느냐, 소스코드 형상관리를 사용하냐 물어보면 프레임웤은 사용하지 않고 소스코드 형상관리도 하지 않는다고 한다.

실제 예로, 모 협회에서 신규 서비스를 런칭하려고 하는데, 개발 외주를 발주하는데 도움을 준 적이 있다. 그래서 간단한 Use-case와 Wireframe을 그려서 기획에 대한 이해를 돕고, 기술적으로 기존 협회 홈페이지에서 아쉬웠던 점들을 기재했었다. 그리고 업체 인터뷰날 아침에, 그냥 기술적인 요구사항들만 덜렁 써놓으면 그 맥락이나 필요성에 공감하지 못할까 싶어서 그 의도와 배경을 설명한 글을 적어서 메일로 미리 보냈다.

요약하면 아래 몇 가지를 요구했다.

  1. 개발 과정에 Git을 사용할 것
  2. 실 서비스에 배포할 때도 Git 저장소에서 내려받게 할 것
  3. 지속적 배포를 할 것
  4. (Optional) 배포 자동화 스크립트 (Chef/Puppet 등) 제작해주면 금상첨화. 하지만 어려울 것 같으니 안해줘도 할 수 없음.
  5. CDN 사용에 대해 개발시 고려해줄 것 (리소스 URL을 설정으로 지정할 수 있도록 변수화 하는 등)
  6. SQL Injection, CSRF, XSS 등, 기본적인 보안 위협에 대해 고려해주고, 비밀번호 저장 등에 bcrypt 등 고급 암호화를 사용할 것
  7. 코드와 데이터가 분리되게 할 것. 같은 디렉토리에 섞여서 뭐가 코드 디렉토리이고 뭐가 데이터 디렉토리인지 분간이 안되는건 피할 것

사실 5~7은 내가 주로 사용하는 Django를 염두에 두고 기재한 것들이었다. Django를 사용하면 기본적으로 제공하는 것들이다. Django 뿐만 아니라 잘 만들어진 웹 프레임워크는 아마도 저런 요소들을 잘 처리할 것이다.

이윽고 업체가 도착하고, 인터뷰가 진행되었다. 업체 대표, 개발실장, 기획실장이 참석했다.

처음 도착하고 나서, 업체 대표가 한 마디 했다. ‘그런데, 말씀하신 방법대로 개발을 하려면 너무 부담이 커서, 꼭 필요하지 않은 것들은 좀 뺐으면 좋겠네요.’

이런 저런 이야기가 오가고, 나와 개발실장 사이에 기술적인 질의 응답이 시작되었다. (Wording은 작년 일이라 정확치 않을 수 있다.)

  • P. 언어는 무엇을 사용할거냐.
  • I. ASP.NET을 사용할거다.
  • P. 발주 내용과는 다르지만, 좋다. 개발자가 손에 익은 도구를 사용하는게 중요하니까.
  • P. 내가 ASP.NET은 잘 모르지만, 그쪽도 NHibernate 같은 ORM 도구 같은게 있다고 들었다. ORM 도구는 사용할 계획인지? ORM을 사용하면 따로 ERD가 없어도 코드만 봐도 구조를 파악할 수 있는 점이 좋더라.
  • I. 사용하지 않을 계획이다. Visual Studio가 잘 되어있어서 개발하는데도 편리하고, ERD도 자동으로 생성해주니 문서 업데이트도 문제 없다.
  • P. 아쉽지만 그것도 좋다. 나에게는 베스트 프랙티스일지 몰라도 익숙치 않은 사람에게는 오히려 방해가 될 수 있으니, 빨리 개발할 수 있는 방법으로 하는게 좋겠다.
  • P. 개발 도구나 프레임워크는 좀 덜 중요하지만, 지속적인 배포는 꽤 중요한 요소이다. 1~2주에 한번씩은 주기적으로 테스트 서버에서 현재 개발된 서비스를 사용해볼 수 있도록 배포해줄 수 있는가?
  • I. 그렇게 하기는 어렵다. 계속 로컬에서 개발을 하다가, 완료가 되면 실 서버에 올리기 때문에, 그렇게 계속 올리는건 부담이 된다.
  • P. 그게 왜 어려운가? 배포 도구를 처음에만 셋팅해주면 될 것 같은데.
  • I. 하여튼 어렵다.
  • P. 음… 이건 정말 중요한 부분인데. 뭐 정 못하겠다면 어쩔 수 없지.

이런 식으로 내가 생각하기에 좋은 소프트웨어 개발 방식이라고 요구했던 항목 하나 하나들을 다 양보해나갔다. 어차피 최종 결과물을 잘 만들어내기 위한 도구나 환경들이기 때문에. 또 그들이야 홈페이지를 나보다 더 많이 개발해왔을테니, 내 방식을 고집하며 주장할 수는 없지 않은가.

그랬더니 업체 대표가 살짝 흥분하면서 그러더라. ‘그러면 앞으로는 이런 글 써서 보내지 마세요. 이런 뭐 서버가 수십대 늘어났다 줄어들었다 하느니 몇백만명에게 서비스 한다느니 말이예요. (말도 안되는 요구를 하고 말이야).’

잠깐 딴 생각을 하다가 문득 생각이 들어서 다시 개발실장에게 물어봤다.

  • P. 그런데 코드 변경 관리 도구는 뭘 쓰시나요? Visual Studio 쓰시니까 SourceSafe 같은걸 쓰시나요?
  • I. 부끄럽지만 코드 변경 관리 도구는 써본 적이 없습니다.
  • P. 네? 그러면 같이 개발하시는 분들하고는 코드를 어떻게 공유하시는데요?
  • I. 저 혼자 개발합니다.
  • P. 그러면 로컬에서 개발한 후에 서버로 올리실 때는 어떻게 하시는데요?
  • I. FTP로 올리지요.
  • P. 그러면 긴급히 실 서버에서 코드를 변경하거나 해야 할 때, 로컬의 코드 내용과 동기화를 하기 어려울텐데요?
  • I. 한 번 실 서버로 올리면 다시 로컬로 내리지 않습니다.
  • P. 네?? 보통 로컬에서 변경점을 수정하고 다시 서버로 올리지 않나요?
  • I. 일단 실 서버로 배포한 이후에는, 수정을 위한 코드 변경은 실 서버에서 합니다.
  • P. 네?? 실 서버에서 수정을 직접 한다고요? 물론 그럴 경우가 있긴 하죠. 하지만 항상 그렇게 하는건 좀… 그랬다가 잘못 고치면 어떻게 하죠? 장애가 나거나, 또는 옛날 코드로 되돌려야 할 때는요?
  • I. 그럴 일은 없도록 조심해서 수정합니다.

드디어 할 말을 잃었다. 아… 이건 스타일이 아니라 그냥 주먹구구이구나. 어떻게 실 서버에서 수정을 직접 하면서, 변경 이력도 남기지 않을 수 있는지. 나중에 대대적인 수정을 위해서 로컬에 코드를 가져와야 할 때는 어떻게 할 것인지.

알거나 할 수 있지만 이 경우에는 필요하지 않기 때문에 다른 기술을 선택하는 것과, 몰라서 못 쓰는 것은 차이가 크다. 웹 분야에서 지난 10여년간 이루어진 눈부신 발전을 이토록 무시할 수 있다니.

하긴, 아는 후배가 참여한 모 대형 SI 프로젝트에서는, 업계 5위 안에 드는 대형 SI 회사에서 코드 변경 관리 도구로 SourceSafe을 나눠줬다고 하더라. 그걸 쓰라고. Visual Studio 옛날 버전의 라이센스를 가지고 있기 때문에, 어쩔 수 없이 SourceSafe을 써야 한다고. SourceSafe은 MS 본사에서도 더 이상 사용하지 않는 도구일 뿐더러, 써본 사람은 알겠지만, SourceSafe은 배타적 쓰기 락을 채택하고 있어서, 누군가 코드를 체크아웃하면, 그 사람이 다시 체크인하기 전까지는 아무도 그 코드를 수정할 수 없다. 실제로 그 프로젝트에서도 누군가 코드를 체크아웃해놓고 체크인을 안해서 아무도 그 파일을 수정할 수 없게 되자, 사람들이 file_2, file_3 등 다른 파일들을 만들어서 저장하곤 했다더라. 코드 변경 관리가 제대로 안된 것이지.

이틀 전에 회사 일로 미팅했던 업체도 크게 다르지 않아보인다. PHP를 사용하는데, 웹 프레임워크를 사용하지 않는단다. 코드 변경 관리 도구는 무엇을 사용하는지 두고 볼 일이다.

개발 용역이라는 것 자체가 가지고 있는 한계인가? 스스로 작성한 코드로 인해 스스로가 고통스러워본 경험이 없어서 그런 것일까? 개발과 배포와 운영이 함께 고려되어야만 운영하기 좋고 배포하기 좋은 코드를 작성하게 마련이다. 어쩌면 운영할 때 어떤 문제점이나 애로사항이 있는지 앞으로도 계속 모를 수도 있겠다. 하지만 발주를 내는 사람 입장에서는 시스템을 계속 사용할 당사자인 바, 운영과 유지보수에 대해서도 고려하여 개발하는 것이 더 좋은 것이다.

아래는 내가 미팅했던 업체에게 보냈던 실제 메일 본문이다. 과연 그 업체 대표에게 ‘이런 식의 글 써서 보내지 마세요’라고 욕먹을 성질의 글인 것인지…

안녕하세요, ooo입니다.

저는 이 서비스를 기획하는데 참여해왔고, 개발자이기 때문에 이후 서비스의 개발을 진행하는데 참고하실만한 내용들을 말씀드리려 합니다. 개발에 직접 참여하지는 않을 것이고, 개발을 직접 진행하시는 과정에서 미리 알아두시면 좋을만한 내용이나, 유지보수 측면에서 고려되었으면 하는 점들을 말씀드리고자 합니다.

제가 개인적으로 경험해왔던 것들을 바탕으로, 미리 고려해놓으면 개발 이후에도 계속 유지보수 작업을 해나갈 때 필요를 반영하기가 쉬울 것으로 기대합니다.

개발에서 제가 잘 아는 분야도 있을테고 잘 알지 못하는 분야도 있을겁니다. 그리고 아무래도 제가 제안할 것들은 제가 경험한 상황들에 기반한 것일테니, 모든 경우에 적용되기 어려운 특수성도 있을것으로 생각합니다. 고려사항들을 읽어가실 때 감안하시면 좋을 것 같습니다.

일단 웹서비스 개발과 관련된 제 이력을 간단히 말씀드립니다.

  1. 기존에 작성된 제로보드 기반(Linux+PHP+MySQL)의 모 NGO 홈페이지의 코드 리팩토링 및 유지보수. 1개월간.
  2. 기존에 작성된 온라인 서베이 웹서비스(Windows+Java Servlet+JSP+MSSQL)에 기능 추가 및 유지보수/운영가동. 2년간.
  3. 모바일 배경화면 서비스를 위한 Backend API 웹서비스(Linux+Python Django+MySQL) 개발 및 운영. 5년간. 현재까지.

웹과 관련된 경험은 이렇게 크게 세 경우가 있는 것 같네요. 보시다시피 ASP.NET는 경험이 없어서 잘 모릅니다.

1,2번은 다른 사람이 작성하고 오랜기간 운영되어 온 코드를 넘겨받은 경우였고, 코드가 어떻게 엉망이 되어가는지를 잘 볼 수 있는 경험이었습니다.

3번은 현재까지 담당하고 있는 업무이고, DAU가 약 150만명 정도 되는 서비스입니다. 서비스를 scale-out 해나가기 위해서 서버단에서 무엇을 뒷받침해줘야 하는지 경험할 수 있었습니다.

1~3의 경험 모두 외주 개발 용역이 아닌 In-house 개발이었다는 점도 있네요.

실제 개발 측면에서 다음과 같은 부분들이 고려되면 좋을 것 같습니다.

코드 관리

전에 근무하던 빅데이터 분석 업체에서 이미 작성된 온라인 서베이 웹서비스를 넘겨받아 설문 유형 등의 기능을 추가하는 작업을 했었습니다.

당시 서비스는 Servlet+JSP+MSSQL로 작성되어 있었습니다. 코드 저장소에 웹서비스 소스가 있기는 했지만, 이전 작업자들이 실서버에서 직접 수정작업을 일부 진행해온 상태라 코드 저장소의 코드가 최종 코드가 아니었고, 서버에는 컴파일된 war, jar(+.class), jsp 파일등만 존재하는 상태였습니다. 그래서 일부 수정이 필요하면 선택의 여지가 없이 실서버에서 직접 수정하고 확인을 해야 하는 환경이었습니다. 수정에 드는 시간도 오래 걸릴뿐더러 운영상에도 위험이 존재하는 방식이었습니다. 그래서 서버에 배포되어 있는 최종 코드를 decompile 등의 과정을 거쳐 로컬 Eclipse 환경으로 적재하고 코드 저장소에 최종 코드를 복원하는 작업을 가장 우선적으로 진행했습니다.

대체로 웹서비스를 처음 개발할 때는 로컬에서 개발을 진행하지만, 실 서버에 배포할 때는 압축을 해서 업로드를 한다던지 하는 방식으로 작업을 많이 하는 것 같습니다. 제가 유지보수로 개발을 하기 위해 서버를 넘겨받았을 때나, 협회 홈페이지의 이전 과정에서의 경험을 돌아보았을 때도 같은 방식이었습니다.

그래서 현재 운영중인 웹서비스를 개발할 때는, Git 저장소에 코드를 저장해놓고, 실서버에서도 Git에서 직접 코드를 내려받도록 해놓았습니다. 그래서 혹 실서버에서 코드 변경이 일어나더라도 변경사항을 Git 저장소에 다시 반영할 수 있었습니다. 그리고 로컬 작업 컴퓨터에도 최신 코드가 유지될 수 있었습니다.

간혹 외주 업체에 SVN이나 Git의 사용을 요청하는 경우, 개발 과정에서는 형상관리를 사용하지 않다가 최종 코드를 한번에 반영(commit)하는 경우도 있었는데, 그보다는 실제 개발 과정에서 조금씩 사용해나가는 것이 좋겠습니다.

본 개발에서도 Git으로 개발 코드의 형상관리를 해주시고, 실 서비스 서버에서도 형상관리를 유지해주시면 좋을 것 같습니다.

ORM 사용

유지보수 과정에서 많이 겪었던 부분이, ERD가 없다는 점이었습니다. DB의 구조를 파악하기가 어려웠고, 코드에 모여있는 SQL문이나 DAO 등을 참고하여 재구성해야 했습니다. 그래서 테이블이나 컬럼을 추가해야 할 때, 나중에 알고 보면 후회되는 위치에 추가를 한다던지 하는 문제점들이 있었습니다. 그리고 테이블간의 관계가 머리에 잡혀있지 않으면 join 쿼리는 가능하면 피하게 되었습니다.

SQL Mapper 유형의 ORM 툴이 아닌, hibernate 같은 완전 관리형 ORM 도구의 경우에는 모델 클래스가 변경되면 그에 맞게 DB를 변경할 수 있는 SQL문을 생성하는 등, DB migration도 이력 관리를 할 수 있는 이점도 있겠습니다. DDL문을 직접 다루지 않을 수 있으면, 테이블 생성 및 관리에 대한 부담이 적어져 자연스럽게 DB 정규화가 잘 이루어진 테이블 설계를 하게되는 경향도 있었습니다. 그렇지 않은 경우, 특히 현재 협회 홈페이지의 구성원별 프로필 정보의 경우, 회원 정보가 그 성격에 따라 몇 개의 테이블로 분할될 수 있어보이는데 한 개의 테이블에 20여개의 컬럼들이 존재하게 되는 등, 이미 만들어진 테이블에 그냥 덧붙이는 일이 종종 발생하는 것 같습니다.

ASP.NET에서 DB를 어떻게 다루는지는 모르겠지만, ORM 사용이 가능하다면 가급적 ORM을 사용하면 좋을 것 같습니다.

CDN 사용

서비스가 실제로 운영되면서 이미지나 동영상, 음성 파일 등의 비중이 어떻게 될지는 모르겠지만, 나중에 필요시에 CDN을 손쉽게 적용할 수 있도록 해주시면 좋겠습니다. 구체적으로는, static resource들에 대한 URL을 설정파일에서 변수로 지정할 수 있게 처리해주시면 좋겠습니다.

보안

사용자 암호를 bcrypt 등, 기본 md5 이상으로 암호화해주시면 좋겠습니다. 그리고 CSRF, XSS, SQL Injection 등의 공격에 대한 대응도 해주시면 좋겠습니다. 그리고 현재 협회 홈페이지를 보면 암호가 HTTP를 통해 평문으로 전송되는데, HTTPS 사용해주시면 좋겠습니다.

배포 자동화 및 백업

제가 현재 관리중인 웹서비스는 WAS(Web application server: Nginx+uWSGI)가 peak time에는 20대, idle time에는 10대가 가동됩니다. AWS상에 Chef를 사용하여 auto-scaling 설정이 되어있습니다. 접속이 몰리는 시간대에는 새 EC2 인스턴스를 생성하여 Git에서 코드를 받아오고 웹서버와 애플리케이션 서버 등의 설정을 마친 후에 로드밸런서에 추가하는 작업이 Chef 스크립트를 통해 자동으로 이루어집니다. 덕분에 저를 포함한 단 2명이 처음부터 현재까지 개발과 운영을 담당해올 수 있었습니다.

협회의 이번 서비스는 트래픽이 auto-scaling이 필요할 정도로 많을 것 같지는 않지만, 서버를 이전한다던지 새로운 개발자가 개발 서버를 셋팅한다던지 하는 경우에 유용할 것으로 보입니다. 또한 서버의 장애를 대비해 백업을 해놓는 경우가 있지만, 데이터나 DB를 백업하는 경우가 대부분이고 새로운 시스템을 신속하게 재구성하는 대비는 되어 있지 않은 경우가 많은 것 같습니다. 최근에는 PHP 조차도 Deployer, Rocketeer 등의 설치 자동화 도구들이 등장하고 있는 것으로 보아 배포 자동화가 점점 보편적인 추세가 되어가는 것 같습니다.

본 개발에서도 배포 자동화 (코드를 받아오고 웹서버, 애플리케이션 서버를 설정하여 서비스가 가능한 상태로 만들어주는) 도구가 사용되면 유용할 것 같습니다. 특히 스크립트 중에 백업과 복원에 대한 내용도 포함해놓으면 이후 장애 복구나 서버 이전시에 유용하게 사용할 수 있을 것 같습니다.

다만, 제가 보기에는 매우 중요한 작업은 아니면서 스크립트 작성에 손이 많이 갈 수도 있을 것 같으니, 가능한 경우에만 진행해주시면 될 것 같습니다. 하지만 이후에 자동화를 염두에 두고 개발을 진행한 경우와 그렇지 않은 경우는 나중에 실제로 자동화를 하려고 할 때 차이가 발생할 것 같습니다.

Blog Logo

Jeongsoo, Park


Published

Image

오름직한 동산

Think globally, act locally

Back to Overview