반응형
반응형

[AI] AI 오케스트레이션: 여러 AI 에이전트를 조율하여 프로젝트를 완수하는 리더십.

 

https://app-place-tech.com/post/dd7ab6d3-b94e-434e-a960-ec172557a885

 

AI 시대 개발자 수요 전망 분석 (제번스의 역설 관점 포함)

주니어 절벽과 채용 양극화: AI 도구 도입으로 생산성이 최대 56% 향상되면서 단순 코딩 비중이 높은 신입 채용은 급감(국내 기준 약 43% 감소)한 반면, AI를 활용해 즉각 성과를 내는 숙련된 시니어

app-place-tech.com

 

AI 시대 개발자 수요 전망 분석 (제번스의 역설 관점 포함)

소프트웨어 산업의 가장 뜨거운 화두인 'AI 도입에 따른 개발자 수요 전망'에 대해 심층적인 분석을 공유해 보고자 합니다.

2022년 말 챗GPT의 등장 이후, 개발 현장에서는 "이제 코딩은 AI가 다 하는데, 개발자가 더 필요할까?"라는 근본적인 의문이 제기되고 있습니다. 특히 주니어 개발자들의 채용 문턱이 높아지면서 위기감이 고조되고 있는 것도 사실입니다. 하지만 경제학적 이론과 현재 글로벌 시장의 지표를 교차 검증해 보면, 우리는 단순히 '대체'의 시대를 넘어선 '수요의 대폭발' 시점에 서 있을지도 모릅니다.

1. 생산성의 임계점 돌파: "코딩의 한계 비용이 0에 수렴하다"

인공지능 코딩 어시스턴트는 이제 단순한 보조 도구를 넘어섰습니다. 통계에 따르면 AI를 활용하는 개발자는 비활용 그룹 대비 업무 속도가 약 55.8% ~ 56% 향상되는 것으로 나타났습니다. 깃허브(GitHub)의 데이터에서도 AI 도구 사용 시 주당 코드 배포량이 평균 46% 증가하며 실질적인 생산성 폭발이 입증되고 있습니다.

이러한 변화는 개발자 1인이 감당할 수 있는 프로젝트의 규모와 복잡도를 비약적으로 높였습니다. 이제 구글 내 신규 코드의 25% 이상이 AI에 의해 생성되고 있으며, 인간 엔지니어는 이를 검토하고 승인하는 '디렉터'의 역할에 집중하고 있습니다.

2. 고용 시장의 양극화: '주니어 절벽'과 시니어 레버리지

하지만 생산성 향상의 혜택은 경력 수준에 따라 다르게 나타나고 있습니다. 현재 고용 시장에는 이른바 '주니어 절벽' 현상이 관측됩니다.

  • 주니어의 위기: 단순 구현 및 반복 업무(Boilerplate, Test Case 작성 등)를 AI가 저렴하게 대체하면서, 한국 내 IT 신입 채용 공고는 전년 대비 18.9%에서 많게는 43%까지 급감했습니다.
  • 시니어의 가치 상승: 반면, AI가 쏟아내는 코드의 논리적 오류를 잡아내고 복잡한 아키텍처를 설계할 수 있는 숙련된 시니어에 대한 수요는 여전히 견고합니다. 실제로 26세 이상의 숙련 노동자 고용은 오히려 6~9% 성장하는 기염을 토하고 있습니다.

3. 제번스의 역설(Jevons Paradox): 왜 수요는 줄어들지 않는가?

그렇다면 개발자의 총 수요는 결국 줄어들까요? 경제학의 '제번스의 역설'은 정반대의 미래를 시사합니다. 기술 발전으로 어떤 자원의 이용 효율이 높아지면 비용이 낮아지고, 이는 오히려 해당 자원의 총 소비량을 늘린다는 이론입니다.

  1. 잠재 수요의 현실화: 과거에는 높은 개발 단가 때문에 포기했던 소규모 프로젝트(사내 자동화 툴, 마이크로 SaaS 등)들이 AI 덕분에 경제성을 갖게 되며 시장이 확장됩니다.
  2. 복잡성의 역설: 코딩 비용이 낮아지면 기업은 개발자를 해고하는 대신, 더 많은 기능을 구현하고 더 자주 배포하는 전략을 택합니다. 깃허브의 풀 리퀘스트(PR) 수가 전년 대비 23~25% 증가했다는 점이 이를 뒷받침합니다.
  3. 시장 규모의 확대: 전 세계 AI 지출 규모는 2026년 2조 달러를 돌파할 것으로 보이며, 특히 맞춤형 소프트웨어 시장은 2034년까지 연평균 22.7%의 경이적인 성장을 기록할 전망입니다.

3-1. (반대의견) 개발자의 수요가 전반적으로 감소될 것 (대체론)

"효율성 증가는 곧 필요 인력의 감소를 의미한다."

비관적인 전망에 따르면, 소프트웨어 프로젝트 하나를 완수하는 데 필요한 총 노동 시간이 급감합니다. 기업은 비용 절감을 위해 채용 규모를 동결하거나 축소할 것입니다.

  • 기존 인력의 생산성 2배 증가 = 신규 채용 필요성 50% 감소
  • 단순 SI, 웹 에이전시 등 진입 장벽이 낮은 시장부터 타격
  • '코딩' 자체의 부가가치 하락

4. 대한민국 시장의 특수성: AX(AI 전환)의 가속화

한국 시장 역시 글로벌 흐름과 궤를 같이하고 있습니다. 네이버, 카카오 등 빅테크는 신규 채용을 축소하고 '경력직 수시 채용' 체제로 완전히 전환했습니다. 흥미로운 점은 현대자동차나 삼성SDS 같은 전통적인 대기업들이 AX(AI 전환)를 위해 개발자 채용을 오히려 확대하고 있다는 점입니다.

5. 결론: "코더에서 오케스트레이터로"

결국 미래의 개발자에게 요구되는 핵심 역량은 문법 암기가 아닌 '판단력(Judgment)'입니다.

  • 시스템 아키텍처 역량: AI가 만든 코드 조각들을 안전하게 결합하는 설계 능력.
  • 비즈니스 도메인 지식: 어떤 문제를 해결해야 비즈니스 가치가 생기는지 정의하는 능력.
  • AI 오케스트레이션: 여러 AI 에이전트를 조율하여 프로젝트를 완수하는 리더십.

우리는 지금 '개발자의 종말'이 아니라, 개발자의 업무가 더 가치 있고 전략적인 영역으로 격상되는 '위대한 소프트웨어 시대'의 입구에 서 있습니다. 기술의 효율성이 높아질수록 우리가 해결해야 할 세상의 문제는 더 방대해질 것이며, 이를 설계할 인간 개발자의 중요성은 역설적으로 더 커질 것입니다.

반응형
반응형

소프트웨어 개발의 미래는 소프트웨어 개발자들이다 

https://news.hada.io/topic?id=25448

  • 수십 년간 반복된 “프로그래머의 종말” 예언은 매번 틀렸으며, 기술 발전은 오히려 더 많은 개발자와 프로그램의 증가로 이어져 왔음
  • WYSIWYG, 4GL, No-Code, LLM 등 다양한 자동화 기술이 등장했지만, 실제로는 개발자의 필요성을 줄이지 못했음
  • LLM 기반 도구는 과거 기술보다 신뢰성과 유지보수성이 떨어지며, 대부분의 팀에서 생산성 저하와 품질 악화를 초래함
  • 프로그래밍의 본질적 어려움은 코드 작성이 아니라 인간의 모호한 사고를 논리적으로 변환하는 능력에 있으며, 이는 여전히 인간의 영역임
  • 따라서 AI가 개발자를 대체할 가능성은 낮고, 오히려 숙련된 개발자에 대한 수요가 더 커질 전망임

반복되는 “프로그래머의 종말” 주기

  • 지난 43년간 Visual Basic, Delphi, Executable UML, No-Code, Low-Code 등 다양한 기술이 프로그래머의 필요성을 없앨 것이라 주장되어 왔음
    • 1970~80년대에는 4GL, 5GL, 그 이전에는 Fortran, COBOL, 더 거슬러 올라가면 컴파일러 A-0조차 같은 예언을 받았음
    • 초기 전자식 컴퓨터 COLOSSUS는 물리적 배선으로 프로그래밍되었으며, 이후 세대가 “진짜 프로그래머가 아니다”라 조롱받기도 했음
  • 그러나 결과적으로는 프로그래머 수가 줄지 않고 오히려 증가, 이는 Jevons Paradox의 대표적 사례로 언급됨

LLM과 과거 기술의 차이

  • 과거 기술은 실제로 소프트웨어 생산 속도를 높이고 신뢰성도 확보했지만, LLM은 대부분의 팀에서 반대 효과를 보임
    • LLM은 코드 품질을 낮추고 유지보수를 어렵게 만들어 “LOSE-LOSE” 상황을 초래함
    • 동일한 프롬프트로도 동일한 결과를 내지 못하며, 생성된 코드에는 인간 개발자의 검증과 수정이 필수적임
  • AI가 개발자를 대체한다는 증거는 없음, 최근 인력 감축은 팬데믹 시기 과잉 채용, 금리 상승, 데이터센터 투자 집중 등 경제 요인 때문임

프로그래밍의 본질적 난제

  • 프로그래밍의 핵심은 인간의 모호한 사고를 논리적으로 정밀한 계산 사고로 전환하는 과정임
    • 이는 천공카드 시절부터 COBOL, Visual Basic, Python에 이르기까지 변하지 않은 어려움임
  • 자연어는 본질적으로 모호하고 비정확하기 때문에, 영어나 프랑스어로 프로그래밍하는 시대는 오지 않을 것이라 Dijkstra의 예언을 인용함
  • 이러한 사고방식을 배우는 것은 가능하지만, 모두가 즐기거나 잘할 수 있는 일은 아니며, 숙련된 인력의 공급은 항상 부족함

AI의 한계와 지속 가능성

  • AGI(범용 인공지능) 은 여전히 멀리 있으며, 인간 수준의 이해·추론·학습 능력이 필요함
  • 대규모 LLM은 막대한 비용과 손실을 초래하고 있어 장기적으로 지속 가능하지 않음
    • 시간이 지나면 모델이 학습한 언어·라이브러리 버전의 제약으로 인해 활용성이 떨어질 가능성 있음
    • 이러한 이유로 초대형 LLM은 ‘Apollo 달 탐사’처럼 비경제적 실험으로 남을 수 있음

미래의 개발 환경 전망

  • 가까운 미래의 소프트웨어 개발은 소규모 언어 모델 기반의 보조 도구가 프로토타입 생성이나 코드 자동완성 등 보조 역할을 수행하는 형태로 예상됨
  • 그러나 중요한 결정과 품질 확보는 인간 개발자가 주도하며, Jevons의 법칙에 따라 개발자 수요는 오히려 증가할 가능성 있음
  • 기업은 지금부터 숙련된 개발자 채용과 교육에 투자해야 하며, 이는 AI 유무와 관계없이 생산성과 신뢰성을 높이는 핵심 전략
반응형
반응형

Being good isn’t enough

잘하는 것만으로는 충분하지 않음 (joshs.bearblog.dev)

 

  • 기술적 역량만으로는 경력이 일정 수준에서 한계에 부딪힘
  • 영향력을 높이기 위해선 기술 역량, 제품 사고, 프로젝트 실행, 사람과의 협업 능력이라는 네 가지 축을 균형 있게 키워야 함
  • 약점을 찾고 성장하기 위해서는 피드백과 겸손이 핵심이며, 특히 존경하는 사람의 피드백을 받아 행동으로 옮기는 것이 가장 빠른 방법
  • 단순히 일을 잘하는 것뿐 아니라 보여주고 공유하는 것이 필요하며, 에이전시(agency, 주도성)를 갖고 스스로 기회를 만들고 실행하는 태도가 중요
  • 궁극적으로 원하는 것을 얻는 길은 그에 걸맞은 자격을 갖추는 것이며, 이는 노력 이상의 성장을 위해 반드시 필요한 접근방법임

 

 

커리어 조언의 모호함

  • 커리어 조언은 사람마다 좋은 조언의 기준이 다르기 때문에 모호함
    • 동일한 직함을 가진 두 사람도 필요한 조언은 크게 다를 수 있음
    • 누군가는 좋아하는 일, 다른 이는 의미 있는 일, 또 다른 이는 승진을 추구
  • 따라서 하나의 답은 없으나, 공통적으로 기술적 능력은 경력의 출발점임
    • 채용된 이유인 핵심 업무에서 탁월해야 하며, 초기에는 이로 주목받음
    • 예: 더 나은 코드, 보고서, 디자인은 자연스럽게 인정을 받음

기술적 실력만으로는 부족함

  • 초기에는 기술적 역량만으로도 인정받고 성장 가능
  • 하지만 일정 시점 이후에는 기술적 능력만으로는 차별화가 어려워짐
    • 동료들도 비슷한 수준의 기술적 역량을 보유
    • 더 큰 영향력을 발휘하려면 다른 역량 필요

영향력 확대를 위한 4가지 역량

  • 성공적인 노력은 4가지 핵심 역량의 결합으로 완성
    • 기술적 능력: 선택한 전문 분야에서의 숙련도
    • 제품 사고: 가치 있는 일을 식별하는 능력
    • 프로젝트 실행: 계획을 실현하는 능력
    • 인간관계 기술: 타인과 협업하고 영향을 미치는 능력
  • 이 4가지 역량은 모든 성공적 프로젝트에 필수적
    • 의미 있는 일을 실제로 일어나게 하는 것
    • 예: 제품 개발, 팀 협업, 프로젝트 완료 모두 이 역량의 조화 필요

역량 개발 방법

  • 네 가지 영역은 시간이 지나며 자연스럽게 익혀지지만, 의식적으로 훈련하면 더 빠르게 성장 가능
    • 자신의 약점을 찾는 데에는 피드백 겸손함이 핵심
      • 피드백은 개선점을 보여주고, 겸손함은 이를 받아들이게 함
    • 존경하는 사람에게 피드백을 요청하고 즉시 행동으로 옮김
      • 완벽한 계획을 기다리지 말고, 행동이 우선
  • 멘토링, 프로젝트 제안, 결과물 발표 등으로 역량 강화
    • 타인에게도 기회를 제공하며 협업 환경 조성

공개적으로 행동하기

  • 업무 성과는 스스로 말하지 않으면 인정받기 어려움
  • 일을 하고 그 결과를 공개적으로 보여주는 것이 중요, “일이 알아서 말해준다” 는 가정은 잘못임
    • 공개적으로 작업을 공유하고 결과를 알리는 습관 필요
    • 예: 프로젝트 발표, 팀 내 공유, 멘토링 활동

에이전시의 중요성

  • Agency(주도성, 자율적 실행력) 은 학력, 자격증, 운 보다 강력한 요소
    • 고주도성(High-agency) 인 사람은 일을 주도적으로 실현
    • 저주도성(low-agency) 인 사람은 기회를 기다리며 정체됨
  • 주도성은 선택 가능한 특성: 스스로 행동을 선택하면 됨

결론과 추천 자료

  • 경력 성장은 노력뿐 아니라 전략적 접근 필요
    • 단순히 열심히 일하는 것 이상으로, 영향력 확대에 집중할 것
    • 노력과 성장의 차이는 약점 보완·가시화·에이전시 실천에 달려 있음
  • 장기적으로 원하는 것을 얻는 최선의 방법은 그에 걸맞은 자격을 갖추는 것
  • 추천 도서
    • The Staff Engineer’s Path by Tanya Reilly: 경력 관리에 대한 깊은 통찰 제공. 매년 다시 읽음

 

 

 

반응형
반응형

개발자들이 조심해야 할 함정들

https://qouteall.fun/qouteall-blog/2025/Traps%20to%20Developers#summarization-of-traps

 

Traps to Developers | qouteall notes

A summarization of some traps to developers. There traps are unintuitive things that are easily misunderstood and cause bugs.

qouteall.fun

  • 개발자들이 흔히 빠지는 직관적이지 않은 함정을 정리하여, 발생하기 쉬운 버그의 원인을 소개함
  • HTML, CSS, Unicode/텍스트 인코딩, 부동소수점, 시간 등 다양한 기술에서 자주 발생하는 문제점들을 다룸
  • 각각의 언어와 프레임워크에서 문법 및 동작의 미묘한 차이로 인해 오해나 오류가 생길 수 있음을 강조
  • 동시성, 네트워킹, 데이터베이스 등 백엔드 핵심 영역에서 실제 운영 환경에서 발생할 수 있는 함정들을 예시로 설명함
  • 다양한 예제와 참고 링크를 통해 문제 상황과 해결법, 그리고 예기치 않은 동작 개선점을 안내함

 

HTML과 CSS

  • Flexbox/Grid에서 min-width 기본값
    • min-width는 기본적으로 auto
    • min-width: auto는 콘텐츠 크기에 의해 결정되며, flex-shrink, overflow: hidden, width: 0, max-width: 100%보다 우선 적용
    • 권장: min-width: 0 명시
  • CSS에서 가로와 세로의 차이
    • width: auto는 부모 공간 채우기를 시도, height: auto는 콘텐츠에 맞춤
    • inline, inline-block, float 요소의 width: auto는 확장하지 않음
    • margin: 0 auto는 가로 중앙 정렬, margin: auto 0은 세로 중앙 정렬 불가 (단, flex-direction: column에서는 세로 중앙 가능)
    • 마진 병합은 세로에서만 발생
    • writing-mode: vertical-rl 등 레이아웃 방향이 바뀌면 동작도 반전
  • Block Formatting Context (BFC)
    • display: flow-root로 BFC 생성 (그 외 overflow: hidden/auto/scroll, display: table 등도 가능하나 부작용 존재)
    • 세로 인접 형제 마진이 겹치거나, 자식 마진이 부모 밖으로 새는 현상은 BFC로 방지 가능
    • 부모가 float 자식만 포함하면 높이가 0으로 무너짐 → BFC로 수정 가능
    • border나 padding이 있으면 마진 병합 발생하지 않음
  • Stacking Context
    • 새로운 stacking context를 만드는 조건
      • transform, filter, perspective, mask, opacity 등 렌더링 속성
      • position: fixed 또는 sticky
      • z-index 지정 + absolute/relative 위치 지정
      • z-index 지정 + flexbox/grid 내부 요소
      • isolation: isolate
    • 특징
      • z-index는 stacking context 내부에서만 적용
      • position: absolute/fixed 좌표는 가장 가까운 positioned 조상 기준
      • sticky는 stacking context를 넘어서 동작하지 않음
      • overflow: visible도 stacking context에 의해 잘림
      • background-attachment: fixed는 stacking context 기준으로 배치
  • 뷰포트 단위
    • 모바일 브라우저에서 주소창/네비게이션바 스크롤 시 화면에서 사라지면 100vh 값이 달라짐
    • 최신 해결책: 100dvh 사용
  • Absolute Position 기준
    • position: absolute는 부모가 아닌, 가장 가까운 relative/absolute 또는 stacking context 조상을 기준
  • Blur 동작
    • backdrop-filter: blur는 주변 요소를 고려하지 않음
  • Float 무효화
    • 부모가 flex 또는 grid면 자식의 float는 효과 없음
  • 퍼센트 단위 width/height
    • 부모의 크기가 사전에 결정되지 않으면 작동하지 않음 (순환 참조 회피 목적)
  • Inline 요소 특성
    • display: inline은 width, height, margin-top, margin-bottom 무시
  • Whitespace 처리
    • 기본적으로 HTML의 줄바꿈은 공백으로 취급, 연속 공백은 하나로 축소
    • <pre>는 공백 축소 방지하지만 시작/끝 부분 동작 특이
    • 대부분 콘텐츠 시작/끝 공백은 무시되나 <a>는 예외
    • inline-block 사이의 공백/줄바꿈은 실제 간격으로 표시됨 (flex/grid에서는 발생 안 함)
  • text-align
    • 텍스트 및 inline 요소 정렬에는 적용되지만 block 요소 정렬에는 적용되지 않음
  • box-sizing
    • 기본값은 content-box → padding/border 포함 안 됨
    • width: 100% + padding 설정 시 부모 영역 넘침 가능
    • 해결: box-sizing: border-box
  • Cumulative Layout Shift
    • <img>에 width와 height 속성을 지정하지 않으면 이미지 로딩 지연으로 레이아웃 흔들림 발생
    • 권장: 속성 지정으로 CLS 방지
  • Chrome에서 파일 다운로드 네트워크 요청
    • DevTools 네트워크 패널에 표시되지 않음 (다른 탭으로 처리됨)
    • 분석 필요 시 chrome://net-export/ 사용
  • HTML 내 JavaScript 파싱 문제
    • <script>console.log('</script>')</script> 같은 경우 첫 </script>를 종료 태그로 인식
    • 참고: Safe JSON in script tags

Unicode와 텍스트 인코딩

  • 코드 포인트와 그래프림 클러스터
    • 그래프림 클러스터는 GUI에서의 "문자 단위"
    • 가시적 ASCII 문자는 코드 포인트 1개 = 그래프림 클러스터 1개
    • 이모지는 여러 코드 포인트로 구성된 하나의 그래프림 클러스터일 수 있음
    • UTF-8에서 코드 포인트는 1~4바이트, 바이트 수와 코드 포인트 수는 일치하지 않음
    • UTF-16에서 코드 포인트는 2바이트 또는 4바이트(서로게이트 페어)
    • 표준은 클러스터 내 코드 포인트 수 제한을 두지 않으나, 구현에서는 성능상 제한 존재
  • 언어별 문자열 동작 차이
    • Rust: 내부 문자열 UTF-8 사용, len()은 바이트 수, 직접 인덱싱 불가, chars().count()는 코드 포인트 수, UTF-8 유효성 엄격 검증
    • Golang: 문자열은 사실상 바이트 배열, 길이와 인덱싱은 바이트 단위, 주로 UTF-8 사용
    • Java, C#, JS: UTF-16 기반, 2바이트 단위로 길이 측정, 인덱싱도 2바이트 단위, 서로게이트 페어 존재
    • Python: len()은 코드 포인트 수 반환, 인덱싱은 코드 포인트 하나를 포함하는 문자열 반환
    • C++: std::string은 인코딩 제약 없음, 바이트 벡터처럼 동작, 길이/인덱싱은 바이트 단위
    • 언급된 언어 중 그래프림 클러스터 단위로 길이/인덱싱하는 언어는 없음
  • BOM (Byte Order Mark)
    • 일부 텍스트 파일은 BOM을 가짐, 예: EF BB BF → UTF-8 인코딩 표시
    • 주로 Windows에서 사용, 비-Windows 소프트웨어는 BOM 처리 못할 수 있음
  • 기타 주의사항
    • 바이너리 데이터를 문자열로 변환 시, 잘못된 부분은 � (U+FFFD)로 대체됨
    • Confusable characters 존재 (서로 비슷해 보이는 문자)
    • 정규화(Normalization): 예) é는 U+00E9(단일 코드 포인트) 또는 U+0065+U+0301(두 코드 포인트)로 표현 가능
    • Zero-width characters  Invisible characters 존재
    • 줄바꿈 차이: Windows는 CRLF \r\n, Linux/MacOS는 LF \n
    • 한자 통합(Han unification): 언어별로 모양이 조금 다른 문자가 동일 코드 포인트 사용
      • 폰트가 언어별 변형을 포함하여 적절히 렌더링
      • 국제화 시 올바른 폰트 변형 선택 필요

부동소수점 (Floating point)

  • NaN 특성
    • NaN은 자기 자신을 포함한 어떤 값과도 같지 않음 (NaN == NaN은 항상 false)
    • NaN != NaN은 항상 true
    • NaN을 포함한 연산 결과는 대부분 NaN으로 전파됨
  • 특수한 값
    • +Inf와 -Inf 존재, NaN과는 다름
    • -0.0은 +0.0과 구분되는 값
      • 비교 연산에서는 동일하지만, 일부 계산에서는 다르게 동작
      • 예: 1.0 / +0.0 == +Inf, 1.0 / -0.0 == -Inf
  • JSON과의 호환성
    • JSON 표준은 NaN과 Inf를 허용하지 않음
      • JS JSON.stringify는 NaN, Inf를 null로 변환
      • Python json.dumps(...)는 NaN, Infinity를 그대로 출력 (표준 위반)
        • allow_nan=False 옵션 시 NaN/Inf가 있으면 ValueError 발생
      • Golang json.Marshal은 NaN/Inf 존재 시 에러 반환
  • 정밀도 문제
    • 부동소수점 직접 비교는 실패 가능 → abs(a - b) < ε 형태 권장
    • JS는 모든 숫자를 부동소수점으로 처리
      • 안전한 정수 범위는 -(2^53 - 1) ~ 2^53 - 1
      • 이 범위를 벗어나면 정수 표현이 부정확
      • 큰 정수에는 BigInt 사용 권장
      • JSON에 안전 범위를 넘어선 정수가 포함되면 JSON.parse 결과 값은 부정확할 수 있음
      • 밀리초 단위 타임스탬프는 287,396년까지 안전, 나노초 단위는 문제 발생
  • 연산 법칙 비적용
    • 연산 순서에 따라 정밀도 손실로 인해 결합법칙, 분배법칙이 엄밀히 성립하지 않음
    • 병렬 연산(행렬 곱셈, 합계 등)은 비결정적 결과를 만들 수 있음
  • 성능
    • 나눗셈은 곱셈보다 훨씬 느림
    • 동일한 수로 여러 번 나눌 때는 역수를 먼저 구해 곱하는 방식으로 최적화 가능
  • 하드웨어에 따른 차이
    • FMA(Fused Multiply-Add) 지원 여부: 일부 하드웨어는 더 높은 정밀도로 중간 계산
    • Subnormal range 처리: 최신 하드웨어는 지원하지만 일부 구형은 0으로 처리
    • 반올림 모드 차이
      • RNTE(가장 가까운 짝수로 반올림), RTZ(0으로 절단) 등 존재
      • x86/ARM은 스레드 로컬 mutable 상태로 설정 가능
      • GPU는 명령어 단위로 반올림 모드가 다름
    • 삼각함수, 로그 등 수학 함수 동작 차이
    • x86은 레거시 80비트 FPU와 per-core rounding mode 존재 → 사용 비권장
    • 이 외에도 다양한 요인으로 하드웨어별 부동소수점 결과가 달라질 수 있음
  • 정밀도 향상 방법
    • 계산 그래프를 얕게 구성 (곱셈 연속 구조 줄이기)
    • 중간 값이 매우 크거나 매우 작은 경우 피하기
    • FMA 같은 하드웨어 연산 활용

시간 (Time)

  • 윤초(Leap second)
    • Unix 타임스탬프는 윤초를 무시
    • 윤초 발생 시 주변 구간에서 시간이 늘어나거나 줄어듦(Leap smear)
  • 시간대(Time zone)
    • UTC 및 Unix 타임스탬프는 전 세계 공통
    • 사람이 읽는 시간은 지역별 시간대에 의존
    • DB에는 타임스탬프를 저장하고 UI에서 변환하는 방식 권장
  • 서머타임(DST)
    • 일부 지역에서는 여름철에 1시간 시계 조정
  • NTP 동기화
    • 동기화 과정에서 시간이 "뒤로 가는" 상황 발생 가능
  • 서버 시간대 설정
    • 서버는 UTC로 설정 권장
    • 분산 시스템에서 노드별 시간대가 다르면 문제 발생
    • 시스템 시간대 변경 후 DB 재설정 또는 재시작 필요
  • 하드웨어 시계 vs 시스템 시계
    • 하드웨어 시계는 시간대 개념 없음
    • Linux: 하드웨어 시계를 UTC로 처리
    • Windows: 하드웨어 시계를 로컬 시간으로 처리

Java

  • ==는 객체 참조 비교, 객체 내용 비교는 .equals 사용 필요
  • equals와 hashcode를 오버라이드하지 않으면 map/set에서 객체 동일성을 참조 기반으로 판단
  • map의 key 객체나 set 원소 객체의 내용을 변경하면 컨테이너 동작이 깨짐
  • List<T> 반환 메서드는 경우에 따라 mutable ArrayList 또는 immutable Collections.emptyList() 반환, 후자 수정 시 UnsupportedOperationException 발생
  • Optional<T>를 반환하는 메서드가 null을 리턴하는 경우 존재 (권장되지 않음)
  • finally 블록에서 return 시, try 또는 catch에서 발생한 예외가 무시되고 finally 반환 값이 적용됨
  • interrupt 무시하는 라이브러리 존재, IO 포함한 클래스 초기화 과정이 interrupt로 깨질 수 있음
  • thread pool에서 .submit()으로 전달한 task의 예외는 기본적으로 로그에 출력되지 않고 future로만 확인 가능, future 무시하면 예외 확인 불가
    • scheduleAtFixedRate 작업은 예외 발생 시 조용히 중단됨
  • 숫자 리터럴이 0으로 시작하면 8진수 처리 (0123 → 83)
  • 디버거는 지역 변수의 .toString()을 호출, 일부 클래스의 toString()에 부작용이 있어 디버깅 시 코드 동작이 달라질 수 있음 (IDE에서 비활성화 가능)

Golang

  • append()는 capacity 여유 시 메모리 재사용, subslice에 append 시 부모 메모리까지 덮어쓸 수 있음
  • defer는 함수 리턴 시 실행, 블록 스코프 종료 시가 아님
  • defer는 mutable 변수 캡처
  • nil 관련
    • nil slice와 empty slice는 다름
    • string은 nil 불가, 빈 문자열만 존재
    • nil map은 읽기는 가능하지만 쓰기는 불가
    • interface nil 특이 동작: data pointer가 null이지만 type info가 null이 아니면 nil과 같지 않음
  • Dead wait: Go에서 실제 동시성 버그 사례 존재
  • Timeout 종류 다양, net/http에서 상세히 다룸

C/C++

  • std::vector 원소 포인터 저장 후 vector가 grow되면 재할당 발생, 포인터 무효화
  • 리터럴 문자열로 생성된 std::string은 임시 객체일 수 있음, c_str() 호출 시 위험
  • 반복 중 컨테이너 수정 시 iterator 무효화 발생
  • std::remove는 실제 삭제가 아닌 원소 재배열, 삭제는 erase 필요
  • 숫자 리터럴이 0으로 시작하면 8진수 처리 (0123 → 83)
  • Undefined behavior (UB): 최적화 과정에서 UB는 자유롭게 바뀔 수 있어 의존 시 위험
    • 초기화되지 않은 메모리 접근 UB
    • char*를 struct 포인터로 변환 시 객체 수명 시작 전 접근으로 UB, memcpy로 초기화 권장
    • 잘못된 메모리 접근 (null 포인터 등) UB
    • 정수 overflow/underflow UB (unsigned는 0 아래로 underflow 가능)
    • Aliasing: 서로 다른 타입 포인터가 동일 메모리 참조 시 strict aliasing rule에 의해 UB 발생
      • 예외: 1) 상속관계 타입 2) char*, unsigned char*, std::byte* 변환 (역변환은 적용 안 됨)
      • 강제 변환은 memcpy 또는 std::bit_cast 권장
    • Unaligned memory 접근 UB
  • 메모리 Alignment
    • 64비트 정수는 주소가 8로 나누어 떨어져야 함
    • ARM에서 unaligned 접근은 crash 가능
    • 바이트 버퍼를 struct로 직접 해석 시 alignment 문제 발생
    • alignment는 struct padding을 만들어 메모리 낭비 가능
    • 일부 SIMD 명령어(AVX 등)는 정렬된 데이터만 처리 가능, 보통 32바이트 alignment 필요

Python

  • 함수 기본 인자는 호출 시마다 새로 생성되지 않고 최초 값이 그대로 저장됨

SQL Databases

  • Null 처리
    • x = null은 동작하지 않고 x is null을 사용해야 함
    • Null은 자기 자신과 같지 않음 (NaN과 유사)
    • Unique index는 Null 중복 허용 (단, Microsoft SQL Server는 예외)
    • select distinct에서 Null 처리 방식은 DB마다 다름
    • count(x)와 count(distinct x)는 Null 값이 있는 행을 무시
  • 일반 동작
    • 날짜 암묵 변환은 timezone 의존적일 수 있음
    • 복잡한 join + distinct는 중첩 쿼리보다 느릴 수 있음
    • MySQL(InnoDB)에서 string 필드가 utf8mb4가 아니면 4-byte UTF-8 문자 삽입 시 오류 발생
    • MySQL(InnoDB)은 기본적으로 대소문자 구분 없음
    • MySQL(InnoDB)은 암묵적 변환 허용: select '123abc' + 1; → 124
    • MySQL(InnoDB) gap lock은 deadlock 유발 가능
    • MySQL(InnoDB)에서는 group by와 select 컬럼 불일치 시 비결정적 결과 반환
    • SQLite에서는 strict가 아니면 필드 타입이 크게 의미 없음
    • Foreign key는 암묵적 lock을 발생시켜 deadlock을 유발할 수 있음
    • Locking은 DB별로 repeatable read isolation을 깨뜨릴 수 있음
    • 분산 SQL DB는 locking 미지원이거나 특이한 동작 가능 (DB별 상이)
  • 성능/운영
    • N+1 query 문제는 각 쿼리가 빠르기 때문에 slow query log에 나타나지 않음
    • 장기 실행 트랜잭션은 lock 문제 등 유발 → 트랜잭션은 빠르게 끝내는 것이 권장됨
    • 전체 테이블 lock 사례
      • MySQL 8.0+에서는 unique index/foreign key 추가 시 대부분 동시 처리 가능
      • 구버전 MySQL은 전체 테이블 lock 발생 가능
      • mysqldump에 --single-transaction 옵션 없으면 전체 테이블 read lock
      • PostgreSQL에서 create unique index나 alter table ... add foreign key는 전체 테이블 read lock 유발
        • 회피: create unique index concurrently 사용
        • foreign key는 ... not valid  validate constraint 방식 사용
  • Range 쿼리
    • 겹치지 않는 범위:
      • 단순 조건 p >= start and p <= end는 비효율적 (복합 인덱스 있어도)
      • 효율적 방식:
        select *   
        from (select ... from ranges where start <= p order by start desc limit 1)   
        where end >= p  
        
        (start 컬럼 인덱스만 필요)
    • 겹칠 수 있는 범위:
      • 일반 B-tree 인덱스로는 비효율적
      • MySQL은 spatial index, PostgreSQL은 GiST 사용 권장

Concurrency and Parallelism

  • volatile
    • volatile은 lock을 대체할 수 없으며 atomicity 제공 안 함
    • lock으로 보호된 데이터는 volatile 필요 없음 (lock이 memory order 보장)
    • C/C++: volatile은 일부 최적화만 방지, memory barrier 추가 안 됨
    • Java: volatile 접근은 sequentially-consistent ordering 제공 (필요 시 JVM이 memory barrier 삽입)
    • C#: volatile 접근은 release-acquire ordering 제공 (필요 시 CLR이 memory barrier 삽입)
    • 메모리 읽기/쓰기 재정렬 관련 잘못된 최적화 방지 가능
  • TOCTOU (Time-of-check to time-of-use) 문제
  • SQL DB에서 응용 계층 제약 조건 처리
    • 단순 unique index로 표현 불가한 제약(예: 두 테이블 간 유니크, 조건부 유니크, 기간 내 유니크)을 애플리케이션에서 강제하는 경우:
      • MySQL(InnoDB): repeatable read 레벨에서 select ... for update 후 insert, 그리고 유니크 컬럼에 인덱스가 있으면 gap lock 덕분에 유효 (단, gap lock은 고부하 시 deadlock 유발 가능 → deadlock detection 및 retry 필요)
      • PostgreSQL: repeatable read 레벨에서 동일 로직은 동시성 상황에서 불충분 (write skew 문제)
        • 해결책:
          • serializable isolation level 사용
          • 애플리케이션 대신 DB 제약 사용
            • 조건부 유니크 → partial unique index
            • 두 테이블 간 유니크 → 별도 테이블에 중복 데이터 삽입 후 unique index
            • 기간 배타성 → range type + exclude constraint
  • Atomic reference counting
    • Arc, shared_ptr와 같이 많은 스레드가 동일 카운터를 자주 변경하면 성능 저하
  • Read-write lock
    • 일부 구현은 read lock에서 write lock으로 업그레이드 지원하지 않음
    • read lock 보유 상태에서 write lock 시도 시 deadlock 발생 가능

Common in many languages

  • Null/None/nil 체크 누락이 흔한 오류 원인
  • 반복문 중 컨테이너 수정 시 단일 스레드 데이터 경쟁 발생 가능
  • 가변 데이터 공유 실수: 예) Python에서 [[0] * 10] * 10은 올바른 2D 배열 생성 아님
  • (low + high) / 2는 overflow 가능 → 안전한 방식은 low + (high - low) / 2
  • 단락 평가(short circuit): a() || b()는 a가 true면 b 실행 안 됨, a() && b()는 a가 false면 b 실행 안 됨
  • 프로파일러 기본값은 CPU time만 포함 → DB 대기 등은 flamegraph에 나타나지 않아 오해 유발
  • 정규 표현식 dialect가 언어마다 다름 → JS에서 동작하는 정규식이 Java에서 동작 안 할 수 있음

Linux and bash

  • 디렉터리 이동 후 pwd는 원래 경로, 실제 경로는 pwd -P
  • cmd > file 2>&1 → stdout+stderr 모두 파일, cmd 2>&1 > file → stdout만 파일, stderr는 그대로
  • 파일 이름은 대소문자 구분 (Windows와 다름)
  • 실행 파일은 capability 시스템 존재 (getcap으로 확인)
  • Unset 변수 위험: DIR unset이면 rm -rf $DIR/  rm -rf / 실행 위험 → set -u로 방지 가능
  • 환경 적용: 스크립트를 현재 shell에 적용하려면 source script.sh 사용 → 영구 적용하려면 ~/.bashrc에 추가
  • Bash는 명령어 캐싱: $PATH 내 파일 이동 시 ENOENT 발생 → hash -r로 캐시 갱신
  • 변수 미인용 사용 시 줄바꿈이 공백으로 처리
  • set -e: 스크립트 오류 시 즉시 종료하지만, 조건문 내부(||, &&, if)에서는 동작 안 함
  • K8s livenessProbe와 디버거 충돌: 브레이크포인트 디버거는 앱 전체를 멈추게 하여 health check 응답 실패 → Pod가 종료될 수 있음

React

  • 렌더링 코드에서 state 직접 수정
  • Hook을 if/loop 안에서 사용 → 규칙 위반
  • useEffect dependency array에 필요한 값 누락
  • useEffect에서 정리(clean up) 코드 누락
  • Closure trap: 오래된 state 캡처로 인해 버그 발생
  • 잘못된 위치에서 데이터 변경 → 불순한 컴포넌트
  • useCallback 사용 누락 → 불필요한 리렌더링 발생
  • 메모된 컴포넌트에 비메모 값 전달 시 memo 최적화 무효화

Git

  • Rebase는 히스토리 재작성
    • rebase 후 일반 push는 충돌 → 반드시 force push 필요
    • remote branch 히스토리 변경 시 pull도 --rebase 사용
    • --force-with-lease는 일부 경우 다른 개발자 commit 덮어쓰기 방지 가능, 단 fetch만 하고 pull 안 하면 보호 안 됨
  • Merge revert 문제
    • Merge revert는 효과 불완전 → 동일 브랜치 다시 merge 시 아무 변화 없음
    • 해결책: revert의 revert 실행 또는 깨끗한 방법(backup → reset → cherry-pick → force push)
  • GitHub 관련 주의사항
    • API 키 같은 secret을 commit 후 force push로 덮어도 GitHub에는 기록이 남음
    • private repo A를 fork한 B가 private이라도, A가 public이 되면 B의 내용도 공개됨 (삭제 후에도 접근 가능)
  • git stash pop: conflict 발생 시 stash가 drop되지 않음
  • .DS_Store는 macOS가 자동 생성 → .gitignore에 **/.DS_Store 추가 권장

Networking

  • 일부 라우터·방화벽은 유휴 TCP 연결을 조용히 끊음 → HTTP 클라이언트·DB 클라이언트의 커넥션 풀 무효화 가능 → 해결: TCP keepalive 설정
  • traceroute 결과는 신뢰성 낮음 → 경우에 따라 tcptraceroute가 더 유용
  • TCP slow start는 대기시간 증가 원인 → tcp_slow_start_after_idle 비활성화로 해결 가능
  • TCP sticky packet 문제: Nagle 알고리즘은 패킷 전송 지연 → TCP_NODELAY 활성화로 해결 가능
  • Nginx 뒤에 백엔드 배치 시 커넥션 재사용 설정 필요 → 미설정 시 고부하 환경에서 내부 포트 부족으로 연결 실패
  • Nginx는 기본적으로 패킷 버퍼링  SSE(EventSource) 지연 발생
  • HTTP 표준은 GET·DELETE 요청 body를 금지하지 않음 → 일부는 body 사용하지만 많은 라이브러리·서버가 지원하지 않음
  • 하나의 IP에 여러 웹사이트 호스팅 가능 → 구분은 HTTP Host 헤더와 TLS의 SNI가 담당 → 단순 IP 접속 불가 사이트 존재
  • CORS: 다른 origin 요청 시 브라우저는 응답 접근 차단 → 서버에서 Access-Control-Allow-Origin 헤더 설정 필요
    • 쿠키 전달 포함 시 추가 설정 필요
    • 프론트엔드와 백엔드가 동일 도메인·포트라면 CORS 문제 없음

Other

  • YAML 주의사항
    • YAML은 공백 민감  key:value는 오류, key: value가 올바름
    • 국가 코드 NO는 따옴표 없이 쓰면 false로 해석되는 문제 발생
    • Git commit hash를 따옴표 없이 쓰면 숫자로 변환될 수 있음
  • Excel CSV 문제
    • Excel은 CSV 열 때 자동 변환 수행
      • 날짜 변환: 1/2, 1-2  2-Jan
      • 대형 숫자 부정확 변환: 12345678901234567890  12345678901234500000
    • 원인은 Excel이 내부적으로 floating point로 숫자를 처리하기 때문
    • 이슈로 인해 유전자 이름 SEPT1이 잘못 변경된 사례 존재

 

 

 

반응형
반응형

"개발자가 대체된다"는 유행은 왜 반복될까 ?

The Recurring Cycle of 'Developer Replacement' Hype

 

https://alonso.network/the-recurring-cycle-of-developer-replacement-hype/

 

 

  • NoCode부터 AI까지, 개발자를 대체하겠다는 기술은 반복적으로 등장하지만 실제로는 기술 변화에 따라 역할이 변형
  • NoCode는 개발자를 없애지 않고 NoCode 전문가와 통합 기술자를 탄생시켰고, 클라우드는 DevOps 엔지니어라는 고급 직군을 만들었음
  • 현재 AI 개발도구도 비슷한 길을 걷고 있으며, AI가 코드를 짜는 시대에도 시스템 아키텍처 설계 능력은 여전히 핵심임
  • AI는 로컬 최적화는 잘하지만 전체 시스템 설계에는 약하며, 빠른 생성 속도로 인해 구조적 실수를 빠르게 고착화할 위험이 있음
  • 개발자 대체는 결국 기술 스택 변화에 따른 진화와 고도화일 뿐, 본질적 역할은 계속 필요함

From NoCode to AI-Assisted

  • 몇 년 주기로, 소프트웨어 개발자를 대체할 것이라 주장하는 새로운 기술이 등장함
  • "코딩의 종말", "이제 누구나 앱을 만들 수 있음", "아이도 코딩한다" 등 과장된 기대가 포함된 유사한 제목들이 반복적으로 생성됨
  • 경영진과 컨설턴트들이 이 흐름에 주목하고, 예산이 이동하는 모습이 나타남
  • 하지만 현실은 항상 “대체”가 아니라 “변형”이었음
    • 복잡해진 기술을 다루는 새로운 역할 고도화된 전문직이 탄생하고, 임금 수준도 상승하는 경향이 반복적으로 드러남
  • NoCode는 전문 기술자 없이 앱을 만들 수 있다는 기대를 만들었지만, 결국 데이터 모델링, 통합, 유지보수 등 복잡한 문제가 존재했고 이를 해결할 새로운 직군이 탄생함
  • 클라우드는 시스템 관리자 없이 운영 가능하다는 믿음을 줬지만 실제로는 DevOps 엔지니어라는 고급 전문성을 요구하게 되고, 임금도 상승함
  • AI도 마찬가지로, “AI가 코드를 대신 작성”할 수 있을 것 같지만 실제로는 AI를 관리·오케스트레이션 할 수 있는 숙련 개발자의 중요성이 더욱 커짐

반복되는 대체 약속의 회전목마(The Endless Carousel of Replacement Promises)

NoCode/LowCode 혁신

  • 직관적인 인터페이스로 모든 사용자가 앱을 만들 수 있다는 NoCode/LowCode 혁신이 등장
  • 하지만 실제 현장에서는 데이터 모델 설계, 기존 시스템과 데이터베이스 통합, 예외 처리, 유지 관리 등 신규 문제가 발생함
  • 이에 따라 단순 개발자가 아닌, 도메인 지식과 기술적 한계를 동시에 이해하는 NoCode 전문가가 필요해짐
  • 이들은 기존 개발자보다 더 높은 연봉을 받음

클라우드 혁명

  • 클라우드로 이전하면 시스템 관리자가 필요 없어질 거라는 기대가 컸음
  • 하지만 클라우드 관리 전문성 복잡성이 오히려 증가함
  • 기존 시스템 관리자는 DevOps 엔지니어로 변신하여 더 높은 급여를 받고, 인프라 자동화, 배포 파이프라인, 분산 시스템 관리 등 업무 수준이 고도화됨
  • 업무는 사라진 것이 아니라, 새로운 작업 형태로 진화함
  • 마이크로서비스 전환에서도 복잡성이 커지고, 결국 근본적으로 시스템을 관리하는 전문가의 역할이 중요함이 드러났음

오프쇼어(Offshore) 개발 바람

  • 해외 아웃소싱으로 비용을 절감할 수 있다는 믿음이 생겨났지만, 커뮤니케이션 문제, 품질 저하, 도메인 지식 부족으로 어려움 발생
  • 결국 분산 팀 구조조, 명확한 소유권, 강력한 아키텍처 등으로 전략이 변화하며, 초기 기대했던 것보다 전체 비용이 증가하는 결과를 낳음

AI 코딩 어시스턴트 혁명

  • 이제는 AI가 코드를 자동으로 생성한다는 약속이 화두임
  • 초기 현실에서는, AI가 만들어주는 코드는 종종 미묘한 오류와 일관성 문제를 내포함
  • 시니어 엔지니어가 AI 결과를 검토·수정하는 데 많은 시간을 쓰며, 경험 있는 개발자일수록 훨씬 더 많은 가치를 창출함
  • AI 보조만으로 구축된 시스템은 체계적인 아키텍처가 부재한 경우가 많음
  • 즉, 기술이 기술자를 대체하는 것이 아니라, 더 높은 추상화 계층으로 기술자의 전문성을 끌어올리는 것임

이번 사이클이 특별한 이유

  • 사람들이 간과하는 핵심: 코드는 자산이 아니라 부채
  • 빠르고 쉽게 코드를 만들수록, 유지보수와 보안, 리팩터링의 부담도 커짐
  • AI는 함수 단위 최적화는 가능하지만 전체 시스템 설계 능력은 부족
  • 구현 속도가 빨라질수록 구조적 실수를 빠르게 고착화할 위험 존재
  • 결국, AI 시대에도 진정한 자산은 시스템 아키텍처 설계 능력이며, 이는 대체가 아닌 강화의 대상
  • "AI가 개발자를 대체한다"는 주장은 다음의 근본적 오해에서 비롯됨
    • 코드는 자산이 아니라 부채라는 사실
    • 코드는 지속적인 유지·검증·보안 관리·교체가 필요하며, 그 라인 수만큼 부채가 증가함
  • AI가 코드를 빠르게 만들어준다는 것은, 부채를 그만큼 빠르게 발생시킨다는 것에 불과함
  • 즉, AI는 로컬 최적화(함수, 부분 기능)는 잘하지만, 글로벌 설계·아키텍처 결정은 부족함
  • 구현 속도가 빨라질수록, 잘못된 설계가 시스템 전체에 '굳어지는' 위험성이 커짐
  • 일회성 단기 사이트 제작에는 문제가 없으나, 장기적으로 발전하는 시스템에는 치명적임
  • 기술 혁신의 패턴은 변함없이 유지됨
    • 시스템 관리자는 DevOps 엔지니어가 되고, 백엔드 개발자는 클라우드 아키텍트가 됨
  • 하지만 AI는 모든 것을 가속화함. 살아남고 발전하는 기술은 코드 작성이 아님
  • 그것은 바로 시스템을 설계하는 것(Architecting systems). AI가 할 수 없는 유일한 일이 바로 그것임

 

 

반응형
반응형

AI 시대의 기술 위축을 피하는 방법

 

최고의 미래 개발자는, 오늘날의 AI로 인해, 스스로 생각하는 법을 잊지 않은 사람이 될 것임

 

https://addyo.substack.com/p/avoiding-skill-atrophy-in-the-age

 

Avoiding Skill Atrophy in the Age of AI

How to use AI coding assistants without letting your hard-earned engineering skills wither away.

addyo.substack.com

  • AI 도구로 인한 생산성 증가는 개발자들의 핵심 기술 쇠퇴(skill atrophy) 위험을 초래함
  • AI를 과도하게 의존하면 비판적 사고 문제 해결 능력이 점점 약화됨
  • 디버깅, 아키텍처 설계, 기억력 등 중요한 기술이 점차 퇴화할 수 있음
  • AI를 도구로 삼되, 스스로 사고하고 학습하는 습관을 반드시 유지해야 함
  • AI와 협력하는 방식으로 사용하면, 생산성과 기술 숙련도를 모두 향상시킬 수 있음

AI 시대에 기술 쇠퇴를 피하는 방법

  • 코딩 분야에서 AI 도우미의 부상은 생산성 향상과 함께 기술 쇠퇴(skill atrophy) 위험을 초래함
    • 기술 쇠퇴는 사용 부족이나 연습 부재로 인해 시간이 지남에 따라 기술이 약화되는 현상을 의미함
  • 반복적 작업을 AI에 맡기는 것은 유익할 수 있지만, 과도하면 핵심 능력 상실로 이어질 수 있음
  • 인지적 오프로드(cognitive offloading) 현상으로 인해, 문서나 튜토리얼을 스스로 학습하는 대신 AI에 의존하는 경향이 강해짐
  • 예를 들어, GPS 사용이 길 찾기 능력을 약화시킨 것처럼, AI 자동완성과 코드 생성 기능이 사고력을 저하시킬 수 있음
  • AI가 보일러플레이트 코드를 처리해줌으로써 대규모 프로젝트에 도전할 수 있는 기회가 생겼지만, 자동화와 기술 쇠퇴 사이 경계 설정이 중요함

비판적 사고가 희생양이 되고 있는가?

  • Microsoft와 Carnegie Mellon 연구팀의 2025년 연구에 따르면, AI 의존도가 높을수록 비판적 사고 감소 현상이 발생함
  • AI에 대한 과신은 사람들이 스스로 사고하는 대신 자동 조종 상태로 전환하게 만듦
  • 쉬운 작업일수록 더욱 경계를 풀게 되고, 이로 인해 장기적인 독립 문제 해결 능력 감소가 초래됨
  • AI 도움을 받는 작업자는 동일 문제에 대해 덜 다양한 해결책을 제시하는 경향이 있으며, 이는 사고력 균질화로 이어짐
  • 연구진은 이를 비판적 사고의 저하로 정의함
  • 비판적 사고를 저해하는 장벽들
    • 인지적 장벽: 반복적인 작업일수록 AI에 과도하게 의존하는 경향
    • 동기적 장벽: 시간 압박이나 직무 범위 제약으로 깊은 사고를 회피하게 됨
    • 능력적 장벽: AI의 답변을 스스로 검증하거나 개선하는 데 어려움을 느낌
  • 한 엔지니어는 12년 경력에도 불구하고 AI의 즉각적 도움으로 인해 스스로를 더 못하는 개발자로 느끼게 되었음을 고백함
    • 문서 읽기 중단: LLM이 즉각 설명해주기 때문에 공식 문서를 읽을 필요성을 느끼지 않음
    • 디버깅 능력 감소: 스택 트레이스나 에러 메시지를 직접 분석하는 대신 AI에 복붙하여 해결하려 함
    • 깊이 있는 이해 상실: 문제를 진정으로 이해하려는 노력 없이 AI 제안만 반복 적용하게 됨
    • 감정적 반응 변화: 과거에는 버그를 해결하는 데서 얻던 기쁨이, 이제는 AI가 5분 안에 답을 못 주면 좌절로 바뀜
  • LLM에게 사고를 위탁하면서, 개발자는 장기적 숙련도를 잃고 단기적 편리성을 얻는 교환을 하게 됨"우리는 AI 덕분에 10배 개발자가 된 것이 아니라, AI에 10배 더 의존하게 된 것"
    "우리가 스스로 해결할 수 있는 문제 AI가 해결하도록 할 때마다, 우리는 장기적인 이해 단기적인 생산성으로 바꾸고 있음"

기술 쇠퇴의 미묘한 징후들

  • AI 의존이 단순한 가설이 아니라 실제로 개발 기술의 약화로 이어질 수 있음
  • 몇 가지 뚜렷한 징후를 통해 자신의 기술 쇠퇴 여부를 점검할 수 있음
  • 디버깅 포기 현상
    • 에러가 발생할 때 디버거를 사용하거나 스택 트레이스를 직접 읽지 않고, 바로 AI에 의존하는 경향
    • 과거에는 버그를 직접 분석하고 해결하면서 성장했지만, 이제는 그 과정을 AI에 전가하는 경우가 많아짐
    • AI가 해결하지 못하거나 사용할 수 없는 상황에서는, 기본적인 문제 진단조차 어려운 상태에 빠질 위험이 있음
  • 이해 없이 복붙하는 코딩
    • 보일러플레이트 코드를 AI가 작성하는 것은 괜찮지만,  그렇게 동작하는지 이해하지 못한 채 복사하여 사용하는 경우 문제 발생
    • 특히 젊은 개발자들은 AI 덕분에 빠르게 코드를 작성하지만, 그 선택의 이유나 예외 처리 방식을 설명하지 못하는 경우가 많음
    • 다양한 대안을 고민하는 과정이 사라지면서 기초적인 사고 훈련이 결여됨
  • 아키텍처 및 시스템적 사고력 약화
    • 복잡한 시스템 설계는 단일 프롬프트로 해결할 수 없음
    • 작은 문제를 AI로 해결하는 데 익숙해지면, 고차원적 설계 작업에 대한 두려움이나 회피가 생길 수 있음
    • AI는 특정 컴포넌트나 패턴을 제안할 수 있지만, 성능, 보안, 유지보수성 등 전체 맥락을 이해하는 것은 개발자 본인의 몫임
    • 시스템 수준 사고력을 사용하지 않으면 점차 약화됨
  • 기억력 및 회상력 감소
    • 자주 쓰는 API 호출이나 언어 문법조차 기억이 흐려질 수 있음
    • AI 자동완성 기능에 익숙해지면서, 스스로 코드를 작성하는 능력이 약화됨
    • 이는 수학 계산기를 지나치게 의존하는 학생처럼, 기본 계산 능력 상실에 비유할 수 있음
  • 시간이 흐름에 따라 일부 기술이 자연스럽게 사라지는 것은 정상적인 현상임
    • 예를 들어, 어셈블리어로 메모리를 직접 관리하거나, 손으로 긴 나눗셈을 하는 능력은 더 이상 필수적이지 않음
    • 하지만 어떤 기술은 유지해야 하고, 어떤 기술은 버려도 되는지 구분하는 것이 중요함
    • 긴급 상황에서 디버깅할 수 있는 능력은 여전히 필수 기술로 간주해야 함
    속도와 지식의 트레이드오프:
    AI는 빠른 답을 제공하지만 (높은 속도, 낮은 학습),
    전통적인 방법(Stack Overflow, 공식 문서)은 느리지만 깊은 이해를 구축해줌
  • 즉각적 답변을 좇다가, 진정한 전문가로 성장하는 데 필요한 맥락 이해와 깊이를 놓칠 위험이 있음

AI 과의존의 장기적 위험

  • AI 도구에 대한 과도한 의존이 통제되지 않을 경우, 경력상 비판적 사고 위기에 직면할 가능성이 있음
  • AI가 대부분의 사고 과정을 대신하게 되면, 도구가 실패하거나 해결하지 못하는 문제에 대해 스스로 대응할 능력을 잃게 됨"AI를 많이 쓸수록 뇌를 덜 쓰게 됩니다. 그러면 AI가 해결할 수 없는 문제에 부딪혔을 때, 당신은 스스로 해결할 수 있는 기술이 있을까요?"
  • 실제로 AI 코딩 도우미 장애로 개발자들의 워크플로우가 완전히 멈춘 사례도 발생함
  • 자기 실현적 예언(Self-Fulfilling Prophecy)
    • Microsoft 연구팀은 AI에 의한 직업 상실을 걱정하면서도 "무비판적(uncritically)으로 AI를 사용"할 경우, 스스로 경쟁력을 잃게 될 수 있음을 경고함
    • 특히 신입 개발자들은 "어려운 길"을 건너뛰고 빠른 생산성에만 집중하여, 심화 학습 없이 조기에 성장 정체에 빠질 위험이 있음
    • 결과적으로, 스스로 문제를 해결하는 기쁨이나 깊은 이해를 경험해보지 못한 버튼 누르는 인력(button-pushers) 집단이 생겨날 수 있음
    • 이들은 AI에게 질문하는 방법은 능숙할지 몰라도, 정답을 진정으로 이해하지 못하는 상황에 빠질 수 있음
    • AI가 사소하게 틀렸을 때 그 오류를 발견하지 못하고, 버그나 보안 취약점이 코드에 섞여 들어가는 문제도 발생할 수 있음
  • 팀 문화와 조직 역동성
    • 모든 개발자가 AI 도우미만 사용하게 되면, 멘토십 비공식적 학습(osmosis learning) 이 약화될 수 있음
    • 주니어 개발자들이 동료 대신 AI에 의존하면, 시니어 개발자들이 지식을 전수하기 어려워짐
    • 기초가 약한 주니어들이 많아질 경우, 시니어들은 AI가 만들어낸 오류를 고치는 데 시간을 소모하게 됨
    • 결국 팀은 개별 구성원이 AI에 의존하는 집합체로 전락할 수 있으며, 비판적 리뷰나 공동 품질 유지 문화가 사라질 수 있음
    • 버스 팩터(bus factor) 에 사실상 "AI 서비스 장애"도 포함이 가능함
      • "프로젝트가 무너지려면 몇 명이 버스에 치여야 할까?"
  • 아날로그 방식으로 돌아가자는 것이 아니라, AI를 신중하게 사용해야 한다는 경고
    • AI를 활용하면서도, 작업 그 자체뿐 아니라 사고력 자체까지 아웃소싱하지 않도록 주의해야 함
    • 목표는 AI의 혜택을 최대한 누리되, 동시에 자기 자신의 기술과 사고력을 견고히 유지하는 것

AI를 목발이 아닌 협력자로 사용하기

  • AI 코딩 도우미의 생산성 향상을 누리면서도, 사고력과 기술을 유지하기 위해서는 의식적인 사용 습관이 필요함
  • AI를 전능한 답변자가 아니라, 주니어 페어 프로그래머 러버덕 디버깅 파트너처럼 대해야 함
  • 다음은 고려해봐야할 구체적 실천 전략들
  • "AI hygiene(위생)" 실천 – 항상 검증하고 이해하기
    • AI의 결과물이 그럴듯해 보여도 무조건 신뢰하지 않고 검증하는 습관을 들여야 함
    • AI가 생성한 함수나 코드에 대해 의도적 테스트를 수행하고, 엣지 케이스를 찾아야 함
    • "왜 이 솔루션이 작동하는가?", "한계는 무엇인가?"를 스스로 질문함
    • AI에게 코드를 줄 단위로 설명하거나 대안 접근법을 요청해 학습에 활용함
    • AI의 답변을 심문하면 수동적인 답변을 능동적인 교훈으로 바꿀 수 있음
  • 기본기 훈련 – 때로는 고생도 필요함
    • 매주 일정 시간을 "AI 없는 코딩시간" 으로 설정하여 순수한 수작업으로 문제를 해결하는 시간 확보
    • 경험 많은 개발자들은 "No-AI Day" 를 지정하여 직접 코드 작성, 에러 분석, 문서 검색을 실천함
    • 초기에는 느리고 답답하지만, 시간이 지나면서 자신감과 깊이 있는 이해를 회복할 수 있음
    • AI 없이 꾸준히 코딩하면 기본 실력이 엔트로피로 떨어지는 것을 방지할 수 있음
    • 이는 개발자 두뇌를 위한 크로스 트레이닝과 같음
  • AI한테 묻기전에 문제에 스스로 먼저 도전하기
    • 문제를 접했을 때 곧바로 AI에 묻지 않고, 먼저 접근 방법을 고민
    • 최소한 의사 코드(pseudocode) 나 간단한 아이디어라도 스스로 세워본 후 AI를 활용함
    • 버그가 발생하면 최소 15~30분 정도는 스스로 디버깅해보는 시간을 갖기
    • 이러면 문제 해결 능력을 키울 수 있으며, AI 답변과 자신의 접근법을 비교하며 능동적으로 학습이 가능
  • AI를 사용하여 코드 검토를 대체하는 것이 아니라 증강하기
    • AI가 생성한 코드도 인간 동료가 작성한 것처럼 철저히 리뷰
    • 가능하다면 AI 코드에 대해 인간 코드 리뷰를 병행하여 팀 차원의 품질을 유지함
    • 이를 통해 팀 지식을 루프에 유지하고, AI를 신뢰할 때 단독 개발자가 놓칠 수 있는 문제를 포착함
    • 이는 "AI가 초안을 만들 수는 있지만, 우리가 코드를 소유한다"는 태도를 장려
    • 누가 작성했는지에 관계없이 팀이 저장소에 있는 모든 코드를 이해하고 유지관리 할 책임이 있음
  • 능동적 학습 – 후속 질문과 반복 학습
    • AI가 제시한 솔루션이 잘 작동해도, 그 자리에서 학습을 강화하는 시간을 가짐
    • 복잡한 정규 표현식이나 알고리듬을 AI로 작성한 경우, 그 구조를 스스로 설명하거나, AI에 왜 이 방법을 썼는지 질문
    • AI를 단순 답변 제공자가 아니라, 무한 인내심을 가진 튜터처럼 대화형으로 활용함
      • ChatGPT가 생성한 코드에 대해 "왜 이 방법은 안 돼?" 라고 묻기
    • 이렇게 하면 AI는 단순한 코드 배포자가 아닌 멘토가 됨
  • 학습 일지 및 "AI 어시스트" 목록을 기록하기
    • AI에 반복적으로 묻는 주제를 기록하여 지식 공백을 파악함
    • 예를 들어, CSS에서 div 정렬이나 SQL 쿼리 최적화를 반복해서 묻는다면, 해당 주제를 집중 학습함
    • 플래시카드나 짧은 연습 문제를 만들어 반복 학습하여 장기 기억으로 전환함
    • 다음에 비슷한 문제에 직면하게 되면 AI 없이 문제를 풀어보고 그 방법을 기억하는지 확인해 볼 것
    • AI를 첫 번째 해결책이 아닌, 마지막 안전망으로 사용하는 태도를 유지함
  • AI와 페어 프로그래밍하기
    • AI를 질문 처리 API처럼 대하는 대신, 페어 프로그래밍 파트너처럼 대화함
    • 예를 들어, 내가 함수 초안을 작성하고 AI에게 개선점을 제안받거나, 반대로 AI가 초안을 작성하면 내가 수정함
    • 대화 예시: "이 함수는 작동하는데, 더 명확하게 리팩토링할 방법이 있을까?"
    • 이렇게 하면 당신이 운전석에 앉아있게 함. 단순히 답변을 소비하는게 아니라, AI가 기여할 수 있도록 큐레이션하고 지시
    • AI를 감독이 필요한 주니어 개발자로 취급하고, 최종 책임자는 인간 개발자임을 명확히 함
  • 이런 습관을 통해 AI 사용은 순수한 이득이 되며, 스스로의 능력도 잃지 않게 됨
  • 실제로 AI를 활용하여 생소한 코드를 설명하거나, 복잡한 케이스로 AI를 시험하는 과정은 개인 기술 향상에도 매우 유익함
  • 예를 들어, AI를 사용하여 익숙하지 않은 코드를 설명하면 지식을 심화할 수 있고, 까다로운 사례로 AI를 당황하게 만들면 테스트 사고방식을 향상시킬 수 있음
  • 핵심은 수동적 소비자가 아니라 능동적 사용자로 남는 것임

결론: 날카로움을 유지하기

  • 소프트웨어 산업은 AI 기반 코드 생성의 시대를 향해 가속 중이며, 이제 되돌릴 수 없는 흐름이 됨
  • 이러한 도구를 받아들이는 것은 불가피할 뿐만 아니라, 대체로 이득이 되는 일
  • 그러나 AI를 워크플로우에 통합하면서, 각자 기계에게 양보할 것과 스스로 유지해야 할 것 사이에서 신중한 선택이 필요함
  • 코딩을 사랑한다면, 단순히 빠르게 기능을 출시하는 것뿐 아니라, 문제를 해결하는 장인정신과 즐거움도 유지해야 함
  • AI를 능력 증폭기(amplifier) 로 활용하되, 대체자(replacement) 로 만들지 말아야 함
  • AI가 반복 작업을 대신할 수 있도록 하고, 그 freed-up 시간을 창의적이고 복잡한 작업에 투자함
  • 그러나 기초 기술이 퇴화하지 않도록 주의해야 하며, 항상 "어떻게"와 "왜"를 탐구하는 호기심을 유지해야 함
  • 디버깅 본능 시스템 사고력을 계속 갈고닦아야 하며, AI가 제시하는 지름길만 탐색해서는 안 됨
  • "간단히 말해서, AI를 당신의 목발이 아닌 협력자로 삼을 것"
  • 성공하는 개발자는 인간적 직관과 경험을 AI의 초능력과 조화롭게 결합할 줄 아는 사람일 것임
    • autopilot이 있거나/없거나 상관없이 코드베이스를 탐색할 줄 아는
  • 자기주도적 연습과 도전을 통해, fancy한 도구가 실패하거나 새로운 문제에 직면해도 스스로 문제를 해결할 수 있어야 함
  • "AI가 당신을 대체할까봐 걱정하지 말고, 당신을 대체 불가능하게 만드는 기술을 키우지 않는 것에 대해 걱정할 것"
  • "AI가 제공하는 답변을, 엔지니어의 마음으로 이해해야 한다"는 원칙을 항상 지키면, AI 열풍에 타면서도 쓸려가지 않을 것
  • 보너스
    • 다음에 AI가 기능 전체를 코딩해줄 때 유혹을 느낀다면, 스스로 직접 일부를 작성해보라는 신호로 받아들여야 함
    • 놀랍게도 많은 것을 기억하고 있고, 다시 직접 손으로 코딩하는 기쁨을 느낄 수 있음
    • AI를 생산성 향상의 도구로 삼되, 능동적으로 기술을 연마하는 습관을 절대 멈추지 말아야 함

최고의 미래 개발자는, 오늘날의 AI로 인해, 스스로 생각하는 법을 잊지 않은 사람이 될 것임

반응형

+ Recent posts