-

취업과 채용에 관한 지극히 개인적인 단상

smileostrich 2024. 8. 18. 19:49

서론

가까운 사람이 이직을 위해 준비하고 있기에 올해 목표는 나 자신의 성장보다는 주변을 서포트 하는 것을 우선 순위로 해야겠다고 목표하고 있었다.

그래서 내가 평소에 진행하던 스터디도 줄이고, 개인적인 취미 생활이나 여가는 거의 챙기지도 못했지만 얻게된 것들도 많았다.

Java 와 spring, mysql 등으로 프로젝트를 만들기 시작했는데, 개인 프로젝트라 할 지라도 코드 퀄리티에 대해 놓치긴 싫더라(지금 생각해보니 포트폴리오 목적이었기에 퀄리티를 챙기려 해서 일수도 있겠다.)

그래서 깔끔한 코드를 작성하려고 살펴보면, 최신 버전에 더 좋은 방법들이 많았고 jdk 및 spring, mysql 의 버전도 덩달아 높이게 되더라.

다만, 아니나 다를까 JDK 21 에 Mysql 9.xx 을 선택하는 순간부터 서칭을 통해 찾을 수 있는 자료가 현저히 줄어들었다.(최근에 만든 프로젝트라 할 지라도) 대부분 과거 구글링을 통해 만든 프로젝트들이 많았기에 참고할 곳이 구글링으로 블로그를 찾아봤을 땐 보이지 않았고, 그나마 깃헙에서는 간신히 1~2개 정도 내가 원하는 코드를 발견할 수 있었다. (해당 코드를 작성하신 분의 깃헙 프로필을 보니 역시나 이미 좋은 곳에 계시더라)

결국 좋은 동료를 찾는 것의 시작은 코드에 대한 애착을 가진 사람을 찾아야하는게 아닐까? 하는 생각에서부터 시작된 회고 겸 단상을 공유해보겠다.

 

나는 어땠을까? (업무 능력 그리고 나 자신에 대한 이해)

(아래 내용들은 제가 첫 회사를 준비하는 것에서부터 현재 직장에 이르기까지 생각했던 것들을 되짚어본 지극히 개인적인 내용이니 어디까지나 이런 시각도 있구나 정도로만 참고하시면 좋을 것 같습니다)

당시 많은 사람들이 접근하는 방식인 '어떤 기업이 좋을까?' 는 개인적으로 좋은 접근 방식은 아니라 생각했다.

오히려 '나는 어떤 사람인가?' 라는 질문이 도움이 됐기 때문일 것 같다는 생각이 든다.

이걸 조금 더 구체화 시켜보면

'나는 어떤 성격이고, 어떤걸 좋아하고, 잘하고, 싫어하고, 못할까?'등과 같이 내 특성을 살펴보면 좋을 것 같았다.

심리학에 관심이 많은 분들은 다들 아시겠지만, 사람이 가장 힘든 시기는 자기 불일치가 발생했고 그 gap이 클 때라고 한다.

즉, '내가 원하는 상태' 와 '내 상태' 가 불일치하고 그 차이가 클 수록 힘들어진다.
이런 걸 심리학에선 자기 불일치(Self-Discrepancy) 라 표현하는데 이는 목표-행동 불일치(Goal-Behavior Discrepancy) 같은 것들이 동반되게 되는 경우가 많아 스트레스를 많이 받거나 심지어는 우울증으로까지 이어지는 경우도 많다고 한다.

(이왕 사족을 붙이기 시작했으니 조금 더 붙여보자면, DB 에서는 MVCC 라는 개념이 있듯
심리학에선 MBSR 로 유명해진 Mindfullness  와 같은 개념들이 이에 속한다.
요약하자면 주기적으로 내 스스로의 상태를 체크하는 컨셉의 개념이다. 즉, 인지하고 수용하고 관용을 베풀기라 할 수 있다)

더군다나 개발자들이 속해있는 업계의 복잡도는 빠른 속도로 상승하고 또 변화하고 있다.
(아래 내용은 오시영님의 글에서 발췌했다)

취직하기 전 내가 중요히 여겼던 것은 업무 능력을 보여주는 것이라 생각했다. (결국 회사는 이윤을 창출하는 곳이고, 그것을 위해선 필요한 업무를 설계하거나 진행해야할 것이라 생각했다)

다만, 당시 내가 정의했던 업무 능력은 단순히 특정 기술을 잘 다루는 것에 그치지 않았다.
오히려 이는 주어진 시간 내에 프로젝트의 요구사항을 충족시키며, 더 나아가 조직 전체의 생산성에 기여할 수 있는 능력을 생각했었다.

이를 위해 당시의 나는 다음과 같은 요소들을 갖추려고 했었다. (*당시 내가 중요하다고 생각했었던 순서)

  1. 업무에 필요한 기본 지식
    해당 업무에 필요한 지식의 커버리지를 최대한 채워놓기. 이런 노력이 학습에 소요되는 시간을 단축시키고, 새로운 상황에 빠르게 적응할 수 있는 능력을 키울 수 있을 것이라 생각했다.
  2. 복잡도 높은 맥락을 빠르게 파악하는 능력
  3. 커뮤니케이션 효율성
    커뮤니케이션 코스트가 낮을 수록 좋을 것이라 생각했어서 구직과정에서 이 점도 많이 전달하려 노력했었다.

계속 복잡도가 높아지는 환경의 특성상 1번에 해당되는 지식 쌓기는 한 번에 끝날 순 없다고 생각했다.
다만 (병특 시절의 경험을 통해) 회사에 다니면서 지식을 쌓기위해 공부하는 것은 너무나도 힘들었던 기억이기에 회사를 바로 다니기 보단 준비 기간을 좀 늘리고 싶었다. 그래서 공통적인 부분에 대한 지식을 최대한 쌓아두고(당시에는 지금처럼 공부할 게 많지 않아서 CS 를 위주로 공부했다) 그리고 내가 어느정도 공부한 후부터는 원하는 분야의 지식인 DB, DevOps 관련 지식과 경험들을 쌓자고 판단했다.

취준생 시절 준비했던 내용은 아래와 같다.

- CS(CSAPP, OSTEP 나 네트워크 관련 지식 등)

- CMU DB 강의들 (https://www.youtube.com/@CMUDatabaseGroup)

- 토이프로젝트를 진행하며 직접 사용자 트래픽 받고 견디기(Terraform, Nginx, spring 등)

- AWS / Terraform 등 인프라 관련 지식

- CKA

- 이외에도 각종 DB 를 살펴보면서 글을 쓴다거나 발표를 하기도 했었다(다른 곳에 작성했던 발표자료를 나중에 이 블로그에도 옮긴 적 있는데 cockroachDB 를 다뤘던 이 글(https://smileostrich.tistory.com/entry/cockroachDB)이나 etcd를 다룬 이런 글(https://smileostrich.tistory.com/entry/etcd)들이 있다. 

 

Inside Etcd

ETCD3 ETCD3 Before etcd etcd 이름의 유래 CAP & PACELC theorem CAP PACELC 그래서 PACELC에서 etcd는 어디에 속하는가? 그럼 newsql은? Distributed Concensus CFT, BFT, PBFT Paxos Raft Etcd에서의 raft client가 꼭 etcd 리더에게 요청

smileostrich.tistory.com

 

Inside CockroachDB

(과거 스터디에서 발표하기 위해 노션에 작성했던걸 이전한 자료입니다. 옮기는 과정에서 깨져있을 수 있음을 양해 부탁드립니다) 우선, CockroachDB란? CockroachDB는 트랜잭션 및 강력하게 일관된 key

smileostrich.tistory.com

 

근데 막상 진행해보니 시간이 너무나도 오래 걸렸어서 취직이 급한 분께는 추천드리지 않고 있다.

(다만, 당시의 나는 명문대도 아니고, 스스로를 증명할 방법이 없었거니와 당장 취업할 상태는 아니라 판단했어서 사법고시 준비하듯 아침 8시 즈음 일어나서 밤 11시까지 1년 이상 공부만 했었다)

근데 이건 말 그대로 '지식'만 쌓는 것이더라.

업무에서의 커뮤니케이션은 달랐다. 특히나 주변에서 말 잘한다는 얘기를 꽤나 들어왔던 내게도 업무에서의 커뮤니케이션은 전혀 달랐다.

업무에서의 커뮤니케이션은 상대방의 의도를 빠르게 캐치하고 업무의 진행 상태를 공유하고 좋은 방향으로 나아가도록 돕는 것이 핵심이었다.

게다가 취직하고 내가 속했던 조직들에서 업무를 수 년간 하면서 느낀건 2 번(*복잡도 높은 맥락을 빠르게 파악하는 능력)은 다른 것들의 슈퍼셋에 가까웠고, 다른 내용들은 부분집합에 불과한 내용이라 느껴질 정도였다.

맥락을 빠르게 파악한다는 것은 결국 핵심을 빠르게 찾고 이해한다는 것을 의미했고,

감사하게도 내 동료(과거, 현재 모두)분들은 핵심을 빠르게 찾고 좋은 커뮤니케이션을 하는 분들이셨기에 배울점이 참 많았다.

다만, 과거 다른 조직들에선(심지어 N사에 있을 때 조차도) 작업 속도가 상당히 빨랐는데, 지금 조직에 합류했을 땐 내가 병목이 될 때가 있었기에 더 치열하게 노력하려고 했었던 것 같다
(애초에 맥락이 복잡한 사안인데 내가 아는지 모르는지 잘못 판단할 때가 많았다. 그와중에 빠르게 성과를 보여주려는 욕심이 있었기에 안다고 생각하고 넘어갔던 것들이 패착이었다)

현재 조직에는 입사한지 3년 가까이 되어가는데 복기해보면

초반 9개월 가량은 나 스스로를 갈아넣었는데, OSGI 라던가 자사의 제품인 Observability 솔루션, 자체 DB에 대한 이해가 있다는 것이 오히려 말 안되는 상황이었기에, 조급함이 오히려 독이 되었다.

이후 3개월 정도는 회사 분위기가 좀 뒤숭숭했어서(회사가 급속도로 커지고 있던 터라 구성원 변동이 있었기에 전반적으로 뒤숭숭했고 심지어 금리 인상으로 인해 개발 업계 전체 분위기가 뒤숭숭했었다) 회사를 완전히 신뢰하지 못했다.

야근도 하고, 나름 시간도 많이 퍼부었던 사람이 그걸 줄이기 시작하니 사실 주변에선 그게 티가 났을 것 같다. (사실 정상 근무로 돌아간 것이긴 한데, 애초에 내가 너무 과했던 것도 잘못이라 생각한다) 뿐만 아니라 제품(DB, Observability) 대한 애정으로 이직한 것이기에 페이를 줄이고 왔는데 그 여파가 우리 회사에도 미치지 않을 수 없으니, 연봉협상이 내가 원하는대로 흘러가지 않았던 것도 신뢰하기 힘들었던 가장 큰 원인이기도 했다.

이래저래 한동안 방황을 좀 하다가 그래도 지인분 추천으로 지인 회사에 입사한 것인데, 아무리 생각해도 지금과 같은 방식이면 서로가 괴로울 것 같아서 1on1 을 신청했고 여러가지 고민을 먼저 털어놓았다(애초에 그동안 너무 달려왔으니 퇴사하고 잠깐 쉬고 싶다는 얘기에서부터, 이런저런 고민 포인트들까지) 다만, 팀원분을 비롯해서 타 부서의 직원분들 몇 분과 깊은 대화와 함께 여러 제안들을 받았고 결국 회사에 잔류하기로 결정했다.
다만, 결정에 후회를 하지 않기 위해선 나부터 회사에 신뢰를 줘야 한다 판단했다.
신뢰를 쌓기 위해 가장 중요한 것은 업무를 훨씬 더 잘하는 것이라 판단했고, 그걸 위해선 (설사 내게 지금 업무가 혹시나 이직할 때 하등 도움이 되지 않더라도) 사내 시스템 파악이 중요할 것이라 생각했다.
다만, 내가 속한 storage 팀에서 관리하는 모든 DB(confDB, raft, OLAP 외에도 여러 DB 가 있다) 및 사내 시스템 전체 코드를 다 다 파악하는 것은 불가능하다 판단했고 (짧은 시간안에 파악했다는 얘길 듣고 싶었지만 그런 건방진 태도는 버리고) 초심으로 돌아가 전반적인 흐름과 함께 내가 맡은 코드부터 다시 파악해야겠다 싶었다. (예를 들어, 당시 살펴보던 부분인 사내 Raft 구현체에서부터 여러 DB 의 Index, Data 구조를 다시 살펴보고 정리하기 시작했다. DB 에선 데이터 구조를 여러개 가질 수 밖에 없는데 자사도 마찬가지. 그래서 Columnar 외에도 여러 버전의 데이터 구조를 정리하고 차이를 정리하는것에서부터, Cluster storage 팀의 업무에 필요한 내용들을 하나 둘 파악하기 시작했다)

다행스럽게도 좋은 동료분들이 계셨기에, 파악하는 시간을 기다려 주셨고 시스템 이해도가 낮아서 발생하는 잘못된 결정들을 최대한 가이드해주시고 또 인내해주셨다. (이건 정말 동료 운이 좋았다고 밖에 설명할 수 없긴 하다)

사실 곧 3년이 되어가는 지금도 모든 코드를 이해했다고 할 순 없지만 적어도 내가 맡은 부분에서 만큼은 전보다 훨씬 많은 것들이 보이기 시작했고, 아이러니하게 그 때부터 회사 코드가 아니더라도 전반적인 시야가 넓어졌고, 실력도 좋아지는게 체감되더라.

결국 내 장점이었던 커뮤니케이션을 잘 한다고 느끼는 것은 업무적으로 도움이 되진 않았지만 신뢰를 쌓는데 조금이나마 도움 되지 않았을까 싶어서 내가 했던 노력들을 남겨본다.

평소 (업무 외적인) 커뮤니케이션에서 항상 중요하게 생각했던 건 거짓이 없어야 한다는 점이었다.

그래서 그동안 1on1 및 많은 대화에서 항상 솔직했다.
즉, 나를 꾸미지 않았고, 내가 부족한 부분들을 잘 인정하고 수용하고 개선하려고 노력했다.
그리고 장기적으로 개선된 모습들을 보여주려 노력했다.

그렇다고 당장 기다려 달라고 얘기만 하는 것은 빚지는 느낌이 들 것 같아서 최대한 내가 기여할 수 있는 부분들을 기여하려고 했다.

예를 들어, 내 장점이었던 DevOps 에 대한 지식을 사내 인프라에 녹여내려고 IaC 화하는 작업들을 진행했고 틈날때마다 각종 문서화 작업들을 진행했다.

당시 회사엔 평균 근속연수가 10년에 가까울 정도로 오래 다니신 분들이 워낙 많았고, 우리팀엔 나를 제외하곤 전부가 그랬다. (오죽했으면 스토리지팀에 거의 10년만의 신입이라는 얘기가 잦았을 정도이니...)

다만 이런 사실이 마냥 나쁜 것은 아닌게, 추후에 입사할 사람들을 위해 문서화 할 것들이 많다는 것을 알게됐다.

그래서 남들이 귀찮아 할 법할 일들인 문서화에서부터 기존에 스크립트로만 운영되던 인프라를 IaC 로 하나 둘 전환했다.
내 입장에선 지겹게 썼던 K8S 나 docker(docker compose), Terraform 등의 당연한 내용이 기존 시스템에 너무 익숙했던 분들에겐 도움이 된 것이 나름 즐거웠던 포인트기도 했다.

이외에도 내 업무였던 자체 DB 를 파악하면서 알게된 것들을 정리해두는 등 마음을 바꾸고 보니 기여할 내용들은 너무나도 많더라.
그래서 기존 업무에 진행하고 시간이 남을 때 마다 저런 작업을 진행했었고 지금은 어느정도 템플릿이 생겼다. (물론 아직도 개선할게 많지만... 적어도 내가 업무에서 내가 IaC 화 했던 부분들에서 도움을 많이 받고 있다)

이러한 노력들은 결국 내가 먼저 회사에 대한 신뢰를 표현한 셈이 되었고, 그것이 내 미숙한 부분들을 조금이나마 상쇄시켜주지 않았을까 싶다.

물론, 이런 내용들은 애초에 내가 CSAPP 서론에서 언급되는 슈퍼 개발자가 아니어서 일 것이다.
다만 그 super 개발자가 아닌 사람들을 위해 (특히 당시의 나처럼 방황하는 분들을 위해) 내가 했던 발악 했던 과정들의 기록이 누군가에겐 도움될 수 있지 않을까? 하는 마음에 주절주절 적어보았다.

요약하면, 복잡도가 너무 높은 시스템을 접했고, 매번 파악했다 생각했지만 정작 그렇지 못했었다
(observability 를 제공하려는 보안 솔루션 제품의 복잡도는 단번에 파악할 수 있는게 아니었다. 내가 너무 건방졌다)
다만, 내가 회사를 떠나기 보단 회사 시스템을 파악해서 회사에 기여하고 싶은 마음을 전달하려 노력했다.

 

신뢰를 쌓으려면?

오랜만에 글을 적다보니 말이 너무 샜다. 원래 다루려 했던 주제인 신뢰로 돌아가도록 하자.

대부분의 사람들이 커뮤니케이션을 모호한 것으로 여기는데
일각에선 안나 카레니나의 법칙처럼 커뮤니케이션을 잘 하는 방법은 어느정도 정형화 되어있다고 주장한다(나도 그걸 믿고 지지하고 있고)
ChatGPT 가 대표적인 증거로 사실 ML 쪽에선 오래된 주제였고, 좋은 강의도 많다(이 블로그에도 자주 홍보했던 patrick winston 님의 How To Speak 도 대표적인 예)
How To Speak 만 해도 좋은 인사이트를 얻을 수 있는데,

좋은 커뮤니케이션을 고민하다보면 필연적으로 어떻게 신뢰를 쌓을까? 에 도달하게 된다.

즉, 어떻게 신뢰를 쌓을까? 로 치환해서 생각해보면 답은 간단하다.

가장 큰 부분인 업무 능력이 전제되어야 한다.

'잘 한다'는 말은 공허하다. 어떤 사람에게는 특정 프레임워크를 경험해보았다는게 잘 한다의 기준이 될 수 있고, 어떤 사람에게는 복잡도 높은 시스템에서 현명한 결정을 하고 그걸 코드로 잘 구현하는것 까지가 잘 한다의 기준이 될 수도 있다.

내가 정의한 신뢰는 '내가 속한 조직'에서 필요로 하는 니즈를 캐치하고 그 니즈에 부합하는 가치를 제공하고 '특정 기간 이상 동안 꾸준히' 그 모습을 보여주는 것이다.

뭔가 익숙하지 않은가?

그렇다. 바로 아까 얘기했던 상태 불일치와 유사하다.

회사에서 기대하는 상태실제 내가 보여주는 상태(아웃풋)으로도 요약할 수 있다.

회사에서 기대하는 상태와 내 아웃풋이 일치하고 때론 회사가 필요로 하는 니즈를 캐치하고 채워주면서 충분한 기간이 지나면 비로소 신뢰가 생기는게 아닐까? 생각한다.

그렇다면 이제 원하는 회사를 선택하는 방법도 어느정도 보이기 시작할 것이다.

아래는 오시영님께서 쓰신 '차이를 만드는 커리어 굴리기' 라는 발표인데
아래 내용처럼 난이도, 환경, 문화를 고려해서 회사를 선택하고 거기에 노력이 동반되면 엄청난 성장을 할 수 있음에 매우 동의한다.

다만, 상태 불일치가 너무 크고 길어지면 회사 뿐만 아니라 개인 스스로도 굉장히 괴로울 것이다.
많은 월급을 받으며 매일 챌린징한 업무를 진행하면서 성장하는게 겉으로 보면 좋고 부럽기만 한 일일수도 있지만,
만약 상태 불일치가 메꿔지는게 아니라 상태가 더 커져가는 것을 느끼게되는 상황이라면...

그래서 오히려 더 본인 스스로에 대해 파악하고, 원하는 부분을 위해 노력하고 무엇보다도 길게 보는게 참 중요하다(내가 원하는 부분을 나중에라도 찾게 될 수 있으니.. 우선 나부터도 그러했다)

다만, 이게 노력으로만 가능하지 않다고 생각한다(그래서 오시영님의 글에 참 공감을 많이했고, 발췌도 많이했던것..)
이제와서 돌이켜보면 운이 정말 큰 것 같기도 하다.
대표적인 예시로 시기.
지금같은 시기엔 더 막막하고 벅차고 힘들 수 있다. (당장 복잡도 뿐만 아니라 개발을 희망하는사람이 10년 전과 비교하면 엄청나게 많아졌기에 경쟁률도 상당하다. 예전에 다녔던 곳 중 한 곳은 합격 후 약 1000:1 에 가까운 경쟁률이었기에 그때도 10년 전에 비하면 와... 싶었는데 몇 년 지나지도 않은 지난 지금은 2000:1 을 넘었다는 얘기를 얼마 전 듣게 되었다..)

요약하면 결국 너무 조급하게 보지 말고 나를 파악해가며 내 장점을 살릴 수 있는 부분에서 최대한 장점을 살리고,
단기적인 목표 뿐만 아니라 장기적인 목표를 세우며 하나씩 이뤄간다면 마음도 같이 챙기고 길게 갈 수 있는 방법이 아닐까 싶다. (길게 갈 수 있도록 해야 오히려 좋은 길로 갈 수 있다고 믿고 있다)

 

그렇다면 어떻게 하면 원하는 사람을 구할까? (구인자 입장)

(조직 규모 및 유명세 등 상황마다 다르니 아래 내용은 빅테크는 예외로 한다)

특정 아웃풋을 낼 수 있는 사람이 받는 페이는 대략적으로 정해져있다 (물론, 아웃풋을 어떻게 정의하느냐는 참 어려운 문제이고, 어떤 가치를 제공하는지, 실제로 그게 옳은지 판단하는것도 너무나도 어렵긴 하다 애초에 큰 기업이건 작은 기업이건 채용은 너무 어려운 문제다. 트러블 메이커가 조직을 망치는 것을 우려할 수 밖에 없기 때문)

이 때, 빅테크들은 그나마 쉽게 적정가 혹은 그 이상까지도 지불할 수 있지만

현실적으론 그게 힘든 기업들이 훨씬 많을 것이다.

그래서 시니어 개발자 채용은 훨씬 비싸고 리스크가 크다. 이걸 기업들이 모르지 않으니 시니어를 막 늘리기 보단 적당한 가격에 주니어를 키우려는 시도들이 많았다. 다만, 이 경우에는 성장하고 나면 다른 기업에 갈지 모른다는 불안감을 가지는 경우가 많고..

결국 게임이론인데, 서로 원하는 바를 자주 체크하고 서로 타협하려고 노력한다는 인상을 심어주고, 또 그런 분위기라는 것을 주변에 자주 퍼트리는 전략을 취하는 곳이 많아졌으면 하는 바램이...

그렇다면 과거엔 어떤 시도들이 있었을까?

개발자 붐이 일었던 시기에는 투자금이 IT 분야에 쏠렸다. 따라서 막대한 투자금을 바탕으로 한 높은 연봉을 제시해서 해결하려고 했다.

물론 나쁘지 않은 전략이었지만, 과한 가치를 부여했다고 느끼고 배신감을 느낀 회사들이 해당 전략을 바꾸기 시작했다.

이전 시기에 비하면 많이 내려간 상황이니 5~10년차 사이의 인력들을 더 낮은 가격으로 데려가는 경우가 많아진 것.

다만, 무작정 데려오는것이 능사는 아니다. 내가 원하는 동료를 구하려면 어떤 업무를 수행하길 원하는지부터 정해야한다.
(어찌보면 너무나도 당연한 얘기지만, 급하다보면 이것 조차 생략하는 곳들이 수두룩 하다)

해당 동료분이 입사 후 어떤 업무를 진행해야하고, 원하는 아웃풋이 어떤 것인지에 따라 어떤 방식으로 채용할지도 달라진다.

모든 상황에 맞는 방법을 찾진 못했고, 현재 회사를 가정해서 방법을 찾는 것을 시뮬레이션 해보겠다.

우선, 니즈부터 정의해보자.

대용량 데이터를 유실 없이 핸들링하고 자체 DB 를 개선하면서 성능도 뛰어나길 바라는 제품을 만드는데 기여해 줄 동료이면 좋겠다.

다만, 기본적으로 observability 를 제공하기 위한 아키텍쳐의 layer 는 꽤나 복잡하고 제공하는 기능들이 너무 많아서 상당히 벅찰 수 있다

(아래에는 기본적으로 회사에서 제공하는 DB 및 Observability 기능들인데 정말 너무나도 많다...)

더보기

{
  "명령어": {
    "엔터프라이즈 명령어": {
      "매개변수": ["set", "setq"],
      "데이터 조회": [
        "csvfile",
        "fulltext",
        "json",
        "jsonfile",
        "load",
        "logger",
        "pcapfile",
        "remote",
        "result",
        "stream",
        "table",
        "textfile",
        "xmlfile",
        "zipfile"
      ],
      "데이터 가공": [
        "alertmsg",
        "auditmsg",
        "boxplot",
        "bypass",
        "cube",
        "curvefit",
        "decodedhcp",
        "decodedns",
        "decodehttp",
        "decodesflow",
        "eval",
        "evalc",
        "explode",
        "fields",
        "flowsearch",
        "groovy",
        "limit",
        "mpsearch",
        "order",
        "parallel",
        "parse",
        "parsecsv",
        "parsejson",
        "parsekv",
        "parsemap",
        "parsexml",
        "pcapdecode",
        "pcapreplay",
        "pivot",
        "prev",
        "rename",
        "repeat",
        "rex",
        "rollup",
        "search",
        "serial",
        "signature",
        "sort",
        "stats",
        "timechart",
        "tojson"
      ],
      "데이터 매핑": [
        "geocode_kr",
        "lookup",
        "lookuptable",
        "memlookup",
        "nslookup"
      ],
      "데이터 적재": [
        "drop",
        "import",
        "insert",
        "outputcsv",
        "outputjson",
        "outputpcap",
        "outputtxt",
        "sendmail",
        "sendsyslog",
        "sendsyslog-tcp"
      ],
      "데이터 병합": ["join", "streamjoin", "union"],
      "이벤트 연관 분석": [
        "evtctxadd",
        "evtctxdel",
        "evtctxdrop",
        "evtctxlist"
      ],
      "머신러닝": ["anomalies", "forecast", "kmeans", "lof", "rforest", "stl"],
      "프로시저": ["proc"],
      "외부 시스템 연동": [
        "dbcall",
        "dbload",
        "dblookup",
        "dboutput",
        "dbquery",
        "dbscript",
        "ftp",
        "hdfs",
        "mongo",
        "rss",
        "sftp",
        "wget"
      ]
    },
    "소나 명령어": {
      "이벤트": ["alert", "event"],
      "로그 스키마": ["schema"],
      "자산 IP": ["sonar-set-ip-address"],
      "데이터셋": ["dataset"],
      "위협 인텔리전스": ["matchfeed", "node-feed"],
      "행위 프로파일": ["behavior", "matchbehavior", "node-behavior"],
      "주소 그룹": ["matchblackip", "node-ip-blacklist"],
      "네트워크 대역": ["matchnet", "node-subnet-group"],
      "포트 그룹": ["matchport", "node-port-group"],
      "패턴 그룹": ["matchsig", "node-pattern-group"],
      "보고서": ["sonar-export-report", "sonar-send-report"]
    },
    "포렌식 명령어": {
      "윈도우 아티팩트": [
        "automatic-destinations-file",
        "custom-destinations-file",
        "evtx-file",
        "hive-file",
        "lnk-file",
        "ntfs-logfile",
        "ntfs-mft",
        "ntfs-usnjrnl",
        "prefetch-file",
        "reg-bam-entries",
        "reg-network-profiles",
        "reg-opensave-files",
        "reg-recent-docs",
        "reg-shellbags",
        "reg-shim-cache",
        "reg-user-assists",
        "recent-file-cache",
        "srum-application-resource-usages",
        "srum-energy-usages",
        "srum-long-term-energy-usages",
        "srum-network-connectivities",
        "srum-network-usages",
        "srum-push-notifications",
        "timeline-activities",
        "wer-file",
        "wmi-objects-data",
        "zipfile-entries"
      ],
      "리눅스 아티팩트": [
        "linux-arp-entries",
        "linux-connections",
        "linux-cron-jobs",
        "linux-env",
        "linux-failed-logins",
        "linux-hidden-files",
        "linux-logins",
        "linux-network-interfaces",
        "linux-no-owner-files",
        "linux-non-device-files",
        "linux-open-files",
        "linux-partitions",
        "linux-pipes",
        "linux-processes",
        "linux-recent-files",
        "linux-rkhunter",
        "linux-routes",
        "linux-setuid-files",
        "linux-shell-sessions",
        "linux-system-files",
        "linux-shell-commands",
        "linux-system-info",
        "linux-systemd-services",
        "linux-systemd-timers",
        "linux-tmp-files",
        "linux-users",
        "linux-user-groups",
        "linux-vmstats"
      ],
      "웹 브라우저 아티팩트": [
        "chrome-cookies",
        "chrome-downloads",
        "chrome-plugin-artifacts",
        "chrome-search-terms",
        "chrome-visits",
        "esedb-columns",
        "esedb-records",
        "esedb-tables",
        "eml-file",
        "firefox-downloads",
        "firefox-visits",
        "ie-cache-files",
        "ie-cookies",
        "ie-downloads",
        "ie-visits",
        "sqlite-records",
        "sqlite-tables"
      ]
    },
    "시스템 명령어": {
      "시스템": ["confdb", "system logs"],
      "통신 설정": ["system-syslog-tcp-senders"],
      "수집기": ["system loggers"],
      "테이블 및 데이터": [
        "system tables",
        "system count",
        "checktable",
        "copytable",
        "purge",
        "system logdisk",
        "system indexdisk"
      ],
      "룩업": ["system lookups"],
      "쿼리": [
        "system queries",
        "system streams",
        "system ceptopics",
        "system cepclocks"
      ],
      "PCAP 디바이스": ["system pcapdevices"],
      "센트리": [
        "system sentries",
        "sentry-arp-cache",
        "sentry-bundles",
        "sentry-jstack",
        "sentry-logger-configs",
        "sentry-logger-connect",
        "sentry-logger-create",
        "sentry-logger-deploy",
        "sentry-logger-disconnect",
        "sentry-logger-remove",
        "sentry-logger-set-interval",
        "sentry-logger-set-schedule",
        "sentry-logger-set-time-range",
        "sentry-logger-start",
        "sentry-logger-stop",
        "sentry-loggers",
        "sentry-netstat",
        "sentry-processes",
        "sentry-routing-table",
        "sentry-top-threads",
        "sentryswap"
      ],
      "스레드": ["system threads", "system topthreads"],
      "클러스터 노드": ["system nodes"],
      "라이선스": ["system license-usages"]
    },
    "함수": {
      "참조 함수": ["$()", "field()", "whoami()"],
      "타입 변환 함수": [
        "array()",
        "binary()",
        "date()",
        "dict()",
        "double()",
        "frombase64()",
        "fromhex()",
        "groups()",
        "int()",
        "ip()",
        "long()",
        "string()",
        "tobase64()",
        "tohex()"
      ],
      "타입 검사 함수": [
        "isnum()",
        "isnotnull()",
        "isnull()",
        "isstr()",
        "typeof()"
      ],
      "조건 함수": ["case()", "if()", "in()", "match()", "nvl()"],
      "문자열 함수": [
        "concat()",
        "contains()",
        "format()",
        "guid()",
        "indexof()",
        "kvjoin()",
        "lastindexof()",
        "left()",
        "len()",
        "lower()",
        "lpad()",
        "replace()",
        "reverseip()",
        "right()",
        "rpad()",
        "split()",
        "strjoin()",
        "substr()",
        "trim()",
        "upper()",
        "urldecode()",
        "urlencode()"
      ],
      "수치 함수": [
        "abs()",
        "acos()",
        "asin()",
        "atan()",
        "ceil()",
        "cos()",
        "exp()",
        "floor()",
        "log()",
        "log10()",
        "max()",
        "min()",
        "mod()",
        "pow()",
        "round()",
        "seq()",
        "sin()",
        "sqrt()",
        "tan()"
      ],
      "날짜 함수": [
        "ago()",
        "dateadd()",
        "datediff()",
        "datepart()",
        "daterange()",
        "datetrunc()",
        "epoch()",
        "now()"
      ],
      "IP 주소 함수": ["ip2int()", "ip2long()", "long2ip()", "network()"],
      "암호화 함수": [
        "decode()",
        "decrypt()",
        "encode()",
        "encrypt()",
        "hash()",
        "rand()",
        "randbytes()"
      ],
      "배열 함수": [
        "flatten()",
        "foreach()",
        "subarray()",
        "sumarray()",
        "unique()",
        "valueof()"
      ],
      "이벤트 컨텍스트 함수": [
        "evtctxget()",
        "evtctxgetvar()",
        "evtctxsetvar()"
      ],
      "객체 그룹 함수": [
        "matchbehavior()",
        "matchblackip()",
        "matchfeed()",
        "matchnet()",
        "matchport()",
        "matchsig()"
      ]
    },
    "집계 함수": [
      "array()",
      "avg()",
      "corr()",
      "count()",
      "cov()",
      "dc()",
      "estdc()",
      "first()",
      "last()",
      "max()",
      "median()",
      "min()",
      "percentile()",
      "slope()",
      "stddev()",
      "sum()",
      "values()",
      "var()"
    ]
  }
}


게다가 사내에서 만든 DB 의 종류만 해도 OLAP, ConfDB, 각종 인덱스 데이터 구조, Raft 등 너무나도 많은 내용이 있지만 각각의 내용의 난이도도 결코 쉽지 않다.
결국, 지원자가 이러한 내용을 미리 알 것이라 기대하기 힘들기에, 기본 CS 지식이 탄탄하고, 복잡한 맥락 속에서 문제 해결하는 것을 포기하지 않는 동료를 찾고 있다.

물론 명문대 출신이거나 각종 오픈소스에 기여했다면 채용 과정이 수월하겠지만 작은 회사들에서 제공할 수 있는 가치가 한정적인데다가 금전적으로 제시할 수 있는 상한도 한계가 있다. 물론 페이 외에도 업무 자체가 매력적인 경우가 있을 수 있고, 업무 방식이나 시간 등 협상에 사용할 수 있는 카드들은 다양하겠지만,
해당 인력들만 고집하기엔 현실적인 무리가 있을 것 같아서 대외적으로 증명되진 않았지만 니즈에 만족하는 지원자들을 찾을 순 없을까? 하는 의문이 들게된다. 더군다나 (지극히 당연하게도) 대부분의 지원자는 자신을 포장한다. 그 포장 속에서 원하는 사항들을 체크하고 우리 조직에 적합한지 체크해야하는데 모든 요소를 세세하게 체크하기엔 현실적으로 힘들다. 그래서 적은 노력으로 쉽게 파악하는게 중요하다.

그러면 잠재력을 효율적으로 판단하고 싶은데 대표적인 방법으론 포트폴리오로 제출된 코드에서 사용한 라이브러리 살펴보기 같은 방법들이 있다.
(절대 모든 코드를 볼 필요는 없고, 요즘 IDE 는 많은 기능들을 제공하기에 그리 오랜시간이 걸리지 않는다.)

구직자가 신입 ~ 주니어라면 CS 지식에 대한 질문 외에는 진행했던 프로젝트를 기준으로 판단할 수 밖에 없을 것이기에 보통은 프로젝트를 첨부한다. 해당 프로젝트에서 사용하고 있는 라이브러리의 버전이 최신 기준인지 체크하고 만약 아니라면 버전을 높였을 때 어떤 문제들이 발생하는지 혹은 Deprecated 된 코드를 사용하고 있는지 IDE 를 통해 체크해도 꽤 괜찮은 참고가 된다.

다들 아시다시피 최신 버전에 대한 레퍼런스는 찾기 힘들다. 누가 알아주지 않더라도 본인의 제품(프로젝트)에 그런 수고로움을 아끼지 않고 문제없이 작동하도록 반영했다면 그것만으로도 멋진 지원자가 아닐까?

(쓰다보니 지금 이 타이밍에 지인분을 홍보하려고 한다. 지금 회사에 추천하고 싶지만 아쉽게도 TO 가 열린 상태가 아니라서 추천하진 못하지만, 위 내용들을 다 부합하는 좋은 지원자가 있으니 혹시 관심있으시다면 ian.ilminmoon@gmail.com 연락주시면 연결해드리겠습니다)

 

그렇다면 구직자 입장에서는?

구직자 입장에서도 쓰려고 했는데

구인자 입장을 읽다보면 어느정도 답을 찾으셨을 것 같다. (결국 기업들이 어떤 지원자를 원하는지에 대한 니즈를 파악하고 그 니즈를 제공하는것인데, 가장 큰 부분은 정해져 있으니... 사소한 부분을 챙기고 싶은 욕심이 들더라도 Amdahl's law 를 떠올렸었다.)

물론 본인이 명문대 출신이거나 각종 오픈소스에 기여했다면 그 자체만으로 능력이 증명되었다고 여기는 기업들의 러브콜을 받을 것이다. (예를 들어, Google 출신이라는 타이틀 만으로 많은 신뢰를 주는 것은 사실이다. 그래서 기술력으로 유명한 곳을 노리는것도 충분히 좋은 방법.)

결국 내 상태(얼마나 많은 지식이 있는지, 보여줄 수 있는 프로젝트의 퀄리티 등)에 따라 선택할 수 있는 선택지가 달라지고, 어떤 강점을 더 어필하고 싶은지에 따라 원하는 회사를 선택하면 좋을 것 같다.
예를 들어, 특정 지식이 필수적인 조직에 들어가고 싶다면 해당 지식 및 기반 지식을 탄탄하게 쌓는 방향으로 가고,
만약 프레임워크의 숙련도를 통해 빠르게 제품을 제공하는 것을 보여주고, 그 장점을 살릴 수 있는 곳을 희망한다면 현재 본인이 가진 기술력을 최대한 녹여낸 프로젝트를 만드는 것이 중요할 것 같다.

더 나아가 내가 작업한 내용의 퀄리티를 끌어올리려는 시도를 멈추지 않는 사람이라면 누구라도 뽑고 싶은 지원자일 것 같다.
그것은 단순히 저런 체크 포인트가 아니더라도 어떤 방식으로든 드러나게 되어있기에, 그 매력을 알아봐주는 회사에 가는 것도 추천한다.
(지원자의 가치를 잘 알아주는 회사는 지원자의 강점을 활용하려 노력할테고 결국 지원자에게도 좋은 회사일 가능성이 높을테니)

 

마지막으로 커리어에 대해 고민하고 계실 분들이라면 많은 도움이 될 오시영님의 "차이를 만드는 커리어 굴리기" 를 남기면서 보잘 것 없는 글을 마치고자 한다.

https://siyoung.org/kr/posts/2019/career-gap-strategy

 

발표: 차이를 만드는 커리어 굴리기 | 오시영

2019년 05월 30일 · 765 단어 · 4분 소요 🌊 2024년 글 개발 커리어 파도타기에서 약간 이어집니다. 진로 개발에 대해 발표를 할 기회가 있어서 기록해본다. 문제: 시작은 비슷해 보이는 사람들이 왜

siyoung.org

 

Contact

ian.ilminmoon@gmail.com

'-' 카테고리의 다른 글

첫 회고  (3) 2023.05.28