당신은 5년 차인가요, 1년 차 5번인가요?

5년 차 자바 경력이 단 60분의 면접으로 무너졌다

📌개요

메일함에서 Medium Daily Digest를 확인하다가 발목이 잡혔다. 공감할 수 있는 내용이고 자신의 태도에 대해 고민해 볼 수 있는 좋은 글이라고 생각한다.

이 글에서 ‘우리’, ‘자신’이라는 키워드가 자주 등장할 텐데 만약 본인은 포함되지 않는다고 생각한다면 빠르게 뒤로 가기, 탭 닫기를 통해 시간을 아끼길 바란다.

“나의 5년 자바 경력이 60분 면접 만에 무너졌다 - My 5 Years of Java Experience Collapsed in a 60-Minute Interview"는 자극적인 제목보다 더 충격적이었던 건, 그 안의 질문들에 선뜻 답하지 못하는 나의 모습이었다.

우리는 모두가 자신의 문제를 해결하기 위해 바쁘게 생산적인 일을 한다. 매일 스프린트를 쳐내고, 라이브러리를 가져다 쓰고, 비즈니스 로직을 구현한다. 하지만 ‘어떻게(How)’ 돌아가게 만드는 것에 익숙해진 나머지, ‘왜(Why)’ 그렇게 설계되었는지에 대해서는 추상화라는 장막 뒤로 숨겨두곤 한다.

이 포스팅은 원작자가 겪은 뼈아픈 면접 기록을 통해, 우리가 놓치고 있었던 ‘백엔드 개발자의 기술적 깊이’란 무엇인지, 그리고 ‘연차’를 ‘실력’으로 치환하기 위해 어떤 태도가 필요한지 정리해본다.

📌내용

어느 5년 차 개발자의 뼈아픈 고백

원문: My 5 Years of Java Experience Collapsed in a 60-Minute Interview

“간단한 것부터 시작하죠.” 면접관의 이 한마디가 비수가 되어 돌아오기까지는 그리 오랜 시간이 걸리지 않았습니다. 5년 동안 자바를 다뤄왔고 수많은 마이크로서비스를 배포했으며 운영 환경의 복잡한 버그들을 잡아왔던 한 개발자의 자신감은 60분 만에 산산조각이 났습니다.

최근 해외 개발 관련 글에서 공감을 얻고 있는 My 5 Years of Java Experience Collapsed in a 60-Minute Interview라는 글의 이야기다. 이 글은 단순한 면접 탈락 수기가 아니다. 우리가 ‘경험’이라고 부르는 시간이 얼마나 허망하게 쌓여있을 수 있는지에 대한 자기반성이자 동시에 우리 모두에게 던지는 경고장이다.

나 역시 이 글을 읽으며 묘한 서늘함을 느꼈다. “내가 저 자리에 있었다면 과연 면접관의 꼬리 질문을 견뎌낼 수 있었을까?“라는 질문에 선뜻 “예쓰"라고 답할 수 없었기 때문이다. 우리는 과연 경력이라는 이름 뒤에 숨어 성장을 멈춘 것은 아닐까?

왜 우리는 경험을 실력이라 착각하는가?

원작자는 5년의 경력을 가졌음에도 Arrays.asList()로 생성한 리스트에 요소를 추가할 때 왜 에러가 나는지, 왜 공유 자원에 대한 동시성 이슈를 해결할 때 AtomaticInteger가 대안이 될 수 있는지 명확히 설명하지 못했다. 왜 이런 일이 벌어질까?

1. 숙련도와 전문성의 괴리: 사용과 이해는 다르다.

우리는 도구에 익숙해지는 것을 실력이라 착각하곤 한다.

  • 숙련도(How): 특정 라이브러리의 API를 호출하고 늘 쓰던 패턴으로 서비스를 구축하는 능력.
  • 전문성(Why): 그 도구가 내부적으로 어떻게 동작하며, 왜 다른 대안이 아닌 이 기술을 선택했는지 논리적으로 증명하는 능력. 시니어에게 요구되는 것은 전자가 아니라 후자다. 하지만 많은 이들이 프레임워크가 제공하는 편리함(추상화)에 안주하며 내부 원리를 궁금해하지 않는다.

2. 업무의 반복성: 1년 차 5번 반복의 함정

원작자는 뼈아픈 통찰을 남겼다. “나는 5년 동안 코딩해 왔지만, 5년 동안 배우지는 않았다"라는 것이다.

  • 매일 비슷한 비즈니스 로직을 짜고, 기존 템플릿을 복사해 새 서비스를 만들며 바쁘게 보낸 시간은 우리를 익숙한 개발자로 만들 뿐이다.
  • 새로운 기술적 난제에 부딪히고 이를 해결하기 위해 깊게 파고드는 경험이 없다면, 그것은 5년의 경력이 아니라 1년의 경험을 5번 반복한 것에 불과하다.

우리는 수평적으로 경험을 확장하는 데 급급해 정작 한 분야의 뿌리를 깊게 내리는 수직적 성장을 소홀히 해왔을지도 모른다.

백엔드 개발자에게 요구되는 진짜 깊이란?

원작자가 마주했던 질문들은 결코 지엽적인 말장난이 아니었다. 이는 백엔드 개발자가 매일 다루는 도구의 한계점과 동작 원리를 얼마나 깊게 인지하고 있는지를 묻는 본질적인 질문들이었다.

1. 자바 기본기: Arrays.asList()와 추상화의 함정

단순히 “에러가 난다"를 아는 것과 그 이유가 ArrayList라는 이름 뒤에 숨겨진 구현의 차이 떄문임을 아는 것은 다르다.

Arrays.asList()는 우리가 흔히 쓰는 java.util.ArrayList가 아니라, 내부 클래스인 Arrays$ArrayList를 반환한다. 이는 ‘고정 크기’ 배열을 래핑한 것에 불과하기 때문에 add() 호출 시 예외를 던지는 것이다.

우리가 사용하는 인터페이스(List) 뒤에 어떤 구체적인 구현체가 숨어 있는지 확인하는 습관이 없다면, 런타임에 예상치 못한 사이드 이펙트를 마주하게 된다.

2. Concurrency: 동시성 이슈를 해결하는 논리적 근거

공유 자원 문제에 단순히 synchronized를 붙이는 것은 가장 쉬운 해결책일 수 있지만, 성능 최적화 관점에서는 최악일 수 있다. 면접관이 던진 AtomaticInteger라는 대안은 Lock-based(비관적 락)와 CAS(Compare-And-Swap, 낙관적 락)의 차이를 이해하고 있는지 묻는 것이다.

실무에서 발생하는 데드락이나 성능 저하 문제는 대개 이런 원리에 대한 무지에서 시작된다. “돌아가니까 됐다"는 시니어의 답변이 될 수 없다.

3. 시스템 설계: Trade-off의 예술

레이트 리미터 설계 예시에서 중요한 건 ‘정답’이 아니다. 왜 고정 윈도우가 아닌 슬라이딩 윈도우를 택했는지, 토큰 버킷 방식이 트래픽 버스트를 어떻게 처리하는지 설명할 수 있어야 한다.

모든 기술 선택에는 비용이 따른다. 시니어는 성능, 복잡도, 유지보수성 사이에서 최적의 균형점을 찾는 ‘의사결정권자’여야 한다.

얕은 지식을 온전히 내 것으로 만드는 전략

사실 이건 엉덩이 붙이고 앉아서 사투를 벌이며 체화하는 것 말고 왕도가 있을까 싶다. 자신에게 맞는 효율적인 방법을 찾아 시간을 아낄 수 있다면 더할 나위 없이 좋은 가치가 된다. 하지만 효율을 핑계로 깊이 파고드는 고통을 회피하고 있는 것은 아닌지 스스로 경계해야 한다.

파편화된 지식을 경험으로 연결하기 위해 내가 실천하고 있는, 그리고 원작자가 제안한 ‘리셋’ 전략이다.

1. 소스 코드 여행(Go to Declaration)

IDE에서 라이브러리 메서드를 사용할 때 Ctrl+Click을 누르는 습관을 들여야 한다. 내가 호출한 메서드가 내부적으로 어떤 객체를 생성하고 어떤 예외를 던지는지 직접 눈으로 확인하는 과정이 쌓여 기술적 깊이가 된다.

2. 문서화와 언어화

머릿속으로 안다고 생각하는 것과 그것을 타인에게 설명하는 것은 천지 차이다. 학습한 내용을 블로그에 정리하거나 동료에게 공유해보자. 논리의 빈틈은 설명하려 할 때 비로소 드러난다.

PoC(Proof of Concept) 중심 학습

이론으로만 배운 개념은 금방 휘발된다. AtomaticInteger가 정말 synchronized보다 빠른지, 1000개의 스레드를 돌려 직접 벤치마크 코드를 작성해 보아라. 직접 현상을 재현하고 데이터를 눈으로 확인한 지식은 결코 무너지지 않는다.

연차의 무게를 감당하는 개발자가 되기 위해

원작자는 마지막에 이렇게 말한다. “당신의 경험은 그것을 깊이 있게 설명할 수 있을 떄만 의미가 있다.”

5년, 10년이라는 숫자가 주는 안락함에 속지 말자. 오늘 내가 작성한 코드 한 줄의 ‘이유’를 설명하지 못한다면 우리는 그저 거대한 프레임워크의 부품으로 머물 뿐이다. 연차에 어울리는 무게감은 내가 아는 기술의 뿌리에서 나온다. 내일의 우리는 오늘보다 조금 더 깊은 개발자이기를 바란다.

🎯결론

경력은 단순히 시간이 흐른 결과가 아니라 그 시간 동안 쌓아 올린 논리적 근거의 총합이다. 효율을 핑계로 깊이 파고드는 고통을 회피하고 있는 것은 아닌지 스스로 경계해야 한다.