나는 고등학교 1학년 말에 처음으로 백엔드 포지션에서 프로젝트를 진행했다. 여기저기서 자주 우려먹는 교내 공식 기숙사 관리 시스템인데(파업 상태일 수도 있다), 같은 동아리였던 선배와 함께 Vert.x라는 서버 프레임워크가 지원하는 Vert.x-Web 툴킷으로 Java 8 런타임에서 돌아가는 웹 어플리케이션 서버를 개발했었다. 지금 생각해보면 참 많은 문제가 있었다.

내 과거

배포 방식

첫 번째는 배포 방식이다. 테스트 코드가 없는 건 둘째 치더라도, 신규 기능 개발이나 버그 해결을 하고 배포하기까지 사람 손이 정말 많이 들어갔다.

  1. Maven으로 WAS를 .jar 형태로 빌드한다.

  2. WinSCP라는 FTP 클라이언트로 서버에 원격 접속한다.

  3. jar 파일을 덮어쓴다.

  4. Putty라는 SSH 클라이언트로 서버에 원격 접속한다.

  5. screen으로 돌아가고 있는 WAS 세션에 들어가서 서버를 껐다 켠다.

다운타임 문제도 있고, 자동화할 수 있는 부분이었지만 자동화할 생각을 하지 못했다.

물리 서버가 한 대

리눅스에서 물리적인 터미널을 가상 터미널 여러개로 다중화해주는 screen이라는 도구를 써서, screen 하나는 서버 돌리고, 하나는 DB서버 돌리는 식으로 운영했다. 이게 사실 비용적인 문제 때문에 어쩔 수 없긴 했지만, 물리 서버가 한 대인 게 문제임을 인지하지 못했던 것이 더 컸다. '서버가 한 대인데 그게 고장나면?'이라고 누군가 질문하면, '아 그럼 고쳐야죠'라고 대답했을 것 같다. API 서버와 DB 서버를 분리해야 하는 필요성을 느낄만한 경험도 없었고, 아직 혼자 뭔가를 알아보기 어려운 내게 누군가가 가르쳐주지도 않았으니 말이다.

테스트 코드 없음

테스트를 코드가 아니라 PostMan으로 했다. happy path(가장 이상적인 로직)에 대해서 요청 몇 번 해보고, 잘 되면 배포했다. 이런 습관 때문에 문제가 아주 많았는데, 한가지 예를 들면 사용자가 2015년 이전의(파싱된 데이터가 없는 날짜의) 급식 정보를 로드하려 할 때 서버가 500을 내려줬던 적이 있었다. 테스트 코드가 없는 서버를 운영하는 것에 대해서는 말이 더 필요할까 싶다.

브랜칭 모델, 리뷰 없는 배포

먼저, 기능 개발이나 이슈 대응에 대한 별도의 티켓팅 과정이 없었다. 같이 서버를 개발하던 선배와 메신저로 얘기하면서 작업을 분배했고, 나는 할당받은 작업들을 wunderlist라는 to-do list 앱에 적어두고 하나씩 진행했다. 작업은 master 브랜치에서 진행했고, 배포는 리뷰 없이 각자 알아서 진행했다. 아래는 2017년 11월에 적어뒀던 작업 목록이다.

999A5E385C0677D620.png

까먹어서 처리하지 못한 이슈가 생길 때도 있고, 우선순위 조절도 매우 힘들었다.

로그 시스템 없음

Vert.x라는 프레임워크에는 미들웨어 개념이 있음에도 불구하고 제대로 된 로그 시스템을 구축하지 않았다. '제대로 된 로그 시스템'이라고 한 이유는, 파일 형태로 요청 로그를 남기기는 했기 때문이다. 아무튼 '로그를 남겨서 뭐하나' 싶었다. 로그 시스템이 없다는 건, 서버에 에러가 나고 있어도 인지하지 못한다는 것이다. 따라서 버그는 '보고 받는' 식으로 발견했다. 사용자가 원하기 전에 먼저 대응해두는 것이 더 좋은 흐름인데 말이다.

raw string 형태의 쿼리

코드를 보면 이해가 될 거다. ORM이 논쟁이 많은 기술이고 뭐고 다 떠나서 ORM을 적용했더라면 저 때 조금은 덜 열불나지 않았을까 싶다. 물론 저 때엔 문자열 결합으로 쿼리 문자열을 만들어내고 나서 '와 진짜 잘만들었다'라고 생각했다.

그 외에도 API 문서가 엑셀로 정리되어 있다거나, 서버가 살아있는지 체크하는 health check가 없다거나, 데이터베이스 백업 안해 뒀다가 쿼리 잘못 날려서 계정 정보 다 날아가거나 하는 것도 있었다. 지금 보면 왜 저랬나 싶은데, 당시엔 그게 당연한 건줄 알았다.

왜?

백엔드를 조금 경험해본 사람이라면 사용자를 어떻게 인증할지, 암호화는 어떻게 할지, API 문서는 어떻게 작성해야할 지 같은 걸 비교적 쉽게 의사결정할 수 있지만, 그렇지 않은 사람은 이런 게 필요하다는 것조차 깨달을 수 있는 경로가 별로 없다.

  1. 어플리케이션 레벨의 경우, 언어와 프레임워크의 선택지가 너무 다양해서 예제를 찾기 힘들다. 안드로이드는 Java나 Kotlin, iOS는 Objective-C나 Swift, 웹 프론트엔드는 React, Vue처럼 그래도 손에 꼽는 수준인데, 백엔드는 그렇지 않다. Java+Vert.x 예제는 정말 찾기 어려웠다. 요즘 갖고 노는 Python+Sanic도 그렇고.

  2. 당연하겠지만, 애초에 production level의 코드를 뜯어볼만한 기회가 별로 없다. 웹이라면 개발자 도구를 켜고, 앱은 종종 GitHub에 올라오는 코드로 얼추 알아볼 수 있을텐데 말이다.

  3. 백엔드는 코드만 봐서 되는 포지션이 아니다. 배포와 배포 패턴, 모니터링, 로깅, 스토리지, 트래픽 변동의 대응처럼 코드 외적으로 신경써야 할 부분이 많다.

  4. 어느 기술이던 경험해보지 않으면 필요성을 못 느끼는 것이 맞다. 그러나 백엔드는 그런 경험조차 해보기 어렵다. 예를 들어, 변동이 적은 데이터는 캐싱해 두면 좋지만, 굳이 캐싱해두지 않아도 데이터베이스에 쿼리하는 시간이 워낙 짧으니 필요성을 못 느낀다. 학교에서 조별 과제로 하는 프로젝트는 사용자가 매우 적거나 없으니 말이다. 로깅도 그렇고, 백업도 그렇고, 데이터베이스 서버 분리도 그렇다. 동기부여의 기회가 별로 없다.

이런 배경에서 어째저째 백엔드 엔지니어라는 이름을 단 채 일하기 시작하고 나니, 이런 걸 도와줄 수 있는 컨텐츠를 만들어보고 싶었다. 내 경우엔 뭔가 하나 깨우치는 걸 혼자 하려면 엄청 어려웠는데, 누가 옆에서 5분이라도 설명해 주면 꽤 쉬웠던 것 같아서, 그런 설명충 컨텐츠를 기획했다.

배포 전에 테스트를 돌리고, 배포를 자동화하고, 로그를 남기고, 시각화하고, 로그 파이프라인 중간에 버퍼나 proxy를 끼워넣는다거나 하는 게 누군가에겐 당연한 일일 수도 있겠지만, 그렇지 않은 사람들이 많다. 그래도 배경지식이 좀 생기면 혼자 찾아볼 수 있는 능력이라도 생기니, 같이 프로젝트 하나 해본다고 생각하면 될 것 같다. 컨텐츠 제목이 좀 싸가지 없어 보일 수도 있는데, 그냥 저게 평소의 내 말투라서 저렇게 지은거고 딱히 뭐 의미를 부여하고자 한 건 아니다.

이 컨텐츠의 룰

'백엔드가 이정도는 해줘야 함'이라는 컨텐츠는,

  1. 친구 서너명과 '게시판 기반의 커뮤니티 포털' 프로젝트를 진행해서 서비스화 시킨다고 가정한다. 이 배경을 기반으로, 백엔드의 관점에서 기술스택 의사결정부터 시작해 '백엔드가 이정도는 해줘야하지 않나'싶을 때까지 이것저것 붙여볼 것이다.

  2. 의사결정은 '다 ~로 하니까'가 아니라 상황에 맞춰 유동적으로 해볼 것이다. 트렌드를 따르거나, 추측을 기반으로 한 기술 선택은 멍청한 것 같다는 생각이다. '로그 분석에 ELK가 일반적이어서'같이 '당연히 이래야지'같은 이유로 기술을 도입하는 것은 본인에게나 조직에게나 좋지 않은 것 같다. 컨텐츠를 진행하며 계속해서 '내 결정이 옳다는 근거는 무엇인가?'라는 고민을 글로 옮길 것이다.

  3. 프로젝트에서 이런저런 외부 도구들을 쓰기 때문에, 백엔드로 프로젝트에 두세번 정도 참여해 본 사람 정도의 수준에 맞춰서 진행한다. 컨텐츠의 후반으로 갈 수록 이런 경향이 심화될 것이다. git, SQL, HTTP 등을 경험해본 적 없다면 초반 몇 챕터를 읽는 것도 어려울 수 있다. A to Z 모두 설명해보곤 싶지만, 내 역량이 부족하기도 하고, 그렇게 들어가기 시작하면 끝이 없기도 하니 이건 각자가 여기저기서 알아보며 공부하도록 하자. 주는대로 받아먹기만 잘하는 사람에겐 어울리지 않는 내용일 것이다.

  4. 조직 내 문서화 툴, 메신저와 같이 '프로젝트 팀 전체'에 해당하는 의사결정은 하지 않을 것이다.

  5. 의사결정의 흐름을 부드럽게 하고, 설명을 더 알차게 하기 위해 되도록 필자가 가장 잘 쓰는 기술을 선택할 것이다. 의사결정에서 '조직에게 가장 익숙하다'라는 이유를 붙이는 경우가 그런 예다. 물론 정말로 '이 기술이 조직에게 익숙한가'는 의사결정의 기준이 되어야 하는 것이 맞지만, 이 컨텐츠에 한해서는 '익숙함'이라는 기준이 의사결정의 우선순위가 조금 더 높을 뿐이라는 것이다.

  6. 모든 의사결정은 배경과 요구사항-선택지-의사결정 순서의 소분류로 나누어 정리할 것이다.

  7. 아주 자잘한 의사결정이거나, 당장 얘기하기엔 너무 길어질 것 같은 내용이라 따로 챕터를 두려는 부분은 '일러두기'라는 챕터에서 정리한다.

컨텐츠를 생성하는 필자의 배경과 관점 안에서 의사결정이나 코딩을 하게 될테니, 주관적인 부분이 조금 있을 것이다. 그러니 '얘는 프로젝트에서 백엔드를 이렇게 하는구나' 하며 이해해도 될 것 같다. 따라서 글의 내용을 따라오기 위해 모든 기술 스택을 내게 맞출 필요도 없다(뒷감당은 본인이 해야겠지만). 무작정 싹 다 설명하면서 도와주기보단 자립을 돕는 식으로 글을 쓰도록 노력해 보겠다. 모바일 기준 7~8화면 정도 분량으로 4~50편 정도에 걸쳐 진행될 예정이며 적어도 2019년 말까진 글이 활발히 올라올 것 같다.

컨텐츠를 진행하며 의사결정이 필요할 때마다 '이 방법은 이래서 구리고, 저 방법은 이래서 선택하지 않겠다'같은 이야기를 많이 하게 될텐데, 내가 '구리다'라고 하는 걸 본인이 썼거나 쓰고 있다고 해서 부끄러워할 필요는 없다. 다 필자의 주관적인 생각이고 '더 나은 방법'은 각자가 고민해야 하는 일이니까, '더 나은 방법이 없을까?'하는 고민을 멈추지만 말자. 그리고 가끔 가다가 예의없이 대충 설명하고 넘어가는 부분이 분명 있을테니, 맘에 안 드는 부분이 있다면 어떤 경로로든 얘기해주기 바란다. 더 좋은 글을 작성하는 데엔 독자의 피드백만한 게 없다.