O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

하드웨어 스타트업의 소프트웨어 이야기

어느날 우연히 스위처 소방수로 참여해서 2달 동안 수행한 일들을 공유합니다. 그 첫번재 이야기 ‘기본을 지키자’ 입니다.

전체를 리드하면서 업무를 진행해본 첫 경험이기도 했고, 유저가 증가하며 서비스되고 있는 프로젝트를 A to Z로 혼자 감당해본 첫 경험이기도 했습니다.

새로운 서버를 설계하고 개발하면서, 레거시 안정화 및 이슈 응대를 모두 병행하는게 쉬운 일은 아니었지만, 핑계대지 않고 하나하나 기본을 다져 보았습니다!

아직 갈길이 멀었지만, 성장해가는 아이오(스위처)의 소프트웨어 이야기를 하나씩 하나씩 풀어보려 합니다 ;)

  • Seja o primeiro a comentar

하드웨어 스타트업의 소프트웨어 이야기

  1. 1. 하드웨어 스타트업의 소프트웨어 이야기 첫번째 이야기, 기본을 지키자 박미정 mjpark03@switcher.co.kr mjpark03@gmail.com
  2. 2. Author 박미정 mjpark03@gmail.com / mjpark03@switcher.co.kr ● 스타트업을 사랑하는 개발자 ○ 코빗, 스케일체인, I/O(스위처) ● (주) 서버 개발 ● (부) 가끔 프론트엔드 (퍼블리셔 리스펙트), 가끔 보안 ● 시작은 대기업 개발자 ● 블로그: http://mjpark03.github.io/about/me ● 링크드인: https://kr.linkedin.com/in/mjpark03
  3. 3. 이 슬라이드는 하드웨어 스타트업인 I/O가 소프트웨어 회사로 함께 성장해가는 과정을 공유하여, 건강한 피드백을 수용하기 위한 목적으로 작성되었습니다. 많은 변화를 겪고 있는 과정이므로, 첫번째 이야기, 기본을 지키자 부터 공개하려 합니다. Intro
  4. 4. 4Before 스위처 소프트웨어 스택 ● Node.js 4.4.6, Express 4.13, Sequelize 3.23, JDK 1.8 ● MySQL 5.6.27, MongoDB 3.2 ● AWS ELB, Elastic Beanstalk ● Apache2, Tomcat7, Nginx
  5. 5. 5Before 스위처 서버 종류 ● 스위처 서버 ○ 스위처를 사용중이신 고객님들에게 스위처 정보, 결제 정보, 배송 정보 등을 제공 ● 생산 서버 ○ 직접 생산한 스위처를 제품으로 등록하고, 재고 관리 기능 등을 제공 ● 이벤트 서버 ○ 새로운 고객님들로부터 스위처 신청을 받고, 이벤트 기능을 제공
  6. 6. 6Before 어쩌다 제가 조인하게 되었냐하면.. 문제는 3차 이벤트 신청, 그 날 부터 시작되었습니다.
  7. 7. 7Before 어쩌다 제가 조인하게 되었냐하면.. 트래픽이 몰리면서 서버가 다운되기 시작했고, 고객님들에게 원활한 이벤트 신청 기능을 제공하지 못하였습니다. 더욱 큰 문제는, 이러한 문제를 고민하고 해결해나갈 개발자의 부재였습니다. 대표님은 베프였던 저에게 이러한 고민을 털어놓았고.. 그래서.. 그 때 부터.. 제가 조인하게 되었습니다! 평소 대표님과의 친분도 있었지만.. 어디가 문제인지도 모를만큼 문제 투성이었던 서버에 대한 호기심이 가장 컸습니다. 2주 2주 2주마다 이벤트(스위처) 신청 너에게 트래픽을 주겠어 ..
  8. 8. 8Before 그래서 제가 I/O에서 달성해야할 목표는 .. ● (잠시 누군가 빠르게 개발해 놓으시고 떠나신) 레거시 서버의 안정화 ● 새로운 서버 (일명 ‘클린서버') 설계 및 구축/개발
  9. 9. 9Before 조인 당시 상황은 .. ● 서버 개발자 0, 서버 인프라 관련 엔지니어 0 ● iOS 개발자 1명, Android 개발자 1명 혼자 레거시 서버를 분석하고, 혼자 레거시 서버의 안정화 및 새로운 서버를 구축하고 개발해야 하는 상황이었습니다. 여러모로 자원이 부족한 상황이었지만, 약 2달간, 기본을 지키기 위해 어떤 일들을 수행하고 변화시키려 했는지 공유하도록 하겠습니다. ※ 해당 편은 ‘기본을 지키자' 편으로써 ‘What’에 대한 이야기가 주를 이루고 있습니다. ※ 후속 편에서는, 고급(?) 편으로 ‘How’에 대한 이야기를 다룰 예정입니다.
  10. 10. 10 서버 / 인프라
  11. 11. 11 문제 #1 ● 하나의 물리적인 서버 안에 존재하는 3가지 서버 ○ 스위처 서버, 생산 서버, 이벤트 서버 ○ 3가지 프로세스가 서로 영향을 주고 받을 수 있는 물리적인 환경에 방치 서버 / 인프라 스위처 프로세스 생산 서버 이벤트 서버 너에게 영향을 주겠어 ... 너에게 영향을 주겠어 ...
  12. 12. 12 해결 #1 ● 아래와 같은 구조로 각 서비스 별, 서버 분리 ○ 각 서비스가 독립적인 서버로 운영 가능 서버 / 인프라 Don't put all your eggs in one basket
  13. 13. 13 문제 #2 ● 개발 서버의 부재 ○ 새로운 기능 추가 시, 운영 서버에 바로 배포함으로써 서버 환경에서의 테스트 기회 박탈 ○ 운영 중에, 새로운 기능에 대한 구멍 발견 빈번함 서버 / 인프라 local 나홀로 테스트 dev 멤버들 테스트 production 릴리즈
  14. 14. 14 해결 #2 ● 각 서비스 별 서버마다, 개발 서버와 운영 서버 분리 ○ 신규 기능 추가 시, 마케터 / PM / 앱개발자 모두 테스할 수 있는 환경 갖춤 서버 / 인프라
  15. 15. 15 문제 #3 ● AWS Security Group의 inbound/outbound PORT 활짝 오픈 ○ HTTP, HTTPS, SSH, Custom Port가 어디서든(Anywhere) 접속 가능하도록 오픈 ○ AWS EC2 Abuse Report 2번이나 받음 ○ 중국분들의 거침없는 침입 서버 / 인프라
  16. 16. 16 해결 #3 ● AWS Security Group의 inbound/outbound 정책 수립 ○ 각 inbound/outbound PORT 마다 source/destination을 특정 IP 대역 및 Security Group으로 한정 ○ 이제는 AWS EC2 Abuse Report를 받지 않음 (휴..) ○ AWS Security Group Doc 참고 서버 / 인프라
  17. 17. 17 문제 #4 ● Apache2 설정의 동시 접속 가능한 클라이언트 수 제한 ○ prefork 방식의 Multi Processing Module 사용 ○ maxRequestWorkers가 150으로 설정 ○ 이벤트 오픈시, 동시 접속자가 300명 이상 되는 상황에서 해당 설정으로 요청 지연 발생 ○ 신청을 기다린 고객님들을 화나게함(..) 서버 / 인프라
  18. 18. 18 해결 #4 ● Apache2 설정의 동시 접속 가능한 클라이언트 수 확장 ○ 8G (총 메모리) - 2G (시스템 기본 점유 메모리 + 서비스 프로세스 메모리) = 6G ○ 6G / 10M (Apache 1개의 Process 점유 메모리) = 약 600 ○ 여유있게 maxRequestWorkers 500 설정 ○ JMeter 동시 접속 성능테스트 결과, 1초 미만 달성 서버 / 인프라
  19. 19. 19 애플리케이션
  20. 20. 20 문제 #1 ● API Spec 규칙의 오용 ○ REST API 규칙을 잘못 사용하고 있었음 ○ ‘POST /mobile/product/{macaddress}/shareCode’ API가 shareCode를 생성하는 API가 아니고, 실제로 조회하는 API 였음 ○ APP 개발자 분들과 커뮤니케이션 하기 위해, 코드를 일일이 살펴봐야 하는 비용 발생 애플리케이션 박개발 김개발 ‘A’ API는 ‘A’ 기능을 하지 ‘A’ API는 ‘B’ 기능을 하는데
  21. 21. 21 해결 #1 ● REST API Best Practice에 따라 API Spec 변경 ○ ‘POST /mobile/product/shareCode’ ○ shareCode를(/mobile/products/shareCode, 리소스) 생성하는(POST, 행위) 기능 ○ APP 개발자 분들고 소통할 때, 하나의 API Spec을 두고 동상이몽 하는 일 제거 애플리케이션
  22. 22. 22애플리케이션 문제 #2 ● 예외 처리의 부재 ○ 예측 가능한 예외에 대한 처리가 없었음 ○ 예) 사용자에게 할당된 스위처(디바이스) 정보가 없을 때 서버 에러 메시지가 그대로 response로 전달 ○ 서버에서 적절한 에러 메시지를 전달해주지 않아서, APP에서 처리 못함 ○ 결국, 사용자에게 서버 에러 메시지가 그대로 전달 이럴수가..
  23. 23. 23 해결 #2 ● 공통 에러 코드 및 메시지를 문서화하고, 예측된 예외 처리 ○ 예측 가능한 예외에 대해, 문서화된 에러 코드 및 메시지와 일치하도록 response 전달 ○ APP 에서 사용자에게 예외에 대한 적절한 처리 가능 ○ APP 개발자 분들로부터 ‘서버 좀 봐주세요'가 아닌 ‘Switcher Does Not Exist 메시지 봐주세요’ 라는 구체적인 요청을 받을 수 있게됨 애플리케이션
  24. 24. 24 문제 #3 ● 무의미한 테스트 코드 ○ 테스트 독립성 부재 ○ 테스트 검증 데이터 미약 (커버리지 낮음) ○ 기존 레거시 서버의 로직을 이해하는데 도움을 받고자 테스트 코드를 확인하였으나, 무의미함 ○ 재사용 가능성 낮음 애플리케이션
  25. 25. 25 해결 #3 ● 새롭게 단위테스트 작성 ○ 함수 하나를 테스트 대상 ○ 함수 내의 논리별로 테스트 케이스 작성 ○ 테스트 케이스별 의존성 없도록, 독립적으로 작성 ○ 테스트 커버리지 90% 이상 ○ 테스트 코드를 통해, 함수의 의도록 파악할 수 있음 ○ 함수 로직 수정 시, 작성된 테스트 케이스를 수행하여 논리적 구멍을 발견 가능 애플리케이션
  26. 26. 26 문제 #4 ● 트랜잭션 처리의 부재 ○ 하나의 논리적 작업 단위 내에, 실패한 연산 존재 시 데이터 초기화의 부재 ○ 예) ‘스위처 반납 신청' 중, 송장번호 생성에 실패하여 완료되지 않았음에도 불구하고, 스위처의 상태는 ‘반납 중' ○ 고객님들은 반납 신청 완료된 줄 알고, 왜 택배 아저씨 안오시냐고 불만을 갖게 됨 애플리케이션 배송대기 배송완료 사용중 반납신청배송중 반납중 반납완료 요청 성공 요청 실패 그러거나 말거나 반납중 ..
  27. 27. 27 해결 #4 ● 트랜잭션 처리 적용 ○ 하나의 논리적 작업 단위 내에, 실패한 연산 존재 시 rollback 처리 ○ 비 정상적인 데이터 변경 사라짐 애플리케이션
  28. 28. 28 문제 #5 ● 무의미한 로그 ○ 타임스탬프의 부재 ○ 예외 발생 시점의, 데이터 기록되지 않음 ○ APP 개발자 분들의 이미 지난 시점의 서버 로그 확인 요청은 불가능에 가까웠음 ○ 불필요한 로그로 인해 디스크 사용량 90% 이상 차지함 애플리케이션 도대체 넌 언제적 로그니 ..
  29. 29. 29 해결 #5 ● 의미있는 로그 포맷 적용 ○ 불필요한 로그 제거 ○ ‘타임스탬프, 실행 중인 함수 및 로직, 처리 데이터’를 포함한 의미있는 로그 포맷 적용 ○ APP 개발자 분들의 로그 확인 요청을 두려워하지 않게 됨 애플리케이션
  30. 30. 30 문제 #6 ● Health Check의 부재 ○ 서버의 상태를 확인할 수 있는 Health Check의 부재 ○ 서버가 다운된 경우, 실시간으로 감지할 수 없음 ○ 팀원들을 불안하게 함 애플리케이션
  31. 31. 31 해결 #6 ● AWS ELB Health Check 적용 ○ EC2 내의 서버 프로세스가 동작하고 있는지 확인하기 위한 HTTP Get Request 적용 ○ 서버 프로세스가 동작하지 않을 때, Notification 이메일 전송 ○ 자식같은 서버가 동작하지 않는데, 혼자 룰루랄라하는 상황 사라짐 애플리케이션
  32. 32. 32 배포
  33. 33. 33 문제 #1 ● Repository의 master / dev 브랜치 관리의 부재 ○ 개발 서버 및 운영 서버의 부재로, 당연히 브랜치 관리 부재 ○ 작업 분리하여 트래킹 불가능 ○ 하나의 Repository로 협업하기 힘듦 배포
  34. 34. 34 해결 #1 ● Repository별 git branch 전략 도입 ○ 다양한 git branch 전략이 존재하지만, branch 전략에 팀원들이 익숙해지기 위해 우선적으로 master / develop/ feature 전략 도입 ○ feature 별, 테스트 별 작업 트래킹 가능 배포
  35. 35. 35 문제 #2 ● 배포 자동화 부재 ○ 서버에(ec2) 직접 접속하여 git pull 후, 프로세스 재실행 반복 ○ 배포를 위한 불필요한 시간 낭비 ○ 서버에서(ec2) 직접 급하게 코드를 수정한 흔적 ○ 점점 git repository와 멀어진 동기화 흔적 배포
  36. 36. 36 해결 #2 ● 배포 자동화 도입 ○ master / dev branch 마다 각 서버 보유 ○ 코드 push 후, Elastic Beanstalk CLI 이용하여 배포 자동화 ○ 서버에 접속하여 코드 동기화 & 배포 실행하는 시간 단축 ○ 서버에서 직접 코드를 수정할 가능성 차단 배포
  37. 37. 37 개발문화
  38. 38. 38 도입 #1 ● TDD (Test-Driven Development) ○ 새로 개발 시작된 기능들은 반드시 테스트 코드를 먼저 작성하도록 권유 ○ (TDD는 아니지만) 기존 코드는 리팩토링 시, 테스트 코드 반드시 작성하도록 권유 ○ 멤버들의 후기 > 어렵고, 시간이 많이 걸린다 > 시간이 지날 수록 기존 코드의 설계 문제를 확인할 수 있다 > 새로운 코드가 단단한 코드가 된 것 같다 개발문화
  39. 39. 39 도입 #2 ● 코드리뷰 ○ feature 개발 완료 시, 반드시 Pull request를 생성 ○ 멤버별로 리뷰 메이트 존재, 본인의 리뷰 메이트만 리뷰를 마쳤다면 merge 가능 > 멤버별 도메인 지식이 가장 비슷한 사람과 서로 리뷰 메이트로 지정 ○ 규칙은 온라인 이지만, 리뷰 메이트 사이에는 오프라인으로 자유롭게 리뷰 가능 ○ 멤버들의 후기 > 어렵다, 배포를 바로 못해서 답답하다 > 리뷰를 위해 코드를 신경쓰게 된다 (ㅋㅋ) > 같은 기능의 개발도 생각이 다양하다는 걸 알 수 있다 개발문화
  40. 40. 40 도입 #3 ● Documentation ○ 기존에는 문서화의 부재로, (저처럼) 새로운 사람 조인 시 공유할 수 있는 자료가 없었음 ○ 최소한의 리소스로 꼭 필요한 정보 문서화 진행 ○ 서버 아키텍처 문서, DB 설계도, API Spec 문서 ○ 새로운 API 추가 시, 문서화된 자료를 통해 클라이언트 개발자 분들과 Spec 확정 가능 ○ 문서화된 자료로 인해, 개발자간에 직접 대화해야 하는 시간 낭비 감소 개발문화
  41. 41. 41 결론
  42. 42. 42After 기본을 지키고 나니 .. ● 개발자간의 커뮤니케이션이 원활해졌습니다. ● 개발자간의 신뢰가 향상되었습니다. ● 개발자가 자신의 코드 품질에 대해 인식하고 개선을 위한 의지가 강해졌습니다. ● 동시 접속자를 견디지 못하거나 서버 오류로 인해 하루가 지나서야 마감되었던 이벤트 신청이, 동접 300명 가까이를 견디면서 11분만에 매진된 매끄러운 상황으로 개선되었습니다.
  43. 43. 43After 사실 .. 어렵지 않은 일이지만, 누군가는 언젠가 기반을 다져야 하는 일이었습니다. 하루가 다르게 고객이 증가하고 성장해가는 스위처에서, 규모있는 시스템을 다루기 위한, 개발팀의 초석을 다지는 일을 제가 직접 수행할 수 있는 기회는 값진 경험이었습니다. 이제는 유연하고, 확장가능한 시스템의 기반을 다졌고, 무엇보다 개발팀간의 커뮤니케이션 및 프로세스가 잡혀가는 과정이 진행 중이라는 사실이 지금까지의 가장 큰 수확이라고 생각합니다.
  44. 44. 44After 다음에 다룰 내용은 .. ● 로그 수집 시스템 ● SPOF(Single Point Of Failure) 제거 ● 부하 분산 ● Docker 적용 ● 새로 개발한 서버 적용 후기 ● Scala 기반의 서버 에 대해 How 관점에서 자세히 다루어 보려고 합니다.
  45. 45. 감사합니다 두번째 이야기, 로그 시스템 적용기 9월의 멋진 어느날, 아윌비백... 박미정 mjpark03@switcher.co.kr mjpark03@gmail.com

×