우아한테크캠프 6기 교육생들의 최종 회고

Nov.29.2023 우아한테크캠프 운영진

우아한테크캠프

우아한테크캠프 6기가 진행된 여름이 지나가고, 어느덧 겨울의 한가운데로 향하고 있습니다.
이번 우아한테크캠프(우테캠)의 여정은 교육생분들의 많은 도전과 성취, 그리고 협업 과정에서의 소중한 경험들로 가득 찼는데요. 저희 운영진도 오리엔테이션부터 데모데이와 수료식까지 교육생분들의 성장을 지켜보며, 열정이 빛나는 순간에 함께할 수 있어 기뻤습니다.

지난여름을 되돌아보며 수료생분들이 우테캠 과정에 대한 최종 회고글을 남겼습니다. 개발을 향한 열정과 미래에 대한 에너지가 돋보이는 글 2편을 소개합니다 🙂

우아한테크캠프 데모데이
우아한테크캠프의 마지막날, 각 팀의 프로젝트가 빛나는 데모데이가 진행되었습니다.

안건 님

우아한테크캠프에 참여한 것은 나에게 굉장히 가치 있는 경험이었다. 우아한테크캠프를 통해 발전한 점, 그리고 캠프 이후 나의 생활과 목표를 공유해 보고자 한다.

교육 전후로 발전한 점

1. 애플리케이션에서 발생 가능한 여러 이슈에 대해 경험하고 인식하게 되었다.

우테캠 이전에는 대량의 트래픽이나 데이터로 인해 발생할 수 있는 성능, 동시성 이슈에 대해 무지했었다. 로컬 환경에서 혼자 테스트하거나 기껏해야 1만 건의 데이터를 다뤄보고는 별문제가 없으면 그냥 넘어갔다. 맞닥뜨리고 해결했던 문제들은 거의 프레임워크에 대한 부족한 지식으로 인해 발생하는, 공식 문서를 읽고 사용법을 익히면 해결되는 기능 구현에 관한 것들이었다.

우테캠 팀 프로젝트에서 ‘100만 건 이상의 데이터 다루기’가 요구사항으로 주어졌는데, 팀에서 요구량의 열 배인 1천만 건 이상의 데이터를 다뤄보면서 대량의 데이터로 인해 발생하는 조회 쿼리 성능 이슈를 처음으로 경험할 수 있었다. 팀원들과 함께 진행한 SQL 튜닝 스터디에서 얻은 인덱스 관련 지식과 강의 시간에 접한 반정규화가 문제 해결에 큰 도움을 주었다.

교육생들과 지식을 공유하며 InnoDB 스토리지 엔진을 사용할 때 발생할 수 있는 동시성 이슈(갱신손실)와 이에 대한 해결책인 락, 그리고 락을 사용했을 때 발생할 수 있는 성능 이슈에 대해서도 처음 접하게 되었다. 이를 쇼핑몰 애플리케이션 개발에 적용해서 다수의 사용자가 동시에 하나의 상품을 주문하거나 단일 주문에 대한 상태 변경 요청이 동시에 들어오는 경우 발생 가능한 동시성 이슈를 비관적 락 설정을 통해 방지했다. 그리고 락이 걸리는 시간이 길어지면서 발생하는 성능 문제는 트랜잭션을 작은 단위로 분리해 완화했다.

2. 다양한 문제 해결 방법을 모색하는 태도를 키울 수 있었다.

우테캠의 4가지 미션은 하나의 컴퓨터로 2명이 함께 개발하는 페어 프로그래밍으로 진행되고, 마지막 프로젝트도 4명이 함께 진행하는 팀 프로젝트이다. 혼자 개발하는 것이 아니다 보니 제시된 문제에 대해 의논하다 보면 자연스럽게 다양한 해결책이 나오고 각 방법을 비교하며 하나의 선택지로 의견을 수렴해 나간다.

이 과정에서 많은 이야기를 나누면서 개발에 대한 이해가 깊어지기도 했고, 긴 고민을 거쳐 의사결정을 내렸기 때문에 더 좋은 결과물이 나온 것 같다. 캠프가 끝나고 개인적으로 팀 프로젝트를 개선해 보았는데, 혼자 진행했음에도 여러 선택지를 놓고 장단점을 비교하며 더 나은 방법을 찾았다. 가장 먼저 떠오르는 해결책을 바로바로 적용했던 이전과는 달라진 모습이다.

3. 팀워크, 소통, 협업의 중요성을 깨달았다.

캠프 이전에도 팀 프로젝트를 진행한 적이 있지만 100% 온라인으로 진행했고 구현사항에 대해 긴 논의를 거치는 경우가 별로 없었다. 충분한 논의 없이 일단 기능을 구현하고 코드가 작성된 이후에 의견을 제시했기 때문에, 의견이 잘 반영되지도, 결과물이 만족스럽지도 않았다. 이에 반해 우테캠에서 협업을 진행할 때는 서로의 개발 진행 상황과 발생한 문제를 매일 틈틈이 공유하고 같이 고민했다. 다 같이 머리를 맞대니 혼자 고민할 때보다 더 빠르게, 더 나은 방법으로 문제를 해결할 수 있었다.

무엇보다 지식과 의견을 공유하는 행위 자체가 무척 즐거웠고, 열정 넘치는 사람들 사이에서 긍정적인 자극도 많이 받을 수 있었다. 동료의 소중함을 깨닫는 순간들이었다. 전에는 단순히 많이 배워서 일을 잘해나가는 게 제일 중요하다고 생각했었다. 그러나 지금은 동료들 사이에서 즐겁게 일하면서 함께 성장해 나가는 것이 더 소중한 가치가 되었다.

교육 이후 어떻게 시간을 보냈는지

1. 면접 준비

면접을 준비하면서 우테캠 두 달간 배웠던 내용과 팀 프로젝트를 리뷰하고, 팀원들과 CS 스터디를 진행하면서 네트워크, 운영체제, 데이터베이스 등의 중요 개념들을 머릿속에 되새겼다. 나는 어떤 개발자인지, 어떤 개발자가 되고 싶은지 고민해 보고, 팀 소개 글이나 우아한형제들이 지은 "이게 무슨 일이야"를 읽으면서 회사에 대해 더 알아가는 시간을 가졌다.

2. 팀 프로젝트 리팩토링

3주라는 촉박한 일정으로 인해 팀 프로젝트에 도입하지 못했던 기능을 추가하고 성능이나 구조상 문제가 될 법한 부분을 개선했다. 여러 가지 문제 해결 방법을 시도하면서 Apache Kafka와 같은 새로운 기술을 접해보기도 했다.

3. 문제 해결(problem solving)

‘문제 해결’은 자신 있는 분야 중에 하나였는데 우테캠 코딩테스트를 마지막으로 알고리즘 문제를 하나도 풀지 않았더니 비교적 쉬운 코딩테스트도 떨어지는 불상사가 발생해서 캠프가 끝나고 다시 조금씩 풀기 시작했다. 이제 계속할 필요성은 많이 사라졌지만 하루를 시작할 때 한 문제씩 풀어주니 뇌가 활성화되는 느낌이 들어서 간간이 풀어볼 생각이다.

4. 개인 공부

평소에 컴퓨터의 로우 레벨 동작에 대한 지식이 부족하다고 생각했고 궁금한 점도 많아서 캠프가 시작할 때쯤 개인 공부로 컴퓨터 구조와 시스템 프로그래밍에 대한 책, "Computer Systems A Programmer’s Perspective Paperback"을 읽기 시작했다. 아침에 교육장(우아한형제들 작은집)으로 이동하는 동안, 그리고 밤에 집에 돌아와서 틈틈이 읽었고 캠프가 끝난 후에도 꾸준히 읽었다. 그동안 모호하게 알고 있던 부분에 대해 깊이 파고들 수 있는 좋은 기회였다.

앞으로 어떻게 지낼 예정인지, 목표는 무엇인지

얼마 전까지 거의 매일 블로그에 학습 기록을 남겼다. 그런데 정리에만 1시간 이상 걸릴 때가 종종 있어 꼭 기억하고 싶은 내용이나 당일 회고 위주의 간단한 내용만 정리하는 것으로 방법을 바꿔 꾸준히 기록해 나갈 생각이다.

지금까지는 하루빨리 사회에서 자 리잡고 싶다는 생각이었고, 항상 성장에 대한 조급함이 있었다. 하지만 주변으로부터 값진 조언을 받고 나서 이제는 조급함은 버리되 게으르지 않게 부단히 노력하자는 마음이다. 기술을 깊이 이해해 안정적인 서비스를 만드는 개발자가 되고 싶다. 더불어 소프트 스킬 역량도 향상시키고 싶다. 목표를 모두 이루는 날이 오면 좋겠다.

최준영 님

2023년 5~6월 관악구, 우리 집

다 아는 내용이네

우아한기술블로그에서 우아한테크캠프 6기 모집글의 커리큘럼을 읽으며 든 생각이다. “다 아는 내용이네” 지금 생각해 보면 굉장히 부끄럽지만 솔직하게 말하면 실제로 이렇게 생각했었다. Java 언어 기반의 백엔드 개발을 꿈꾸고 있는 개발자라면 어렵지 않게 접할 수 있는 키워드들이었다. 다만 조금 친하지 않은 키워드(TDD, 클린코드, 코드 리뷰 등)들이 있긴 했지만 말이다.

그래도 지원한 이유

내가 그때까지 진행한 프로젝트는 대부분 개인 프로젝트였다. 개인 프로젝트를 진행하면서 느낀 한계점은 하나의 문제를 해결하더라도 해결 방법은 내 생각이었고 그 이상을 벗어날 수 없었다는 것이다. 아무리 다른 해결 방법이 있을까 하며 고민을 해도 결국 내 시야를 벗어나지 못했다. 그렇다. 나는 우물 안의 개구리였고 이를 잘 알고 있었다. 그래서 우아한테크캠프를 통해서 이 한계를 극복해 보고자 했다. 같이 교육을 듣게 되는 교육생, 코치분들과 생각을 공유하고 시야를 넓히고 해결 방법도 얻을 수도 있겠다는 생각으로 지원하였다.

2023년 7~8월 송파구, 작은 집

한참 몰랐네

지원하기 전과 다르게 우아한테크캠프에서 "한참 부족했구나"라는 생각이 들기까지 오랜 시간이 걸리지 않았다. 간단해 보이는 미션 요구사항이라 할지라도 테스트를 먼저 작성하며 구현해야 한다는 점이 낯설어 적잖이 헤매었고, 코드 레벨에서 컨벤션의 존재도 페어로부터 그때 처음 알게 되었다.

또한 캠프를 진행하며 자연스럽게 코드 레벨에서 얻었던 인사이트들이 몇 가지 있다. ‘값을 가져와 처리하는 것보다 객체에게 메시지를 전달하기’, ‘원시값을 포장해서 포장한 객체에게 적절한 책임을 묻기’ , ‘final 키워드로 변경을 방지해 불변 객체로 다루는 것과 컬렉션 API의 오남용 방지 및 불변성을 보장해 주기 위해 일급 컬렉션을 사용할 수 있다는 것’, ‘코드 가독성을 높이기 위해 들여 쓰기는 한 단계로 하기’, ‘else 키워드를 쓰지 않기’, ‘메서드는 길지 않게 하기’등이 있었다.

우아한테크캠프 이전 ‘다 아는 내용’이라 자신만만했던 나에게 앞서 언급한 코드 레벨에서 얻은 인사이트들은 전부 처음 듣는 이야기였고 프로젝트를 진행하며 적용해 본 적 없던 내용들이었다. 한참 몰랐다는 것을 깨닫는 것도 잠시 미션을 통해 페어와 생각을 나누며, 리뷰어와 소통하며 그리고 직접 미션에 적용해 보며 나 자신을 설득할 수 있었다. 이를 통해 이전과는 다른 수준의 성장을 이뤄냈다고 느꼈다.

생각 나누기

매주 미션의 끝에는 코치님들이 우리가 진행한 미션에 대해 왜 그런 방식으로 요구사항을 해결했는지 물으며 함께 생각을 공유하는 시간을 가졌다. 처음에는 별다른 고민 없이 “그냥 이렇게 작성하면 되는데, 이유가 필요한가?”라고 생각했는데, 이유를 명확하게 설명하는 교육생분들을 보며 정말 놀랐다. 이때 코드를 그렇게 작성한 이유를 설명할 수 없다면 나중에 팀원과 페어 심지어 나조차 설득할 수 없겠다는 생각이 들었다. 이후, 지난날을 반성하며 한 줄 한 줄 "나는 왜 이렇게 코드를 작성하는가" 생각해 보는 습관을 가지게 되었다.

이러한 습관은 우아한테크캠프 교육생분들과 같은 문제를 해결하는 여러 가지 방법에 대해 생각을 나누는데 도움을 주었다. 예컨대 ‘테스트 데이터를 미리 넣어놓는 방법’과 ‘테스트마다 매번 새로운 데이터를 만드는 방법’에 대해 이야기해 보았다. 전자의 경우에는 테스트 시 매번 테스트 객체를 만들지 않아도 되어서 협력 객체 생성 등의 반복적인 작업을 간소화할 수 있다는 장점이 있다. 반면 미리 넣어놓은 데이터가 변경될 때, 테스트 데이터에 의존하고 있던 데이터가 모두 실패할 수 있다는 단점이 있다. 후자의 경우에는 테스트마다 협력객체 생성 등의 반복적인 작업을 진행해야 한다는 단점이 있다. 장점으로는 테스트 데이터가 변경되었을 때 그 변경이 미치는 범위가 좁다는 것이다. 각 방식의 장단점을 서로 이야기해 보며 교육생분들이 어떻게 사고하는가를 배울 수 있는 경험이었다.

정답은 없다

우아한테크캠프에서는 미션을 진행한 뒤에도 생각을 많이 나누었다. 나도 정말 생각 나누기를 좋아했지만 나보다 더 좋아하는 교육생분들이 많아서 대단하다고 느낄 정도였다. 이외에도 우리가 나눈 이야기들은 ‘표준 예외를 사용하는 것과 커스텀 예외를 정의해서 사용하는 것의 차이’, ‘Wrapper Class와 Primitive Type의 차이‘, ‘원시값 포장의 필요성’ 등이 있었고 이야기를 하면 할수록 정답을 찾을 수 없다는 것이 느껴졌다. 결국 자신이 어떤 가치에 더 중점을 두고 있는지에 따라 저마다 생각이 다를 수 있었고 우리는 그 다름을 인정하고 맞춰가는 방향을 선택하기로 했다.

팀 프로젝트

팀 프로젝트는 상품, 재고, 주문, 결제 도메인이 있는 쇼핑몰 프로젝트를 진행하였고 우아한테크캠프 교육 기간 동안 배운 내용을 적용하며 찐한 협업을 경험할 수 있었던 시간이었다. 우리 팀은 처음부터 끝까지 거의 대부분의 기능 구현을 페어 프로그래밍으로 진행하였고 팀원들 모두가 프로젝트에 대한 이슈와 도메인에 대한 이해도를 높였다. 이러한 협업 방식은 우리 팀이 함께 주어진 문제를 헤쳐나가는데 도움이 되었다고 생각한다.

한편 프로젝트의 동시 처리 성능을 높이기 위해 인덱스를 활용하거나, 트랜잭션 내외부 API 호출을 분리하는 경우 또는 프로젝트 구조, 데이터베이스 테이블을 변경하는 작업과 장애가 발생했을 때의 대처 방안 등을 고민했다. 이에 대해 회의를 하면서 주어진 자원과 시간을 고려해 보았을 때 ‘어디까지 개선해야 하는지’, ‘왜 해야 하는지’, ‘어떻게 해야 하는지’를 생각해야 했다. 현재 우리 서버에 발생할 수 있거나 발생하고 있는 상황인지를 되짚어보았고 ‘어쩌면 우리가 발생하지도 않은 장애나 트래픽 처리에 대해 오버 대응하고 있지 않나’라는 생각이 들었다.

이후 성능 테스트를 통해 문제를 마주해 보고 원인을 분석한 뒤 그에 맞는 적절한 대응을 하기로 결정했다. 그래서 우리가 구축한 서비스가 한 달에 벌어들일 금액이 얼마인지를 결정하고 이 가정을 토대로 서비스를 이용하고 있는 사용자 수, 주문 수를 역으로 계산해 처리해야 되는 TPS를 결정하였다. 그리고 목표한 TPS를 달성하기 위해 다시 움직였고 이제는 진짜 일어날 문제들을 만나러 갔다.

하나의 예시로 ngrinder를 사용해 주문 API 성능 테스트를 진행한 결과 TPS 값 1을 넘지 못하는 결과를 얻었는데 모니터링을 통해 커넥션 풀의 수가 부족한 사실을 알 수 있었다. 코드를 분석해 보니 주문 결제 트랜잭션 내에서 결제 API를 호출하는 로직이 있어서 적어도 1.3초 이상 커넥션을 점유하고 있는 문제를 확인하였다. 이 문제를 해결하기 위해 주문 트랜잭션에서 결제 API 호출을 분리하고 결제 API가 실패했을 때 트랜잭션에서 성공한 로직을 직접 롤백하는 로직을 작성함으로써 TPS14까지 개선하였다.
이외에도 시나리오 기반의 성능 테스트를 진행하여 그때마다 마주한 문제들을 해결해 나가면서 왜 개선해야 하는지, 어떻게 해결해 나아가야 하는지를 팀원들과 함께 배울 수 있었다.

바로 잡아준 코치님들

교육생끼리 회의를 진행하고 이야기를 하다 보면 잘못된 방향으로 나아갈 수 있는 여지가 있었다. 이를 테면 데이터베이스로의 접근 횟수를 줄여 조회 성능을 개선하기 위해 상품 조회 API에 캐싱을 도입하였는데 코치님이 검색 조건의 가짓수가 많다면 캐시 히트율이 떨어져 캐시 메모리만 할당된 채로 원하는 성능을 얻지 못할 수 있다는 피드백을 주셨다. 우리 팀이 미처 예상하지 못했거나 간과했던 부분들을 되짚어주시면서 보다 올바른 방향성을 제시해 주셨다. 덕분에 우리 팀은 상품 검색 조건에서의 캐싱 도입을 철회하고 변경이 적고 조회가 많은 상위 10개의 메인 상품 조회 API만을 캐싱함으로써 가장 적은 메모리를 사용하며 조회 성능을 극대화할 수 있었다.

2023년 9 월~돌아온 관악구, 우리 집

우아한테크캠프 이후의 시간들

우아한테크캠프가 마무리되고 이후에는 부족하다고 느꼈던 데이터베이스, JPA에 대해 깊이있게 공부했다. 또한, 코드 레벨에서 얻은 인사이트들과 깨달음을 토대로 기존에 진행했던 프로젝트를 리팩토링 하는 시간을 가졌다.

특히 프로젝트를 진행하면서 데이터베이스와 JPA 관련 이슈들이 많았다. 사용한 MySQL의 경우 인덱스 기반의 레코드 잠금을 진행한다는 점을 제대로 알지 못해 데드락 및 성능 저하를 경험했었다. JPA에서 OSIV와 영속성 컨텍스트에 대해서 제대로 알지 못해 평균 50ms가 걸릴 트랜잭션들이 1300ms가 걸리는 경험을 하기도 했었다. 그래서 우아한테크캠프가 끝나자마자 나는 관련 책들을 구매해서 더 깊이 공부하며 제대로 알아가고자 노력하고 있다.

또한 개인 프로젝트를 리팩토링 하는 시간을 가지면서 단지 코드 레벨에서 얻은 인사이트들, 대표적으로 *객체지향 생활체조를 지키는 것만으로도 단위 테스트 수가 늘어났고 단위 테스트 수가 늘어남에 따라 더욱 가독성 있는 코드로 리팩토링하는 것이 쉬워졌다. 테스트를 추가해 나가면서 테스트하기 좋은 구조로 변경했고 이로 인해 자연스럽게 확장성 있는 설계에 가까워져 어렵지 않게 기능들을 추가해 나갈 수 있었다.

*객체지향 생활체조는 마틴 파울러의 저서 "소트웍스 앤솔러지"에서 소개한 ‘객체지향적 사고방식을 위한 9가지 원칙’을 말한다.

달라진 나

정리해 보자면 우아한테크캠프에서 나는 정말로x100 새로운 경험들을 얻었다. 페어 프로그래밍, 우아한형제들 개발자분들로부터 받는 코드 리뷰, 데일리 미팅 회고, 매주 금요일 주간 회고, 생각 나누기, 팀원들과 4인 프로그래밍, 팀원들과 하루종일 회의만 하기 그리고 든든한 잠실 음식들까지 모두 새로운 경험들로 가득 찬 시간이었다.

이 경험들을 통해 1) 문제 해결의 답부터 찾던 과거에서 나의 문제 해결 방법을 설득할 근거를 찾는 현재로, 2) 객체로부터 데이터를 가져와 스크립트 형식의 코드를 작성하던 과거에서 객체 간 메시지를 보내어 코드를 작성하는 현재로, 3) “~ 이럴 것이다”라는 추측보다는 “직접 확인해 보니 이렇다”라는 근거를 드는 방향으로 변화할 수 있었다.

어쩌면 이 모든 것들을 영원히 깨닫지 못했을 수도 있겠다는 생각이 드는 한편, 이 짧은 시간 동안 이렇게 중요한 것들을 배울 수 있었음에 우아한테크캠프 운영진분들과 코치님들, 교육생분들께 감사함을 느낀다.