2025. 8. 30. 20:44ㆍKIM CHAN HEE/생각
안녕하세요. iOS 개발자 찬히히입니다.
이제 “진짜 iOS 개발자가 됨”이라고 적었던 글을 쓴 지도 벌써 6개월 정도가 지났습니다. 당시 글 마지막에는 이런 말을 적었습니다.
몇 년 뒤에 이 글을 다시 읽었을 때,
“이때는 진짜 아무것도 몰랐네.”
하면서 웃을 수 있을 만큼 성장해 있으면 좋겠습니다.
몇 년까지 기다릴 필요는 없었던 것 같습니다. 6개월이 지난 지금 다시 읽어보니, 진짜 아무것도 몰랐던 것 같습니다. (..ㅋㅋ)
회사에서 사용하는 코드를 잘 이해할 수 있을지, 팀에 잘 적응할 수 있을지, 도움이 되는 개발자가 될 수 있을지 걱정하면서 가능하면 사고도 안 치고 잘 버텨보겠다고 적었습니다. 크고 작은 사고를 전혀 안 쳤다고는 말할 수 없지만.. 그래도 아직 잘 다니고 있습니다. ㅊㅎㅎ
취업하기 전에도 개발을 했습니다.
개인 앱을 만들고 App Store에 배포했고, 프로젝트의 구조를 고민하고 테스트 코드도 작성했습니다. 오픈소스에 기여하고 알고리즘 문제도 꾸준히 풀었습니다. 당시에도 나름대로 열심히 개발하고 있다고 생각했습니다.
하지만 회사에서 돈을 받고 실제 제품의 코드를 작성하는 일은 생각보다 많이 달랐습니다.
개인 프로젝트에서는 만들고 싶은 기능을 직접 선택할 수 있었고, 구조가 마음에 들지 않으면 처음부터 다시 만들 수도 있었습니다. 일정이 늦어져도 대부분 내가 감당하면 됐고, 예상하지 못한 상황에서 기능이 동작하지 않더라도 그 영향은 주로 나와 프로젝트 안에 머물렀습니다.
회사에서 작성한 코드는 실제 사용자가 사용합니다.
내가 변경한 코드가 동료의 작업에 영향을 주고, 잘못 저장된 데이터가 제품에 대한 신뢰를 떨어뜨릴 수 있으며, 예상하지 못한 네트워크 환경에서도 앱은 가능한 범위에서 계속 동작해야 했습니다.
돈을 받고 일하게 되었다고 갑자기 더 성실한 사람이 된 것은 아닙니다.
다만 돈을 받고 일한다는 사실은 내가 작성한 코드의 결과에 책임이 생겼다는 의미로 다가왔습니다. “열심히 만들었다”는 말만으로는 부족했고, 실제로 동작해야 했으며, 기존 기능을 망가뜨리지 않아야 했고, 문제가 발생하면 원인을 찾고 다시 같은 문제가 생기지 않도록 해야 했습니다.
입사 후 6개월은 취업 준비를 하며 가지고 있던 아마추어적인 생각들을 하나씩 발견하고 버려나가는 시간이었습니다.
코드가 동작하면 기능이 끝난다고 생각했던 것, 새로운 구조가 항상 기존 구조보다 좋다고 생각했던 것, 정상적인 상황을 먼저 만들고 예외 처리는 나중에 해도 된다고 생각했던 것, 내가 이해할 수 있으면 다른 사람도 이해할 수 있을 것이라고 생각했던 것들이 실제 제품 앞에서는 자주 통하지 않았습니다.
물론 이제 완전히 프로다운 개발자가 되었다는 뜻은 아닙니다.
오히려 6개월 동안 일하면서 프로답게 일한다는 것이 무엇인지 이제 조금 알게 된 것에 가깝습니다.
이번 글은 개발자 지망생이 실제 제품을 만드는 iOS 개발자가 된 뒤, 처음 6개월 동안 무엇을 경험했고 어떤 생각을 버렸으며 어떻게 달라졌는지를 정리한 글입니다.
뭐, 그리 대단한 성장기나 대단한 기술 이야기는 아니고, 월급을 받으며 코드를 작성하기 시작한 중고 신입 개발자의 개인적인 기록입니다. ㅊㅎㅎ
커밋 기록을 되돌아보니 입사 이후 8월 말까지 약 370개의 커밋이 남아 있었습니다.
번역 리소스 변경이나 작은 수정 커밋도 많기 때문에 숫자 자체에 큰 의미가 있는 것은 아닙니다. 그래도 당시 무엇을 고민했고, 어떤 문제를 반복해서 만났는지를 떠올리는 데에는 꽤 도움이 되었습니다.
커밋을 하나씩 살펴보니 단순히 새로운 기능을 만든 기록만은 아니었습니다. 당연하다고 생각했던 것들이 실제 제품에서는 왜 통하지 않는지 배우고, 그 생각을 하나씩 수정해 온 기록에 더 가까웠습니다.
그럼 지난 6개월 동안 무엇을 했고, 그 과정에서 어떤 생각이 달라졌는지 적어보겠습니다.
처음 맡은 일
입사 후 처음으로 크게 맡은 작업은 앱의 다국어 대응이었습니다.
외부 번역 플랫폼인 Localazy를 프로젝트에 적용하고, 기존에 화면마다 작성되어 있던 문자열을 정리했습니다. 언어 설정 화면을 만들고, 번역 데이터를 불러오거나 캐싱하고, 설정이 변경되었을 때 화면에 반영하는 과정도 구현했습니다.
처음에는 문자열을 번역 키로 교체하면 되는 작업이라고 생각했습니다.
하지만 실제 제품에서는 생각보다 고려할 것이 많았습니다.
네트워크 연결에 실패하면 어떻게 해야 하는지, 외부 번역 데이터를 가져오지 못해도 앱이 실행되어야 하는지, 사용자가 언어를 변경했을 때 어느 시점에 화면을 다시 그려야 하는지, 번역되어야 하는 값과 원본 그대로 유지되어야 하는 값을 어떻게 구분할지 등을 함께 고민해야 했습니다.
그래서 Localazy와 직접 연결되는 부분을 Manager로 모으고, 기존 화면의 변경을 줄일 수 있도록 Text와 String을 확장했습니다. 외부 연결에 실패하더라도 앱에 포함된 번역 파일을 사용할 수 있도록 fallback도 구성했습니다.
당시에는 주어진 기능을 구현하느라 크게 의식하지 못했지만, 지금 다시 보니 입사 후 처음 배운 것은 외부 라이브러리를 사용하는 방법보다도 경계를 만드는 방법에 가까웠던 것 같습니다.
외부 서비스가 제품 전체에 직접 퍼지지 않게 만들고, 외부 서비스가 실패해도 제품은 가능한 범위에서 계속 동작하도록 만드는 일이었습니다.
개인 프로젝트에서는 정상적으로 동작하는 상황을 먼저 생각했다면, 회사에서는 실패하는 상황도 제품의 일부라는 것을 조금씩 배우기 시작했습니다.
화면을 만드는 일이라고 생각했다
다국어 작업 이후에는 Finished Activity, Team Report, Player Report와 같은 대시보드 리포트 화면들을 수정했습니다.
처음에는 주로 UI 작업이라고 생각했습니다.
디자인 요구사항에 맞춰 화면을 나누고, 날짜와 시간 컴포넌트를 분리하고, 선수가 없는 세션의 빈 화면을 처리했습니다. 리브랜딩에 맞춰 색상과 이미지, 레이아웃을 변경하기도 했습니다.
하지만 화면을 수정하다 보니 당연하게도 자연스럽게 화면보다 아래에 있는 상태를 만지게 되었습니다.
라이브 중인 액티비티와 이미 종료된 액티비티는 같은 화면을 사용하더라도 동작 방식이 달랐습니다. 끝난 Activity에 들어갔을 때는 더 이상 필요하지 않은 UDP 동작을 종료해야 했고, 액티비티와 세션의 시작·종료 시간을 올바르게 구분해야 했습니다.
선수의 데이터도 단순히 존재하는지를 확인하는 것으로는 부족했습니다. 해당 선수가 액티비티에 참여했는지, 특정 세션에 참여했는지, 현재 연결되어 있는지, 과거에는 연결되어 있었는지를 구분해야 했습니다.
화면에 표시되는 값 하나가 어디에서 만들어졌고, 어떤 상태일 때 유효한지 알아야 UI도 제대로 만들 수 있었습니다.
그때부터 UI는 결국 데이터 흐름의 마지막 부분일 뿐이다 라는 생각을 하게 되었습니다.
보이는 부분을 고치기 위해서는 보이지 않는 부분이 어떤 규칙으로 움직이는지 먼저 이해해야 했습니다.
운동 지표(Metric) 하나를 추가한다는 것
입사 후 제품의 도메인을 가장 깊게 경험한 작업 중 하나는 Action Effort Metric이었습니다.
처음에는 새로운 메트릭을 계산하고 보여주는 기능이라고 생각했습니다.
하지만 실제로는 하나의 메트릭을 추가하기 위해 계산 로직, 설정값, API, DB column, 단위, 번역, 테이블, 차트, 선수 리포트와 팀 리포트가 모두 함께 변경되어야 했습니다.
같은 값이라도 사용자의 단위 설정에 따라 표현이 달라졌고, 화면에 보여주는 이름과 내부에서 사용하는 key도 구분해야 했습니다. DB에 저장할 때 사용하는 column과 API에서 사용하는 값도 맞아야 했습니다.
“메트릭 하나 추가”라는 짧은 문장 아래에 생각보다 많은 연결 관계들이 숨어 있었습니다.
이 과정에서 기능은 특정 파일 하나에 존재하지 않는다는 것을 배웠습니다.
제품의 기능은 여러 레이어에 걸쳐 있고, 그 레이어가 같은 의미를 공유할 때 비로소 하나의 기능으로 동작했습니다.
또한 데이터가 화면에 정상적으로 표시되는 것만으로는 충분하지 않았습니다. 계산이 정확해야 하고, 올바른 선수와 세션에 저장되어야 하며, 앱을 종료하고 다시 실행해도 같은 의미로 복원되어야 했습니다.
App의 제품은 실제 선수의 위치, 속도, 가속도와 같은 데이터를 다루고 있습니다.
이전에는 앱이 종료되지 않고 정상적으로 보이면 된다고 생각했던 부분도, 실제 제품에서는 데이터의 정확성과 신뢰의 문제라는 것을 알게 되었습니다.
변경하기 쉬운 코드를 고민하다
취업을 준비하며 모듈러 아키텍처를 적용한 Swifty Proteins 프로젝트를 진행한 적이 있습니다. 당시에는 기능을 동작하게 만드는 것에서 더 나아가, 요구사항이 달라져도 변경 범위를 예측하고 필요한 부분만 수정할 수 있는 구조를 고민했습니다.
회사에서도 비슷한 고민을 하게 되었습니다.
당시 메트릭의 내부 key와 화면에 표시할 이름, 단위, 번역 정보, DB column 등이 여러 파일에 나뉘어 있었습니다.
새로운 메트릭을 추가하거나 기존 메트릭의 이름을 바꾸려면 관련된 파일을 모두 찾아 수정해야 했습니다. 한 곳이라도 놓치면 DB에는 값이 저장되어 있지만 화면에는 나오지 않거나, 정렬과 필터가 제대로 동작하지 않는 문제가 생겼습니다.
처음에는 문제가 발생할 때마다 누락된 부분을 찾아 수정했습니다.
하지만 비슷한 문제가 반복되면서 개별 오류를 고치는 것보다, 메트릭의 정의가 여러 곳에 나뉘어 있는 구조부터 바꿔야 한다고 생각했습니다.
그래서 MetricMeta라는 구조를 만들고, 메트릭과 관련된 정보를 한곳에서 관리하기 시작했습니다. 각 화면과 기능이 서로 다른 이름과 key를 관리하는 대신, 같은 메트릭 정의를 사용하도록 기존 코드를 하나씩 변경했습니다.
물론 한 번에 모두 바꿀 수는 없었습니다.
이미 여러 화면과 DB 로직이 기존 구조를 사용하고 있었기 때문에, 기존 기능이 계속 동작하는지 확인하며 사용처를 하나씩 옮겨야 했습니다. 화면에 표시하는 이름은 바꿀 수 있어도 내부 key와 DB column은 기존 데이터와 연결되어 있어 조심해서 다뤄야 했습니다.
이 작업을 하면서 변경하기 쉬운 코드는 단순히 파일이 잘 나뉘어 있거나 중복이 적은 코드만을 의미하지 않는다는 것을 배웠습니다.
하나의 정보를 바꿀 때 수정해야 하는 곳이 명확하고, 일부를 놓쳐도 예상하지 못한 문제가 생기지 않도록 만드는 것이 더 중요했습니다.
예전에는 중복된 코드를 함수로 묶거나, 같은 기능의 코드를 보기 좋게 정리하는 것을 주로 리팩토링이라고 생각했습니다. 지금은 같은 의미를 가진 정보가 여러 곳에서 서로 다르게 관리되지 않도록 변경 지점을 줄이는 것도 중요한 리팩토링이라고 생각합니다.
예전에는 중복된 코드를 함수로 묶는 것이나 같은 기능을 깔끔하게 보일 수 있도록 하는 것을 주로 리팩토링이라고 생각했습니다. 지금은 같은 의미를 가진 정보가 여러 곳에서 서로 다르게 관리되지 않도록 정리하는 것도 중요한 리팩토링이라고 생각합니다.
그리고 기존 기능을 유지하면서 구조를 바꾸는 일은, 아무것도 없는 상태에서 새로운 구조를 만드는 것보다 훨씬 어려웠습니다. 새로운 구조를 설계하는 것뿐만 아니라 기존 기능을 유지하며 안전하게 옮기는 과정까지 고민해야 했기 때문입니다.
알고리즘 공부가 실제 코드에 도움이 되었나?
이걸 알고리즘 공부라고 해야하나, 언어 공부라고 해야하나.. 이전부터 알고리즘 문제를 꾸준히 풀면서 자료구조의 특성과 연산의 시간 복잡도를 함께 생각하는 습관이 들여져있었습니다.
Swift에서 함수를 사용할 때면 Xcode에서 Option 키를 누른 채 클릭해 Quick Help를 열고, Complexity부터 확인하곤 했습니다. 코드가 동작하는지만 보는 것이 아니라, 데이터가 어떤 구조로 저장되어 있고 조회·삽입·삭제 과정에서 어느 정도의 비용이 발생하는지를 한 번 더 생각하는 습관이었습니다.
그러던 와중 입사 후 실시간 데이터를 처리하는 코드에서 Array.removeFirst()가 반복적으로 사용되는 부분을 발견했습니다.
Swift의 Array.removeFirst()는 첫 번째 요소를 제거한 뒤 나머지 요소를 이동해야 하므로 O(n)의 시간 복잡도를 가집니다. 데이터가 계속 들어오는 상황에서 이 작업이 반복되면 불필요한 비용이 누적될 수 있는 구조였습니다.
이를 개선하기 위해 swift-collections의 Deque를 적용했습니다. 메트릭을 이름이나 key로 반복해서 검색하던 부분도 Dictionary와 Set을 활용해 불필요한 탐색을 줄여 필요한 값을 더 빠르게 찾을 수 있도록 변경했습니다.
알고리즘 문제를 많이 푼다고 바로 좋은 앱을 만들 수 있는 것은 아니라고 생각합니다. 알고리즘 공부만으로 제품의 요구사항이나 사용자의 문제를 이해할 수 있는 것도 아닙니다.
하지만 문제를 이해한 뒤 어떤 자료구조와 접근 방법을 선택할지 판단하는 데에는 분명 도움이 되었습니다. 반복되는 연산이 실제 제품의 성능에 어떤 영향을 줄 수 있는지 한 번 더 의심하고 확인하는 습관으로도 이어졌습니다.
2024년의 회고에서 제가 removeFirst()의 시간 복잡도를 열심히 설명하고 있었는데, 2025년의 제가 진짜 회사 코드에서 그 부분을 바꾸고 있을 줄은 몰랐습니다. ㅋㅋ
취업을 준비하며 공부했던 내용이 실제 제품의 문제와 연결되는 경험이라 개인적으로 좀 재미있었습니다.
네트워크 공부 하고 싶다
예전 계획에는 항상 “네트워크 공부”가 있었습니다.
그리고 입사 후에는 원하던 것보다 조금 더 실전으로 네트워크를 만나게 되었습니다.
제품은 여러 디바이스로부터 실시간 데이터를 수신하기 위해 UDP와 TCP를 함께 사용하고 있었습니다.
실시간으로 계속 들어오는 데이터는 전송 속도와 지연이 중요했기 때문에 UDP로 수신했고, 데이터의 순서와 누락 여부를 확인하며 안정적으로 전달해야 하는 작업에는 TCP를 사용했습니다. 각 통신 방식의 특징을 공부하는 데서 그치지 않고, 제품의 상황에 따라 어떤 방식을 선택해야 하는지를 배웠습니다.
데이터가 정상적으로 들어오는지를 판단하는 일도 생각보다 단순하지 않았습니다.
마지막 데이터를 받은 뒤 얼마나 시간이 지났는지, 연결이 완전히 끊어진 것인지, 아니면 잠시 데이터가 들어오지 않는 것인지를 구분해야 했습니다.
기존 Timer에서 처리하던 keep-alive 로직을 UDP queue에서 처리하도록 변경했고, 단순히 카운트를 증가시키는 대신 마지막으로 데이터를 받은 실제 시간을 비교해 timeout을 판단하도록 수정했습니다.
정상 데이터가 다시 들어오면 수신 상태를 복구해야 했고, 심박수나 배터리처럼 서로 다른 주기로 들어오는 데이터도 각각의 특성에 맞게 처리해야 했습니다.
이후에는 시뮬레이터를 구현하면서 TCP 통신과 Bonjour도 다루게 되었습니다.
Bonjour를 이용해 같은 네트워크에 있는 시뮬레이터를 자동으로 찾고 연결했습니다. TCP로 전달받은 파일을 기반으로 액티비티와 세션을 생성하고, 준비가 완료되면 라이브 화면을 자동으로 실행하는 흐름도 만들었습니다.
이 과정에서 UDP와 TCP의 특징을 아는 것만으로는 실제 기능을 완성할 수 없다는 것을 알게 되었습니다.
TCP 연결에 성공하더라도 어디까지가 하나의 메시지인지, 어떤 데이터가 먼저 전달되어야 하는지, 모든 파일을 받았다는 것을 어떻게 판단할지 정해야 했습니다. 잘못된 데이터가 들어왔을 때 어떻게 처리할지, 연결이 끊어진 뒤 어느 상태부터 다시 시작할지도 필요했습니다.
결국 소켓은 데이터를 전달하는 통로일 뿐이었습니다. 그 위에서 데이터의 형식과 순서, 완료 조건과 실패 처리를 약속하는 프로토콜이 있어야 서로 같은 의미로 통신할 수 있었습니다.
예전에는 네트워크를 프로토콜과 계층 중심으로 공부했다면, 실제 제품에서는 순서와 시간, 상태와 생명주기의 문제로 만나게 되었습니다.
연결에 성공했다는 이벤트 하나보다 중요한 것은 그 연결이 언제 유효해지는지, 어떤 데이터를 받아야 준비가 완료되는지, 연결이 끊어졌을 때 무엇을 정리하고 어디서부터 다시 시작해야 하는지를 정하는 일이었습니다.
네트워크 기능은 연결하는 것으로 끝나는 것이 아니라, 연결된 이후의 상태를 올바르게 관리하는 일이라는 것을 많이 배웠습니다.
실제 경기 데이터를 다시 실행하는 시뮬레이터
입사 후 6개월 동안 가장 넓은 범위를 다뤘던 작업은 시뮬레이터였습니다.
실제 경기 데이터를 기반으로 앱의 라이브 동작을 다시 실행해, 경기장이나 실제 디바이스가 없어도 당시의 환경을 재현할 수 있도록 만드는 작업이었습니다.
시뮬레이터에서 전달받은 분석 정보와 액티비티, 세션 파일을 파싱하고, 각 파일이 같은 액티비티의 데이터인지 검증했습니다. 검증이 완료되면 액티비티와 세션을 DB에 저장하고 UDP 서버를 준비한 뒤, 실제 라이브를 시작할 때와 같은 흐름으로 화면에 진입하도록 구현했습니다.
액티비티를 생성하는 것만으로는 실제 라이브 동작을 재현할 수 없었습니다.
각 세션의 시작과 종료 시각에 맞춰 세션이 자동으로 실행되도록 스케줄링해야 했고, 마지막 세션이 끝나면 액티비티도 함께 종료해야 했습니다. 화면을 벗어나거나 실행 중인 액티비티를 종료했을 때는 이미 등록된 스케줄이 남지 않도록 해제해야 했습니다.
처음에는 시뮬레이터가 전달한 데이터를 앱에서 실행하면 되는 기능이라고 생각했습니다. 하지만 구현할수록 데이터가 전달된 이후의 상태와 실행 순서를 함께 관리해야 했습니다.
팀 정보와 Analytics에서 사용하는 index가 항상 같은지, 여러 파일의 activity index가 일치하는지, 첫 번째 세션을 어떤 기준으로 찾을지, 마지막 세션이 끝났을 때 어느 시점에 전체 액티비티를 종료할지 등을 하나씩 확인해야 했습니다.
스케줄을 화면과 ViewModel 등 여러 위치에서 각각 등록하고 해제하면 중복 실행이나 해제되지 않은 작업이 생길 수 있었습니다. 이를 방지하기 위해 스케줄의 등록과 해제를 한곳에서 관리하도록 구조를 정리했습니다. 새로운 시뮬레이션을 시작하거나 화면을 벗어날 때도 이전 작업이 남지 않도록 생명주기를 함께 관리했습니다.
이 작업을 통해 파일 파싱과 데이터 검증, DB 저장, 네트워크 준비, 화면 전환, 시간에 따른 자동 실행까지 앱의 여러 영역을 하나의 흐름으로 연결해 볼 수 있었습니다.
시뮬레이터는 사용자에게 직접 보이는 기능은 아니지만, 실제 환경에서 발생한 동작을 다시 실행하고 확인할 수 있게 만드는 도구였습니다. 기능을 구현하는 것뿐만 아니라 같은 상황을 반복해서 재현할 수 있는 환경을 만드는 것도 제품을 개발하는 데 중요한 부분이라는 것을 배웠습니다.
6개월 동안 달라진 점
입사 초기에는 화면에 원하는 값이 나오지 않으면 그 값을 표시하는 코드부터 찾았습니다.
지금은 조금 다른 질문을 먼저 하게 되었습니다.
이 값은 어디에서 만들어졌는지, 원본 key는 무엇인지, 어떤 단위로 저장되었는지, 어느 선수와 액티비티와 세션에 속하는지, 현재 값인지 복원된 값인지, 언제 갱신되고 언제 사라져야 하는지를 확인하려고 합니다.
결국 6개월 동안 가장 많이 고민한 것은 데이터와 상태의 경계였던 것 같습니다.
- 번역된 문자열과 원본 key
- 화면의 display name과 DB column
- 라이브 데이터와 Finished 데이터
- 액티비티 데이터와 세션 데이터
- 연결된 상태와 데이터를 수신 중인 상태
- 현재 팀과 분석 데이터의 팀
- 기능의 실행과 생명주기 종료
예전에는 “본질에서부터 생각하는 개발자가 되고 싶다”는 말을 좋아했지만, 개발에서 본질이 무엇인지는 잘 몰랐습니다.
지금도 정확히 안다고 할 수는 없습니다.
다만 화면에 보이는 결과만 고치는 것이 아니라, 그 결과가 만들어지는 데이터와 상태의 규칙을 확인하는 것이 본질에 조금 더 가까운 일일 수 있다는 생각을 하게 되었습니다.
잘한 점
6개월 동안 가장 잘한 것은 모르는 코드라도 계속 따라가 본 것입니다.
처음에는 View를 수정하다가 ViewModel을 보게 되었고, ViewModel을 따라가다 SQL과 API를 보게 되었습니다. 메트릭을 수정하며 계산 Engine과 단위 체계를 확인했고, 네트워크 상태를 고치며 UDP queue와 timeout을 보게 되었습니다.
익숙한 영역에만 머물지 않고 제품이 동작하는 전체 흐름을 이해하려고 했습니다.
기능을 구현한 뒤 문제가 생겼을 때도 단순히 조건문을 추가하는 데서 끝내지 않고, 가능하면 상태가 잘못 만들어진 위치를 찾으려고 했습니다.
그리고 취업 준비를 하며 공부했던 것들이 실제 업무와 연결되는 순간도 많았습니다.
SwiftUI와 SceneKit, 네트워크, 자료구조, 모듈과 의존성에 대한 고민이 모두 그대로 사용된 것은 아니지만, 새로운 코드를 이해하고 문제를 나누는 데 도움이 되었습니다.
지금까지 해왔던 것들이 완전히 따로 떨어져 있지는 않았다는 점도 알게 되었습니다.
아쉬운 점
빠르게 구현하고 실제 동작을 확인하며 수정하는 데에는 조금 익숙해졌습니다.
반면 변경하기 전에 반드시 유지되어야 하는 조건을 정리하고, 이를 테스트로 남기는 것은 부족했습니다.
메트릭 구조를 변경한 뒤 누락된 값이나 기존 데이터와 맞지 않는 부분을 수정했고, 세션 복제와 시뮬레이터에서도 index와 시간, 상태 처리에 대한 수정이 반복되었습니다.
수정 자체는 필요한 과정이었지만, 일부는 다음과 같은 조건을 먼저 정의하고 테스트했다면 더 빨리 발견할 수 있었을 것 같습니다.
- 메트릭 key와 DB column은 항상 올바르게 대응되어야 한다.
- 세션의 종료 시각은 액티비티의 종료 시각을 넘을 수 없다.
- 세션을 복제해도 선수와 context의 관계는 유지되어야 한다.
- 연결 시간은 액티비티와 각 세션에 맞게 저장되어야 한다.
- 시뮬레이터 스케줄은 한 번만 등록되고 반드시 해제되어야 한다.
- 서로 다른 종류의 index가 우연히 같을 것이라고 가정해서는 안 된다.
취업 준비 프로젝트에서는 테스트 코드를 작성해 본 경험이 있었지만, 실제 제품에서는 기존 구조와 일정, 실행 환경을 이유로 테스트를 충분히 남기지 못했습니다.
좋은 구조를 고민하는 것과 그 구조가 올바르게 동작한다는 것을 검증하는 것은 별개의 일이라는 점을 배웠습니다.
커밋도 작은 변경을 빠르게 남기는 편이었는데, 때로는 하나의 작업이 여러 수정 커밋으로 나뉘어 전체 의도를 이해하기 어려운 경우가 있었습니다.
앞으로는 코드를 작성하는 것뿐만 아니라 변경의 이유와 유지되어야 하는 조건도 더 잘 남기고 싶습니다.
함께 일하고 싶은 동료가 되었나?
입사 전 목표 중 하나는 함께 일하고 싶은 동료가 되는 것이었습니다.
이 부분은 6개월의 짧은 단면만 보고 판단하기 어려운 목표인 것 같습니다.
아직 팀의 코드를 완전히 이해하지 못한 상태에서 질문해야 하는 경우도 많았고, 혼자 해결해 보려다가 시간이 오래 걸린 적도 있었습니다. 반대로 충분히 확인하지 않고 질문한 적도 있었을 것입니다.
회사에서는 혼자 가장 좋은 코드를 작성하는 것보다, 팀이 같은 문제를 이해하고 함께 유지할 수 있도록 만드는 것이 더 중요하다는 것을 느꼈습니다.
내 코드가 동작하는 것과 다른 사람이 안심하고 변경할 수 있는 것은 다릅니다.
앞으로는 구현한 결과뿐만 아니라 왜 이렇게 구현했는지, 어떤 선택지를 검토했고 무엇을 포기했는지를 더 잘 공유하고 싶습니다.
아직 함께 일하고 싶은 동료가 되었다고 자신 있게 말하기는 어렵지만, 적어도 어떤 동료가 함께 일하기 편한지는 조금씩 배우고 있습니다.
앞으로의 목표
입사 직후에는 회사와 제품에 적응하고 잘 버티는 것이 가장 큰 목표였습니다.
6개월이 지난 지금도 잘 버티는 것은 중요하지만, 다음에는 조금 더 구체적인 목표를 세워보려고 합니다.
- 메트릭 계산과 단위 변환을 테스트 가능한 구조로 만들기
- 액티비티와 세션, 선수 상태의 규칙을 명확히 정의하기
- 네트워크와 실시간 데이터 처리 더 깊게 공부하기
- Simulator를 반복 가능한 검증 환경으로 발전시키기
- 성능 문제를 느낌이 아니라 측정값으로 판단하기
- 큰 구조 변경 전에 전환 과정과 제거할 코드를 정리하기
- 코드의 변경 이유를 동료에게 더 잘 설명하기
- 꾸준히 기록하기
- 건강하기
여전히 하고 싶은 것은 많습니다. ㅊㅎㅎ
예전에는 새로운 기술을 얼마나 많이 경험했는지가 중요하다고 생각했습니다.
지금은 하나의 기능이 어떻게 만들어지고, 저장되고, 전달되고, 실패하고, 다시 복구되는지 끝까지 이해하는 것이 더 중요하다고 생각합니다.
새로운 것을 배우는 것도 계속하겠지만, 이미 알고 있다고 생각했던 것들을 더 깊게 이해하는 시간을 늘리고 싶습니다.
나는 지금 어떤 개발자가 되어가는 중일까?
이건 이전 회고들에서부터 이어지고 있는 자기 되돌아보기 입니다.
저는 기본기가 탄탄하고 무엇을 하더라도 본질에서부터 생각하는 개발자가 되어가고 있을까요?
그에 대한 답은 "아직은 많이 먼 것 같습니다."입니다. 6개월 만에 그런 개발자가 되었다고 적으면 다음 회고에서 많이 부끄러울 것 같습니다. (ㅋㅋ)
그래도 지난 6개월 동안 그런 개발자가 되기 위해 나름대로 노력했습니다. 화면에서 발견한 문제를 데이터와 상태, 네트워크와 생명주기까지 따라가 보았고, 당장 보이는 현상만 고치기보다 왜 그런 결과가 만들어졌는지를 확인하려고 했습니다.
하지만 실제 제품을 이해할수록 제가 모르고 있던 것이 더 많이 보였습니다. 기본기가 탄탄하다는 것이 단순히 기술을 많이 아는 것은 아니었고, 본질에서 생각한다는 것도 가장 멋진 구조를 만드는 일만은 아니었습니다.
오히려 데이터가 어떤 의미를 가져야 하는지, 반드시 유지되어야 하는 상태는 무엇인지, 실패했을 때 어떻게 복구할지, 동료가 안심하고 코드를 변경하려면 무엇을 남겨야 하는지를 끝까지 고민하는 일에 더 가까웠습니다.
입사 전에는 프로 개발자란 기술을 많이 알고 좋은 코드, 깨끗한 코드를 작성하는 사람이라고 생각했습니다. 입사 전에는 취업하면 진짜 개발자가 될 수 있을 것이라고 생각했습니다.
지금은 조금 다르게 생각합니다.
자신이 작성한 코드의 결과를 끝까지 확인하고, 사용자와 동료가 감당해야 할 위험을 줄이며, 주어진 시간과 환경 안에서 신뢰할 수 있는 제품을 만드는 사람이 프로에 더 가깝다고 생각합니다.
기능이 동작하는지뿐만 아니라 데이터가 정확한지, 예상하지 못한 상황에서도 앱이 버틸 수 있는지, 문제가 생겼을 때 원인을 다시 확인하고 같은 상황을 재현할 수 있는지까지 함께 고민해야 했습니다.
아직 모르는 것이 많고, 지금 작성한 코드도 시간이 지나 다시 보면 부족한 부분이 많이 보일 것 같습니다. 그래도 그게 좀 기대되기도 합니다. 6개월 전 글에서 바랐던 것처럼, 벌써 “이때는 진짜 아무것도 몰랐네”라고 웃을 수 있게 되었기 때문입니다.
다음 회고에서도 지금의 글을 보며 같은 말을 할 수 있었으면 좋겠습니다.
아직 기본기가 탄탄한 개발자가 되었다고 말하기는 어렵습니다. 그래도 화면에 보이는 것을 만드는 데서 시작해, 그 아래에 있는 데이터와 상태, 네트워크와 생명주기를 궁금해하는 개발자는 조금씩 되어가고 있는 것 같습니다.
기본기가 탄탄하고 무엇을 하더라도 본질에서부터 생각하는 개발자가 되고 싶다는 목표는 아직 그대로입니다.
다만 이제 그 목표가 이전보다 조금 더 구체적으로 보입니다.
데이터의 의미를 지키고, 상태의 생명주기를 이해하고, 실패를 관찰하고 재현하며, 동료가 안심하고 변경할 수 있는 코드를 만드는 개발자가 되고 싶습니다.
아무튼 저 이제 진짜 iOS 개발자입니다.
6개월 동안 생각보다 많은 것을 했고, 생각보다 많은 사고를 쳤으며, 생각보다 잘 버텼습니다. ㅋㅋ
앞으로도 잘 배우고, 잘 질문하고, 조금 더 신뢰할 수 있는 제품을 만들어 보겠습니다.
잘해보겠습니다. 모두 건강하시고 행복하시길 바랍니다. ㅊㅎㅎ
'KIM CHAN HEE > 생각' 카테고리의 다른 글
| [Fitogether] Global b2b(b2club) (0) | 2026.03.16 |
|---|---|
| 2024년의 회고 그리고, 2025년의 iOS 개발자 찬히히 (0) | 2025.02.07 |
| [Solved.ac] Pro Plan (1) | 2025.02.07 |
| 정보처리기사 합격 후기 (0) | 2025.01.10 |
| 멀티미디어콘텐츠제작전문가 실기 후기 (2) | 2024.11.21 |