Living with Software

Yejun Kim – yejun@hyperthreading.dev

이 글에서는 포화된 개발자 시장에서 개발자의 본질과 경쟁력에 대해 다시금 살펴볼 것이다.

아마 이 글은 0~1년차 주니어 개발자와 채용 과정 설계에 어려움을 겪는 구인자에게 가장 도움이 될 것이다. 개발자의 본질을 살펴봄으로써 구직자 입장에서는 어떻게 하면 경쟁력을 확보할 수 있는지, 면접관 입장에서는 어떻게 해야 좋은 개발자를 채용할 수 있는지 파악할 수 있을 것이다.

최종적으로, 개발자로서 성장하기 위한 문제 중심 케이스 스터디를 제시하고자 한다.

일반적으로 개발을 시작하는 방식에 대하여

개발자 꿈나무 A가 개발을 배우기로 했다. A는 주변 개발자 친구들에게 혹은 인터넷 커뮤니티에서 프론트엔드를 공부해야 하는지, 백엔드를 공부해야 하는지 물어본다. 그리고는 어떤 기술 스택을 공부하면 되는지 알려주는 로드맵을 참고한다. 부트캠프를 등록하든 자습을 하든 비슷할 것이다. 배워야 하는 프레임워크의 목록이 있고 이를 따라 공부한다.

그 로드맵은 대략 이런 식이다.

HTML, CSS, Javascript –> React –> Redux –> Next.js –> TypeScript ... (기타 등등)

이런 식으로 개발을 배우는 것이 현재 아주 일반적이다. 대부분의 부트캠프 커리큘럼은 프레임워크에 초점을 맞추고, 학부생들은 리액트 다음엔 무엇을 공부해야 하는지 물어보곤 한다. 물론 취업에 있어서는 가시적이고 빠르게 개발 도구를 익혀야 한다고 생각하는 것이 당연하다.

이 글에서 도구를 익히는 것 자체를 비판하려는 것은 아니지만, 이 단계에서 멈추게 되면 분명 개발자로서 역량의 한계를 마주칠 것이다. 왜일까?

해결책 중심 사고과 문제 중심 사고

학교 다니던 시절에 수학 공부를 생각해보자. 특정 문제에 대한 풀이 방식과 답을 외워봤자 기출 변형 문제가 나오면 속수무책이다. 결국은 그 원리를 이해해야 한다. 여기서 힌트를 얻을 수 있다.

나는 암기식 사고 방법을 해결책 중심 사고이라고 부른다. 프레임워크나 도구 사용법을 외우는 것 또한 이와 비슷하다. 정해진 문제에 정해진 해결책을 제시하는 것이기 때문이다.

나는 이와 대조되는 문제 중심 사고을 제시하고자 한다. 문제 중심 사고는 왜 이런 해결책이 나오게 되었는지, 그리고 왜 이렇게 해결해야 했는지 기저에 있는 원리에 대해 질문한다.

한쪽이 완전히 잘못된 것이라고 오해하면 곤란하다. 해결책 중심 사고는 특정 문제를 해결하기 위해 필요한 기본 지식을 몸으로 체득하는 데에 효과적이다. 그러나 한쪽에 치우쳐서도 안된다. 해결책만 학습할 것이 아니라, 문제 중심 사고를 병행해야 한다. 문제 중심 사고는 해결책 중심 사고를 보완한다.

참고로 문제 중심 사고는 세상에 존재하지 않던 새로운 방식이 아니다. 단지, 탐구하고 학습하는 자세가 개발에 있어서도 중요함을 강조하고자 내가 빌려쓴 단어일 뿐이다.

그런데 정말 개발자에게 문제 중심 사고가 필요할까? 기술 스택에 대한 전문 지식만 가지고 있으면 되는 것이 아닐까?

개발자에게 문제 중심 사고가 필요한 이유

현재 취업 시장에서는 더 이상 React, Redux, Next.js를 알고 있는 것만으로는 충분하지 않다. 그렇다면 새로운 기술 스택을 익혀야 할까? 부트캠프에서 막 나와 혹은 학부를 막 졸업에 사회에 나가 채용 면접을 보는 입장이 되면 알 수 있다. 면접관이 된 노련한 엔지니어는 이미 알고 있다. 이력서에 잔뜩 쓰여있는 기술 스택은 믿을 것이 되지 못한다.

그래서 면접관은 개발자에서 무엇을 봐야 할까? 면접관은 개발자가 문제를 어떻게 해결하는지, 그리고 그 문제를 얼마나 이해하고 있는지를 보고 싶어한다. 왜냐하면 개발자의 팀의 일원으로서 지금 팀의 목표와 상황에 알맞는 해결책을 제시해야 한다.

실제로 개발자가 되어 어떤 문제를 마주치는지 알아보자.

실제로 개발자가 마주치는 문제

실무에서 주로 마주치는 문제와 그 문제 해결에 영향을 미치는 요소는 프레임워크 혹은 특정 기술로는 해결할 수 없다. 반드시 문제 상황을 제대로 이해하고 상황에 맞는 해결책을 찾아야 한다.

예를 들어, 서비스의 로그 데이터를 저장해야 하는 상황이라고 해보자. 일반적인 해결책으로 단순히 파일로 저장하거나, S3와 같은 오브젝트 스토리지에 저장하는 방법이 있다. 그러나 이것이 최선일까? 다음과 같은 질문을 던져보자.

  • 로그 데이터를 어디에 얼마나 저장해야 할까?
  • 로그 데이터를 저장하는 이유는 무엇일까? 로그 데이터를 어떻게 사용할 것인가? 트래픽 측정이 목표인가? 유저 행동 분석이 목표인가?
  • 얼마나 자주 많이 읽을 것인가? 어떤 형태로 읽을 것인가?
    • 단순히 라인 수를 카운트하면 되는가?
    • 특정 시간대의 트래픽을 분석해야 하는가?
    • 문자열 검색이 필요한가?

이런 질문에 따라 답이 달라진다. 초보자들이 많이 들어봤을 법한 ELK 스택을 사용하면 로그 데이터를 쉽게 검색하고 분석할 수 있지만, 이를 위해선 추가적인 비용이 들고, 관리해야 할 것이 많다. 이런 상황에서는 ELK 스택을 사용하는 것이 최선일까?

어떤 답을 내리느냐에 따라, 단순히 하루치의 업무량이 될 수 있고, 학습과 유지보수를 포함해 한 달 이상이 걸릴 수 있다.

근본적인 원리와 상황을 파악하지 못한 채 이미 누군가가 짠 코드를 가져다 사용하기만 한다면 위와 같은 상황에서 유연하게 대처할 수 없다. 패턴화된 것을 자동화하는 LLM과 같은 기술이 더 발전한다면, 단순히 코드를 짜는 것 이상으로 상황을 파악하고 깊이 있게 문제를 분석하는 역량은 더욱 중요해질 것이다.

개발자의 본질

결국 개발자의 본질은 다음과 같이 요약할 수 있다.

  1. 정말 현재 상황에 유용한 것이 무엇인지 파악하는 것
  2. 이를 통해 빠르고 정확하게 가치를 만들어내는 것

이 두 가지 일을 잘 하려면 어떤 도구가 왜 유용한지, 어떤 가치를 만드는지 파고들고 이해하려고 노력해야 한다. 이런 일을 잘 하려면 결국 필요한 것은 사고력판단력이다.

이러한 실무와 연관된 사고력과 판단력을 평가하려면 결국 문제를 얼마나 깊게 이해하고 해결할 수 있는지 평가해야 한다. 알고리즘 풀이 면접은 이런 사고력을 평가하기 위한 아주 극단적인 형태라고 볼 수 있다. 그러나, 알고리즘 면접은 개발자로서 갖춰야 할 역량의 일부분을 평가할 뿐이다. 실무와 연관이 없다는 비판도 많은 편이다.

나는 앞으로의 면접은 결국 알고리즘 풀이 면접보다는 실제로 실무과 연관된 사고력을 평가하는 방식으로 변화할 것이라고 생각한다.

그래서 어떻게 공부해야 하나요?

나는 이런 문제를 해결하기 위한 방법으로 문제 중심 케이스 스터디을 제시하고자 한다. 문제 중심 케이스 스터디 프레임워크나 특정 해결책이 아닌 문제 자체를 나열하고 깊게 분석한다. 일종의 수학 문제의 해설서와 같은 역할을 하는 것이다. 이를 통해 사고력과 판단력을 키우는 데에 도움을 줄 것이다.

예를 들어 아래와 같은 케이스에 대해 고민해볼 수 있다. 훨씬 어려운 문제는 많지만 공감대를 형성하기 위해 우선 비교적 단순한 기능의 구현 문제를 살펴볼 것이다.

  • 이미지 업로드 기능의 구현
  • 페이지네이션 / 검색 기능 구현
  • 대시보드 성능 최적화

이중 첫번째 사례를 자세히 살펴보자. 한번 문제를 어떤 방식으로 풀 수 있는지 고민해보자.

케이스 스터디 1: 이미지 업로드 시스템 설계

문제 상황

당신은 오이마켓이라는 소셜 서비스를 운영하는 스타트업에서 일하고 있다. 사용자들이 이미지를 업로드하고 공유할 수 있는 기능을 개발해야 한다.

단순한 접근

많은 주니어 개발자들은 다음과 같이 접근할 것이다:

  • React로 프론트엔드 구현
  • Node.js로 백엔드 API 구현
  • 이미지를 서버의 로컬 저장소에 저장

문제 중심 접근

더 깊이 있는 접근을 위해선 다음과 같은 질문을 던져야 한다.

확장성: 사용자가 늘어나면 어떻게 될까? 100명의 사용자일 경우와 1만명의 사용자일 경우엔 어떨까?

  • 서버의 저장 공간은 충분할까?
  • 동시에 많은 업로드 요청이 들어오면 어떻게 처리할까?

성능: 이미지 로딩 속도를 어떻게 최적화할 수 있을까?

  • CDN을 사용해야 할까?
  • 이미지 리사이징이 필요할까?

보안: 악의적인 파일 업로드를 어떻게 방지할 수 있을까?

  • 파일 타입 검증은 어떻게 할까?
  • 업로드 크기 제한은 어떻게 설정할까?

비용: 저장소 비용을 어떻게 최적화할 수 있을까?

  • 클라우드 스토리지 서비스를 사용하는 것이 좋을까?
  • 장기 보관이 필요 없는 이미지는 어떻게 관리할까?

연관 개념 및 사고 프레임워크

효과적인 해결책을 위해 프레임워크나 도구에 익숙할 뿐만 아니라 다음과 같은 개념을 이해해야 한다.

  • 이미지가 업로드되어 저장되고 불러오는 과정과 구성 요소를 알고 있어야 함 (API, 파일, 스토리지)
    • 프론트엔드와 백엔드의 어떤 부분을 거쳐 최종적으로 스토리지에 저장되는지 알아야 함
    • 스토리지의 종류와 특징을 알아야 함 (인 메모리, 블록 스토리지, 오브젝트 스토리지)
    • 일반적인 파일 그리고 이미지 파일의 특징을 알아야 함 (크기, 포맷, 해상도)
    • CDN을 사용함으로써 이미지 로딩 속도를 최적화할 수 있는 이유를 알아야 함
  • 각 구성 요소의 변수와 제약 조건을 고려해야 함 (용량, 속도, 보안, 비용)

마치며

위 케이스를 살펴보면 뜬금없는 면접 질문보다 훨씬 실무와 연관된 문제를 다루고 있다는 것을 알 수 있을 것이다. 그리고 개발 과정에 대한 전반적인 요소를 다루고 있음을 알 수 있다. 이런 문제를 얼마나 깊게 이해하고 해결할 수 있는지가 개발자의 역량을 결정한다.

문제 풀기가 어렵다면 학창 시절에 수학 공부를 하듯 문제에 대해 계속 생각해보며, 필요한 개념을 더 깊이 탐구하고 이해하려고 노력해야 한다. 그래야만 역량을 기를 수 있다.

이 글을 통해 개발자로서의 본질과 경쟁력에 대해 다시금 생각해보았으면 좋겠다. 개발자로서의 여정은 지속적인 학습과 도전의 과정이다. 최신 기술을 쫓는 것이 아니라 문제를 깊게 이해하고 해결하는 능력을 키우는 데 집중해야 한다. 이것이 업계에서 인정받는 개발자가 되는 지름길이다.

앞으로의 계획

앞으로 양질의 케이스 스터디와 해설을 꾸준히 업로드하려고 한다. 비록 해당 문제는 실무에서 마주치는 문제 중 단순한 편에 속하지만, 앞으로 좀 더 복잡하고 다양한 문제를 다룰 것이다.

구직자에게는 실무 중심으로 문제 해결 능력을 기를 수 있는 기회가 되고, 면접관에게는 좋은 개발자를 채용하기 위한 질문의 예시가 될 것이다. 단지 이런 케이스 스터디가 경쟁에서 승리하기 위한 수단으로 쓰이는 것이 아닌, 역동적으로 변화하는 개발자 시장이 성숙하는데 도움이 되었으면 하는 바람이다.

#homelab #k8s

Kubernetes에서 Node Affinity가 있는 Storage를 가진 서비스가 있다고 하자. 여기서의 Storage는 Database와 Filesystem 혹은 Object Storage 전반을 말한다. 해당 노드가 하드웨어 전원 공급 혹은 발열 등의 문제로 꺼진다면 어떻게 될까? 적어도 그 문제를 해결할 때까지, 어쩌면 문제를 파악하기까지도 하루 이상이 걸릴 것이다. 스냅샷을 통해 타 노드에서 복제하더라도 말이다. 그 동안 서비스는 마비될 것이다. 따라서 Storage에 대한 HA 구성이 필수적이라고 할 수 있다. 적어도 그렇게 해야만 하는 하드웨어 환경과 비즈니스적인 상황을 가정하고 있다.

Homelab에서 비즈니스 수준 서버를 구축해야 하는 황당한 문제이긴 하지만, 해볼만한 가치가 있다고 생각한다.

Zulip과 Anytype의 서버를 HA 구성으로 하기 위해선, Persistent Storage의 복제가 필수적이다. 그래야 Node Affinity의 영향을 줄일 수 있다. 이를 위해선 DB Standby 구성, Ceph나 Longhorn, MinIO 등을 Kubernetes 상에서 구동해야 한다. 하나씩 천천히 살펴보도록 하자.

DB는 생각보다 간단하다. 문서를 읽으면 된다. Operator에서 아마 Parameter를 제공할테니, 기존 Helm Chart를 수정해, 사전에 Operator를 통해 생성한 Postgres 혹은 MongoDB Node를 사용하도록 하면 된다. DB에서 보장하는 Durability는 DB마다 다르기야 하겠지만, 적어도 서비스가 알아서 해결 가능한 범위일터다.

Block Storage의 Replication은 좀 더 문제가 복잡한데, Ceph나 Longhorn은 Operator 혹은 Helm을 이용하면 편리하게 설치할 수 있으나, Longhorn이 어떤 정도의 복제를 보장하는지 알 도리가 없고, 무엇보다 레딧 포럼에서는 데이터를 날렸다는 이야기를 가끔 본다. 이전 회사에서도 Longhorn이 설명하기 어려운 동작을 하는 경우를 많이 보았다.

포럼에서 Ceph를 10년이 넘게 잘만 쓴다고 하니 Longhorn을 선택지에 넣고 싶지 않다. 하지만 k8s의 distribution을 k3s로 선택한 이상, rook 등으로 ceph를 구성하는 것이 어려워보인다. distribution을 바꾸는 것은 또 하나의 일이 된다. Talos로 바꿔야 할까? Longhorn을 계속 사용해도 될까?

다행히 MinIO는 이미 만들어진 Block Storage를 기반으로 쌓기만 하면 될 것이다.

요샌 이런 고민을 계속하고 있다. 빠르게 해결할 수 있다면 좋으련만.

#homelab #k8s Kubernetes 클러스터를 Homelab으로 구축한지 1개월째. 당초 목적은 self-hosted app을 잔뜩 올려놓자는 것이었지만, (거기에 내 재미까지 더할 수 있으니) 이런 프로젝트가 으레 그렇듯 시작은 거창하나 끝은 미미하다. 겨우 zulip 정도가 쓸만하게 돌아가고 있다. anytype node를 추가하는 것도 계획중이다. 그러나 사용처와 관련 없는 엔지니어링적인 개선 사항이 보이는 것은 그나마 이 짓을 계속할 용기를 주는 듯 하다. 모든 앱과 스토리지가 HA 구성이 되면 좋겠다. 조악한 하드웨어로 만든 노드 한 두개쯤 망가져도 잘 돌아가면 좋겠다.