백엔드 개발자는 현업에서 실제 무슨 일을 하고 어떤 일을 할 수 있나요?
어플리케이션을 개발하는 백엔드 개발자는 프로젝트에 따라서는 서버관리, DB관리, 프런트엔드 개발까지 모두 담당하기도 함
이렇듯 백엔드 개발자는 폭넓은 기술을 접할 수 있는 역할을 수행한다
SE(System engineer), FE(Front End) 등 인접한 분야의 개발자와 소통할 기회가 많음
그리고 접한 분야 중 한 분야에 대한 전문성을 키울 수 있는 기회를 만나기도 쉬움
예를 들면 담당하는 서비스의 통계 모듈 개발로 시작해서 대용량 데이터를 다루는 데이터 엔지니어로 성장하는 경우
특화된 분야의 전문가로 성장하더라도 어플리케이션을 잘 개발하는 능력은 중요합니다.
다른 개발자가 사용하는 플랫폼이나 라이브러리의 개발도 어플리케이션 개발의 특성을 이해해야 적용하기가 편리한 인터페이스를 설계할 수 있습니다.
대용량 데이터 분석이나 처리를 담당하는 개발자라도 업무 효율화를 위해 모니터링, 관리 도구를 만들어야 할 때도 있습니다. 그래서 깊이 있는 전문분야와 함께 어플리케이션 개발 능력을 갖춘다면 더욱 유능한 개발자가 될 수 있습니다.
백엔드 개발에 필요한 지식
백엔드 개발에서 중요하다고 생각되는 지식이 무엇인지에 대해서 많은 분들이 질문해 주셨습니다. 저는 주로 JVM과 Linux를 바탕으로 한 환경에서 서버 모듈 개발을 했습니다. 그래서 앞으로 이어지는 이야기에서 여러 기술 생태계를 다양하게 담지는 못했다는 점을 감안해 주셨으면 합니다. 웹 서버를 개발할 때는 아래와 같은 요소들이 우선 떠오릅니다.
웹 생태계의 스펙
HTML, HTTP(1.1 , HTTP/2)
기본 SDK, 라이브러리/프레임워크 이해와 활용
클라이언트를 위한 API 설계
서버/컴퍼넌트/객체 간의 역할 분담/의존성/통신 방법 설계
저장소 활용
DBMS 설계
Cache 적용
Global/Local cache 적용범위, 라이프 싸이클, 솔루션 선택
파일 저장 정책/솔루션 선택 활용
검색엔진 연동 방식 결정
빌드 도구
Maven/Gradle
배포 전략
성능 테스트/프로파일링/튜닝
JVM 레벨의 튜닝 (GC 옵션 등)
웹 서버(Nginx,Tomcat)등의 설정/튜닝
OS 설정의 주요 값 확인
인접 기술에 대한 이해
DBMS, Front End 등
서버 개발자에만 해당하지는 않는 항목
테스트 코드 작성/리팩토링 기법
버전 관리 전략
branch 정책 등
백엔드 개발에 필요한 기술
1차
데이터베이스 - e.g) PostgreSQL
서버 프레임워크 - e.g) 파이썬 Django
2차
서버 배치-우분투
웹 서버-Nginx
애플리케이션 서버-파이썬인 경우- uWSGI
작업 큐-파이썬 celery
주기적 작업 처리-cro
호스팅-국내 서비스(비용 저렴)
자동화-fabric
모니터링-whatap-국내
Failover-PostgreSQL
백엔드 개발 실무
다양한 저장소가 쓰이는 시대에도 RDB(관계형 데이터베이스)는 여전히 가장 우선시되는 저장소입니다. 그래서 RDB를 잘 다루는 능력은 백엔드 개발자의 핵심 역량 중 하나입니다. 개발을 하는 도중에도 쿼리의 호출 횟수나 실행 계획이 비효율적이지 않은지 확인하는 습관이 필요합니다. 운영 중에도 느린 쿼리를 모니터링하고 DBA와 협업하여 성능 개선을 하는 작업을 실무개발자들은 꾸준히 하고 있습니다. ORM같은 추상화된 프레임워크를 써서 직접 SQL을 작성하지 않는 경우에도 그런 작업들은 더욱 중요합니다.
과거에는 서버 간의 네트워크 호출 비용을 줄이기 위해 굉장히 많은 테이블을 한번에 조인하는 긴 SQL을 만드는 경우가 많았습니다. 하지만 요즘은 복잡한 JOIN은 가급적 피하는 경향이 생겼습니다. 데이터를 조회하는 SQL이 단순할수록 데이터를 다른 저장소에 캐시하거나 분산해서 저장하기가 쉬워집니다. 대용량을 저장하는 UGC 서비스에서는 RDB 테이블 사이의 JOIN은 최대한 제약을 하고 어플리케이션 레벨에서 여러 저장소의 연관된 데이터를 조합하도함
개발툴
Jenkins, AWS 등 Backend에 도움이 되는 도구를 배웠지만 도구를 배운다는 게 과연 실력을 키우는 것인지는 의문입니다.
개발도구를 잘 활용하는 능력은 생산성과 직결되기에 중요합니다. 그런데 개발도구를 '배워야'하는 개발자보다는 스스로 익힐 수 있고, 적절한 도구를 선택할 수 있는 개발자가 현장에서는 필요합니다. 특정 개발도구를 익혔다는 사실은 단기적으로는 실력이라고 할 수 있습니다. 새로운 도구가 나왔을 때도 적응할 수 있는 학습력/적응력/판단력이 본질이고 이것이 누적되어 실력이 됩니다.
JVM 생태계에서는 계속 Spring/Netty 기반의 프레임워크들이 꾸준한 발전을 하고 있다고 느껴집니다. 제 주변에 있는 여러 개발팀에서는 고부하 처리를 위한 서버에는 Netty를 바탕으로 UI개발과 직접 호출되는 API 서버나 HTML까지 그리는 서버 개발에는 Spring 계열이 많이 쓰이고 있습니다.
HTTP 프로토콜 위에서 JSON혹은 XML의 형식으로 통신하는 API를 폭넓게 REST API라고 부르는 경우가 많습니다. 그런데 현업에서 많은 이들이 REST라고 부르는 API들은 창시자인 Roy Fielding의 기준으로는 REST가 아닙니다. 대표적으로 상태가 Hyper link를 통해 전이되어야 한다는 HATEOAS를 대부분의 API를 충족시키지 않습니다. 이에 대해서는 그런 REST API로 괜찮은가를 참조하실 수 있습니다. REST API의 범위에 대한 논란을 피하고 싶다면 HTTP API 혹은 Web API라고 칭하는 것이 무난합니다.
테스트 코드를 작성하는 일을 통칭해서 TDD (Test Driven Develop)라고 부르는 사람도 있습니다. 이미 운영서버에서 잘 돌아가는 코드에 테스트 코드를 추가하면서 커밋로그에 'TDD 코드 추가'라고 적어놓은 경우도 본 적이 있습니다. 그러나 TDD의 개념을 정리한 Kent Beck이 'Test Driven Development: By Example' 책에서 보여준 기법은 테스트 작성, 테스트를 통과하는 코드 작성, 리팩토링의 싸이클을 거치는 것입니다. 테스트가 없던 레거시 코드의 버그를 고치거나 리팩토링 하기 전에 테스트를 추가하는 것도 TDD의 싸이클의 일부일 수도 있습니다. 그렇지 않은 경우에 뒤늦게 테스트를 추가하는 작업은 TDD라고 부르기보다는 '테스트 코드를 작성한다.'라는 표현이 무난합니다.
비슷하게 JUnit으로 작성하는 코드를 모두 '단위 테스트'라고 부르는 사람도 있습니다. JUnit의 이름으로 인해 생긴 오해입니다. JUnit으로는 다양한 범위의 테스트 코드를 작성할 수 있습니다. 예를 들면 스프링 프레임워크의 레퍼런스 메뉴얼에서도 단위 테스팅(Unit-testing)과 통합 테스팅(Integration-testing)이 구분되어 있습니다. 해당 메뉴얼의 단위 테스팅에 대한 설명에서는 아래와 같이 설명을 덧붙이고 있습니다.
Spring 레퍼런스 메뉴얼의 통합 테스팅 절에서 설명하는 기법들도 JUnit을 쓰고 있습니다. 이를 봐서도 JUnit으로 만든 테스트 코드를 모두 '단위 테스트’라고 칭하는 것은 정교하지 못한 분류이고, 혼동의 소지가 있습니다.
VO (Value Object)라는 패턴 이름도 실무에서 혼란스럽게 쓰이고 있습니다. getter/setter만 있는, 값을 실어나르는 VO라고 칭하는 사람이 있는데 이는 DTO로 칭하는 것이 혼란의 여지가 적습니다. Core J2EE Patterns 라는 책의 초판에서 그 의미로 VO가 정의되어 있었지만, 혼동의 여지가 있어서 2판부터는 TO(Transfer Object)로 바뀌었었습니다. 아래 자료들에서 VO와 TO의 정의를 확인할 수 있습니다.
이전에는 JSP와 같이 HTML를 서버사이드에서 생성하는 기술이 주로 쓰였습니다. 화면 전체를 다시 그릴 필요가 없는 요청은 Ajax로 처리했지만, 서버 렌더링에 보조적으로 쓰이는 경향이 강했습니다. 하지만 요즘은 React.js나 Vue.js와 같은 프레임워크가 널리 쓰이면서 클라이언트 사이드에서 HTML을 생성하는 비중이 높아지고 있습니다. https://d2.naver.com 도 React를 이용해서 전적으로 클라이언트 사이드인 웹브라우저에서 HTML을 그리고 있습니다. 선택지가 더 생김으로 인해서 어플리케이션이나 페이지의 특성에 따라서 어느 방식이 적합할지 이전보다 더 많이 고민하게 되었습니다. 사용자가 페이지에 처음에 진입할 때는 서버에서, 그 이후로는 클라이언트에서 HTML을 그리는 Universal Rendering도 최근 많이 시도되고 있습니다.
HTML 렌더링을 어디에서 할지는 개발자 간의 역할분담에도 영향을 미칩니다. 100% 클라이언트 사이드 렌더링을 하는 구조는 서버 개발자가 HTTP API 개발에만 전념할 수 있다는 장점이 있습니다. 반면 전문 Front End 개발자의 작업이 더 많아지는 부담도 생깁니다. 제가 속한 조직에서는 백엔드 개발자들도 React.js나 Vue.js를 이용한 UI개발자 참여함으로써 그런 단점을 보완하고 있습니다.
앞서 언급한 REST 스타일의 일부를 차용하더라도 HTTP API의 설계의 많은 부분은 매번 프로젝트마다 고민해야할 점이 많습니다. 예를 들면 단순 CRUD(입력/조회/수정/삭제) API는 각각 POST/GET/PUT/DELELE의 HTTP 메서드로 연결시키더라도 이를 벗어난 기능들은 어떻게 설계해야할지 명확하지 않은 경우가 많습니다. 페이징 처리를 할 때나 복잡한 검색조건이 있을 때의 파라미터 표현방식에서도 서비스마다 다르게 정의하고 있습니다. 그리고 API에서 선택적으로 반환할 속성과 아닐 속성을 지정하는 방식도 다양합니다. 아래의 스펙들이 보다 구체적인 API 설계안들을 제안하기는 합니다. 그러나 아직 어떤 상세한 스펙이 지배적으로 많이 쓰이고 있지는 않은 상황입니다.
클라이언트 사이드에서 UI 렌더링을 하는 경우가 늘어나면서도 HTTP API를 더 다양하고 정교하게 사용하고자 하는 필요성이 늘었습니다. 이러한 흐름 속에서 Facebook에서는 GraphQL을 내 놓았고, Github에서도 이를 도입하는 등 점점 확산되고 있는 추세입니다. 현시점에서 기존의 소위 REST 스타일과 유사한 틀에서 나름대로의 관례를 정립해서 최선을 추구할지, GraphQL을 도입할지도 고민되는 선택 중의 하나입니다.
시스템을 만들 때 많은 고민들은 결국 '구성요소 간의 역할과 책임을 어떻게 나눌 것인가'로 표현할 수 있습니다. 적게는 메서드, 클래스, 패키지 사이의 분담을, 크게는 jar로 배포되는 모듈이나 API로 통신을 하는 컴퍼넌트를 나누고 통신을 하는 방법을 고민을 하게 됩니다. 그리고 소프트웨어가 나누어진 경계에 맞추어 사람이 담당하는 업무의 범위나 협업 방식이 정해집니다. 그런 구조가 잘 잘라져 있어야 많은 사람들이 동시에 협업하면서 소프트웨어를 개발할 수 있습니다.
최근 MSA(Micro Service Architecture)라는 구조가 각광을 받으면서 서버에 배포 가능한 모듈의 단위를 이전보다 작게 가져가는 경향이 나타나고 있습니다. 많은 개발자가 동시에 협업하면서 개발하는데 MSA가 장점이 있기 떄문입니다. 이전에는 MSA와 같은 구조로 서비스를 만드는 것이 비용이 더 컸었습니다. 서버/네트워크를 더 많이 사용해야 하고, 서버/구성요소마다 설정하는 시간이 더 들어가고 문제가 생겼을 때 모니터링과 추적을 하는 것도 중간에 원격호출이 없을 때보다는 쉽지 않았습니다. 그러나 요즘에는 인프라시스템, 모니터링, 프레임워크의 발전으로 과거보다는 작게 단위로 서비스를 쪼개는 비용이 내려갔습니다. 그렇지만 서비스 간의 경계를 어떻게 잘라야 할지는 여전히 어려운 일이고, 적절히 잘라지지 않은 경계를 나중에 바꾸는 일도 비용이 큽니다.
네이버의 서비스들은 상호 연관되어 있고 다양한 조직의 많은 개발자들이 협업으로 만들고 있습니다. 네이버의 첫화면에 들어가는 구성요소만 해도 다양한 조직이 담당하는 모듈들을 거치고 있습니다. MSA라는 용어가 나오기 전이었지만, 그리고 최근의 경향보다는 서비스의 단위가 큰 경우가 많았겠지만 MSA가 이루고자 했던 장점들은 네이버에서 오랫동안 실용적으로 추구되어 왔다고 느껴집니다.
클라우드 컴퓨팅 기술(IaaS, PaaS, SaaS)
사내에 많이 쓰이는 플랫폼은 조직마다 직접 설치하고 운영할 필요가 없도록 PaaS 형태로 제공되고 있습니다. 로그수집시스템 Nelo, 어플리케이션 성능 측정 도구인 Pinpoint, 성능테스트 도구인 nGrinder, 분산메모리 저장소인 NbaseARC이 그 대표적인 예입니다. 많이 쓰이는 오픈소스 솔루션도 PaaS화하여 운영하는 사례가 늘어가고 있습니다.
최종 사용자가 바로 서비스를 사용하는, 네이버 메일, 캘린더, 클라우드(NDrive) 등이 SaaS의 예라고 생각합니다. 네이버 내부의 IaaS/PaaS/SaaS 기술들은 Naver Cloud Platform ( https://www.ncloud.com/ )을 통해서 외부에도 제공되고 있습니다.
일단 실행은 되는 백엔드 프로그램을 만드는 일은 쉽습니다. 요즘은 특히 인터넷에 많은 재료와 레시피가 있기에 더욱 그러합니다. 그러나 협업하기에 좋은 방식으로, 성능과 안정성까지 고려한 백엔드 프로그램을 만드는 개발은 쉽지 않습니다. 그리고 모니터링과 데이터 수집,분석 등 사용자의 눈에 보이지 않는 영역들도 실무에서는 많은 비중을 차지합니다. 데이터나 사용자가 적었을 때에는 효율적이었던 구현 방식이 시스템이 성장하면서 문제의 근원지가 되기도 합니다.
그런데 실무 기술을 써본 경험이 있어도 그 기술에 대해 자세히 설명할수 없다면 오히려 경험 안했다고 이야기하는 것보다 더 부정적인 영향을 미칠수 있습니다.
예를 들면 Java로 DB를 쓰는 개발을 해봤다고했는데 그게 MyBatis를 썼는지 JPA를 썼는지도 모르는 경우입니다.
반면 잠깐 써보고 아직 깊이 모르는 기술이라도 구체적인 이야기를 체계적으로 할 수 있다면 더 긍적적인 요인이 됩니다.
예를 들어 MyBatis를 처음 썼는데 어떤 상황이 어려웠고, 알고보니 MyBatis의 어떤 특성 때문이였고, 이를 어떻게 해결했는지 등에 대한 구체적인 이야기를 하는 사람이면, '이 사람은 쓰는 기술에 대해서 제대로 파악을 하려고 했구나'를 느낄수 있습니다. 그런 사람이면 MyBatis를 당장 안 쓰고 JPA를 쓰는 프로젝트에라도 바로 적응할수 있겠구나 하는 느낌을 줍니다.
신입 개발자를 채용할때는 현재 할 수 있는 일이 얼마나 되는지를 넘어서 앞으로 얼마나 발전가능성이 있는지에 더 중점을 둬야된다고 생각합니다. 면접관 입장에서는 자신이 잘 아는 기술을 단편적으로 물어보는것에 그치지 않고 사람이 가진 학습 능력, 학습 의지 등을 파악해야하는데, 당연히 쉬운 일은 아닙니다.
지원자 입장에서는 성장가능성을 표현할수 있는 방법은 여러가지일 것 같습니다.
위와 같이 실무에서 쓰는 이미 잘 알고 있고, 그걸 학습해온 과정을 잘 설명하는 것도 하나의 방법입니다.
학교에서 한 팀 프로젝트라도 남 다르게 한 면이 있다면 실무기술을 잘 몰라도 충분히 앞으로 성장 가능성을 보여줄수 있다고 생각합니다.
코딩 테스트에서 문제를 센스있게 파악한다던지, 유창하고 거침없이 코딩을 할 수 있는것도 자신을 잘 드러낼수 있는 방법입니다.
글을 쓰다보니 '신입개발자로 지원할 때는 자신이 앞으로 빠른 속도로 발전할수 있다는 가능성을 보여주는 것이 중요한데 실무에서 쓰는 기술을 일부 아는 것은 그 방법 중의 하나이다. 그러나 유일한 방법은 아니다.' 정도로 제 생각은 정리가되네요.
글을 쓰다보니 몇년전의 어느 인턴 지원자의 면접이 기억납니다.
Linux 커널에 관심이 많은 학생이였는데, 사실 제가 인턴의 업무로 염두에 두었던 분야는 그쪽은 아니였습니다.
코딩 테스트도 제가 계획한 둔 인턴 과제에서는 쓰지 않을 C++로 하기도했습니다.
당시에 엄격한 기준으로 채점을 하는 시스템을 이용해서 코딩 테스트를 했는데, 그 시스템의 판정으로는 그 학생은 문제를 통과하지 못했습니다.
그렇지만 거의 답에 근접한 방식으로 코딩을 했고, 무엇보다 유창하고 거침없이 코딩을 하는 모습이 인상적이였습니다.
하나의 방법이 잘 안되자 그 다음 생각나는 아이디어를 바로 빠르게 타이핑해나갔습니다.
저는 그 학생을 합격시키고, 연관된 업무가 있을만한 다른 프로젝트 쪽에 추천을 드렸습니다.
인턴을 거쳐서 그 학생은 최종 입사를 했습니다.
그런데 처음 그 신입사원이 했던 분야는 그 학생이 깊게 팠던 Linux 커널등과 관련된 분야는 아니였습니다.
Java웹개발과 JavaScript와 Angular.js로 FE개발까지 했던것으로 알고 있습니다.
Ref..OKKY
'ETC' 카테고리의 다른 글
Eclipes 단축키 (0) | 2020.11.23 |
---|---|
PyCharm 단축키 (0) | 2020.11.23 |
Visual Studio 단축키 (0) | 2020.11.23 |
개발자 인터뷰 시 질문 모음 (0) | 2020.11.23 |
리눅스 자동 스케줄링 - 크론탭(Crontab) 사용법 (0) | 2020.10.23 |