신입 개발자로서 6개월을 회고하며
신입 개발자로서 6개월간의 경험과 배운 점을 회고하고, 개발자로서의 마음가짐을 정리한 글입니다.
어느새, 신입으로서 6개월이 지났다. 4월 1일 입사해서 10월까지 정말 빠르게 시간이 흘러갔다… (내 시간은 어디에)
원래 3개월 차에 3개월 개발자의 회고를 작성하려 했으나 시간이 나지 않아 이번 기회에 적는다.
6개월 간 하며 인상 깊었던 일들에 대해 대략적으로 작성하고 회사의 개발자로서 가져가야 하는 마음가짐에 대해 작성하며 글을 마무리하려고 한다.
나의 6개월
헬로우 월드
팀에 합류한 후 4월 둘째 주 즈음부터 시작하여 5월 초까지 헬로우 월드 프로젝트를 진행했다.
우리 팀이 어떤 라이브러리 & 기술 등을 사용하는지, 어떤 문제들을 해결했는지가 요구사항으로 제공되면 내가 구현해서 팀장님에게 확인받는 식이였는데
빠른 속도로 팀 프로젝트에 코드를 작성하기 위한 필요한 기술들과 내가 학습해야 할 것들을 빠르게 알 수 있었다.
처음에는 깔끔한 코드와 객체 지향을 준수하려고 노력했는데 (우테코에서 배운게 그거이다 보니…)
그보다, 기술에 대한 이해와 사용법 및 주의점에 대해 빠르게 학습하는 것이 중요하다는 것을 깨닫고 초점을 맞춰게 되었다.
서버 장애
5월 초부터 이슈를 받고, 팀 프로젝트의 코드를 작성하게 됐다!
프로젝트 코드 리팩토링 관련으로 이슈를 받고 시작했다. 예) 열거형 사용 로직 개선, 로직에 로그 추가 및 코드 개선 등
기존 코드에서 무언가를 수정하고 배포하는 것이 생각보다 무섭더라. (첫 배포 나가고는 변경 영역 부분 및 DB 를 들어가서 계속 확인했다)
그렇게 이슈를 처리하며 6월 초 즈음에 서버 장애가 발생했다. 자세히 설명 못하지만, 문제가 된 코드는 대략 아래와 같았다.
우리 로직은 크레딧이라는 수단이 있으며, 유료 및 무료 사용자마다 제공하는 크레딧의 양이 다르다. 그리고 제공되는 프리셋 마다 크레딧 양이 다르며, 제공 언어(한국어, 일본어, 영어) 마다 크레딧 양이 또 다르다.
- 기존 테이블 데이터로는 크레딧이 어떤 기능인지 알기 어렵다
- 신규 데이터를 추가
- 기존에 사용하지 않는 데이터는 코드에서 정리
이때 클라이언트와의 호환성을 위해 DTO 에서는 기존 칼럼을 유지하고 데이터를 다른 곳에서 채워줘야 한다.
1
2
3
if (entity.getCredit() != null) {
dto.getCredit().setValue(dto.getPresetInfoByLanguage().getKo().getValue());
}
엔티티에서 칼럼이 삭제될 예정이므로, 엔티티가 있다면 DTO 의 요소를 가져와서 채워주는 방식으로 구성했다. 딱봐도 무언가 위태로운 부분이 보이지 않는가…? 🫠
나름대로의 핑계를 대자면, 우리 로직은 백오피스의 비중이 꽤 높다. ( AI 기능이라서, 디버깅 및 측정이 쉽고 파악하기 용이해야 한다. ) 해당 로직은 DTO 가 복잡하게 되어있는 점 + 백오피스에서만 사용한다고 파악해서 한국어의 값을 가져오게 처리했다.
API 로직에서도 같은 DTO 를 사용하고, 해당 API 는 특정 언어의 요소들만 가져와서 DTO 를 반환해줬다. ( 즉, 영어는 영어만 가져오고 한국어는 비어있음 )
그 결과 해외 서버에서는 NPE 가 발생하여 500이 반환되고 장애가 발생했다. 뇌정지가 와있을때, 다른 팀원분이 빠르게 파악해주고 핫픽스 코드를 올리고 배포를 나가서 현상 파악 30분 후 정상화가 됐다.
서버 개발자는 코드를 작성하는 것도 중요하지만, 아래와 같은 능력들을 키우는 것도 매우 중요하다는 것을 느꼈다.
- 호환을 고려하는, 일종의 방어적 코드를 적절히 작성하는 능력 (너무 더럽지 않게)
- 작업을 되돌릴 능력 (핫픽스를 할지, 롤백을 할지 or flyway 배포가 나갔다면, 이를 되돌릴 정합 스크립트 등)
- 자신의 코드 작성이 전파할 범위의 영향
포르투갈어 배포
서비스 확장을 위해 기존 언어가 아닌, 다른 언어를 배포 나가야 하는 일이 생겼다. 그것도 매우 급하게!
9월 8일에 얘기가 나오고 9일날 3시 즈음 이슈를 할당 받았는데 저녁에 요청을 받아 최대한 빨리 처리해줘야 했다.
9일 하루만에 코드를 파악하고 작성해서 PR 을 올리고? -> 10일 날 리뷰 및 머지가 되고 ( +QA ) -> 11일 날 운영 서버 배포가 나갔다.
특히나 인상 깊었던 게 ENUM 의 문제 때문에 데이터 정합성 쿼리랑 코드가 같이 나가면, 배포 전 서버에서 문제를 발생 시키기 때문에 배포를 따로 나가야 했다.
1
2
3
4
5
6
public static EnumValue findByString(String string) {
for (var value : values()) {
if (value.getCode().equals(code)) return value;
}
throw new IllegalStateException("알 수 없는 Enum Value: " + string);
}
(대애충 이런식의 코드)
시간이 부족하고 살짝의 긴장감과 부담이 느껴졌지만 무사히 잘 배포되어 마무리되었다. 🙂
추가로, 급한 코드일수록 더 돌아가야 하는걸 느꼈다.
- 이슈가 해야하는게 뭔지
- 변경되어야 하는 코드가 뭔지
- 어떻게 배포를 검증할지 - 이전 서버에서 문제 없는지(이를 어떻게 테스트 및 검증할지)
이 요소들이 명확하지 않으면 오히려, 빨리 코드를 작성했다고 해도 더 늦게 나가거나, 심지어 더 큰 문제들을 유발할 수 있다. (리뷰에서 병목이 생기거나 배포가 나가면서 병목이 생길 수 있다.)
현재는..?
수습은 끝났지만, 아직까지도 한없이 부족한 거 같다. 여전히 내가 어떤 요구사항이든 수행해야 하거나, 빠른 시간내 기능을 완료할 수 있냐? 하면 아닌거 같다.
다만, 개발자로서가 아닌 회사에서의 개발자로서 모습을 어느정도 찾아가고 되기 위해 노력하는거 같다.
회사의 개발자로서 마음가짐
내가 느낀점들과 매우매우 비슷하게 느낀 내용이 있어서 공유한다. 우테코 선배이신 수달님의 신입개발자의 역량과 성장에 대해서(feat. Done is better than perfect) 3년차 의 내용이지만, 오히려 신입으로서 너무 중요한 내용이다.
코드는 중요하지만 중요하지 않다
우테코를 다닐 때는 객체지향, 불변, 클린 코드, 매개변수 개수 제한 등등등 다양한 제약들이 존재했다. 프로젝트 때도 물론 어느정도 타협은 했지만, 모두가 말벌 아저씨처럼 이상한 코드가 있으면? 리뷰로 질타하려고 했다.
그래서 그럴까, 어느순간 코드를 쉽게 짜는게 오히려 더 불편해졌었다.
코드를 짜면서도 어, 이거 테스트 하기 어려울텐데
, 아, 이거 객체 하나 만들어서 분리하면 더 이쁘겠는데
, 어떻게 코드를 더 깔끔하게 할 수 있지
같은 제약 조건이 걸려있었다.
물론, 선배들 수다 타임이나 먼저 들어간 크루들 얘기를 들으며 코드가 깔끔하거나 아름답지 않다는 것은 알고 있었다.
하지만, 몸에서 거부하는걸 어쩌겠는가.
여기 객체로 바꾸면, 진짜 깔끔할 거 같은데...
, 서비스 코드를 목으로 테스트 할 필요 없이,
객체 내부로 넣으면 될 거 같은데
물론, 우리팀 코드는 정말 장담하지만 상당히 깨끗한 편이라고 생각한다.
처음 이슈를 받을 때, 최대한 코드를 완벽하게 작성하기 위해 시간을 썼다. 객체에 로직을 넣어주고, 테스트를 하게 하고 테스트 코드에서도 assertThat 를 사용해 체이닝 형식으로 가독성 있게 짜는등
BUT… 의도를 놓친게 있었다.
ENUM 에 기본 값을 추가하는 내용이였는데 이 기본값을 통해 요청이 들어올때도 검증을 할 수 있게 + DB 에서도 데이터를 가져올 때 호환이 되게 해야했다.
왜 그런 내용의 이슈가 나오게 되었는지도 하나도 고려하지 않은 것이였다.
그 결과 4월 30일 올린 간단한 이슈가 5월 16일 머지가 되었다.🥲
개발자로서 코드는 당연히 중요하다. 하지만, 그 코드보다 중요한건 문제 해결과 기한인걸 깨달았다. 개발자 역시도 회사의 일원으로 회사의 목표 및 성과에 기여를 해야하므로
팀원들을 배려하자
이슈를 할당받고 코드를 작성하면 PR 을 올리게 된다. 팀 내 코드 스타일도, 코드가 문제가 없는지도 확인을 해야 하기 때문이다.
코드를 잘못 작성했더라도, 머지가 되고 배포가 되면 모두의 잘못이 된다. 그래서 팀원들이 코드를 볼 때 주는 피로를 최소한만 쓰게 해주자.
일단 기본적인 초식으로 분할 정복처럼 커밋을 나누는 것 부터 시작하자.
근데, 커밋을 나누면서 PR 의 내용이 관심사가 여러개라면? (EX: 코드를 구현중, 리팩토링을 해야겠다면? -> 리팩토링과 구현 PR 을 분리)
- PR 을 과감없이 나눠서 단계별로 올리자.
이를 통해
- 코드를 작성한 우리는 작은 범위의 변경이므로 코드에 대한 자신감을 가지게 된다.
- 코드를 보는 팀원들은 드래그 하면서 코드를 쉽게 볼 수 있다.
코드 리뷰는 대부분 Files changed
를 보며 진행된다. 너무 길지도 않게, 여러 패키지를 선회하지 않게, 불필요한게 포함되지 않게 신경 써야 한다.
- 추가로, 커밋 제목과 본문도 깔끔하고 자세하게 작성하자.
당장 리뷰를 할 때가 아니라 미래 이정표가 된다.
코드를 보는데 궁금한 부분이 있는데 커밋에서 파악을 못하면? -> JIRA 이슈 & 위키를 봐야하고, 봐도 파악을 못하면? -> 팀원을 찾아간다. => 팀원이 없다면…? ☠️
이 코드가 왜 수정되었는지, 어떤 이슈를 위해 코드가 처리됐는지, 어떤 부분을 신경 썼는지 를 포함하자.
1
2
ISSUE-473 API 주소 설정값에 추가
- 개발 서버는 TEST 용 계정을 사용하기 때문에, 별도 설정 testUrl 사용
- 그리고, PR 본문 및 Comment 를 통해 살아있는 PR 이 되게 만들어야 한다. 처음
목적
,변경내용
,강조 내용
등등 을 담았으면 일관성을 지키게 해주자.
처음에 작성을 했는데? 리뷰를 받거나 놓친 부분 & 추가한 내용 등등이 있다면 본문을 수정해서 리뷰어들이 혼선을 가지지 않게 해야한다.
추가로, 리뷰를 받고 Approve 를 받았는데 코드를 수정했다면? 슬랙을 통해 코드가 수정된걸 알려주고 + 어디가 추가 및 변경되었는지 간략하게 설명해주자.
질문은 UDP 로
신입으로서 사실 가장 크게 느낀점은 질문하기
였다.
우테코때 미션을 진행하면서도 피드백을 받은 적이 있었다.
다시 한번 Shout out 웨지…
나름대로 질문이라는 것에 대해 소프트스킬을 갖췄다고 생각했는데, 전혀 아니었다.
우테코 때는 온라인으로 이루어지는 점 + 명확한 관계가 있었다면 (나는, 미션을 수행하는 리뷰이 - 상대방은 리뷰를 해주는 리뷰어) 이제는 바로 옆에서 대화를 할 수 있는 오프라인이자, 같이 코드를 완성해나가는 일종의 동료 관계이다.
특히, 코어타임 동안 각자의 할 일을 열심히 하기 때문에 질문은 상당히 중요하다. 가벼운 질문이라도, 슬랙 알림이 울리고 우측 상단에 뜨면 집중이 흐트러진다.
찾아 보기 전 최대한의 노력을 하자. 코드, 지라, 위키 등등등 그럼에도 안되겠다면? 일단 자기가 생각나는건 다 시도해보자. 마지막으로, 물어보자…
- 왜 질문하게 됐는지
- 어디가 막히는거 같은지 & 모르는거 같은지 ( 대답해줘야 하는게 뭔지 )
- 내가 시도해본 것들은 무엇인지
추가로, 혹시, 저 이거 모르는거 같은데 물어봐도 괜찮나요...?
는 절대 하지말자. 어차피 TCP 처럼 질문이 오가게 될 텐데 처음부터 그러지 말자.
말로 할 때는 더욱 간결하게 해야 한다. 무턱대고 찾아가는게 아니라 자기가 질문해야 하는 내용에 대해 완벽히 이해하고 찾아가자. 아니면, 상대방 앞에서 어 잠깐만요..
나 이 부분 확인해봐야 할 거 같은데요?
라고 말하게 된다.
질문하는게 나쁜건 아니다. 오히려, 못 물어보고 계속 시간을 딜레이 시키는 것 보다야 좋다. 하지만, 가치가 있게 통신이 오가야 한다.
다시 이런 질문을 하지 않게 개인 문서에 정리하거나, 위키에 공유하는 것도 중요하다.
정답을 찾아라
프로그래밍의 가장 재밌는 점이자, 고통스러운 점은 정답이 없다는 것이다. 어떻게든 돌아가는 코드를 만들 수 있는 브루트 포스 방식이 있지만, DFS & BFS & DP 를 통해 더욱 효율적으로 코드를 짤 수 있는 것 처럼 우리의 코드들 역시도 매우 다양한 방식으로 해결이 가능하다.
데이터 정합을 맞추기 위해 작업을 해야 한다고 해보자. 우리는 다양한 선택지를 시도할 수 있을 것이다.
- 하나의 SQL 파일로 처리
- 쉘 스크립트로 작성 + SQL 파일로 계속 반복할 수 있게 처리
- 기존 스프링 코드에 임시 패키지를 만들어 JPA + Spring 으로 코드 작성
- 스프링 배치 의존성을 추가하고 코드 작성
또는, 어떤 부분에서 캐싱 처리를 할지, 어떤 데이터를 캐싱 할지 or 어떤 데이터를 저장해 중복을 방지 할지 등등등 끝없이 고민하게 된다.
개인적으로 느낀점은, 최대한 단순하게 슈도 코드에 비슷하게 완성을 시켜보자. 이 내용은 위 코드는 중요하지만 중요하지 않다.
와 유사한데, 완성을 시켜봐야 코드의 가닥을 잡는다.
이건, 이렇게 하면 안되겠는데...?
, 다른 방법으로 해야만 하겠다
등등
특히나 요새 AI 들이 filesystem 기반으로 컨텍스트를 파악해 테스트 코드를 케이스에 맞게 매우 잘 작성해준다. 자신이 짠 코드에 테스트 코드를 받고 -> 그 테스트 코드를 통해 부담없이 코드를 수정 및 개선해나갈 수 있다.
정답이란 건 존재하지 않지만, 자신이 근거를 가지고 얘기할 수 있는 정답을 만들어나가자. 왜 이렇게 해야만 했는지, 어떤걸 생각했는지, 어떤 접근을 했는지
자신도 성장하고, 팀의 코드도 더욱 견고하게 할테니
로그
우테코 프로젝트를 할 때는 로그가 어디에 작성되어야 하는지, 왜 필요한지를 도무지 깨닫지 못했었다. 그때 당시 코치 브리에게 찾아가서도 "아직 로그의 의의를 잘 모르겠어요"
라고 질문했었다.
회사에서 코드를 짜며 로그는 일종의 최후의 보루인걸 느꼈다.
예를 들어
- 어떤 요청이 들어왔는데 분명히 성공 된 거 같은데? DB 에는 제대로 데이터가 안되어있다던가
- 어떤 사용자의 요청이 계속해서 500 을 반환하는데? 파악을 할 수 없던가
- 코드를 수정했는데? 실수를 해서 저장해야 될 정보가 누락되었다면?
처음에는 요청 및 응답 본문 전체를 로그로 남기는게 필요한가..? 라고 생각했는데 용량 및 부하가 괜찮다면? 비즈니스 중 중요한 부분이라면 로그로도 남기는게 나쁜지 않은거 같다. (물론, 보안 및 ISMS-P 등은 적절히 고려) 언제든 추가로 사용할 수도 + 실수도 캐치할 수 있게 ( 이전 호환성을 깨진 코드가 나가더라도 어떻게든 파싱해서 작업을 한다던가 )
일반적인 로그의 길이가 249B
정도 한다. (이건 당연히 프로젝트나 내용마다 다를테니 확인해야 할 것) 분당 152KB 정도 한다면 152 / 1024 * 1024
* 0.76
= 0.0011$(2원) 정도 된다.
그리고, 로그를 통해 특정 요청들이 잘 처리되고 있었는지 추적을 할 수 있게 도와준다. 이미지 생성이라면
요청 수신 -> 프롬프트 검사 -> 번역 -> 메시지 발행 -> 메시지 수신 -> 생성 -> 보고 등등등 차례대로 로그를 남기면 어디가 문제 발생한지 바로 파악이 용이하다. (에러 로그도 적절히 + 정확히 남길것)
추가로, 이미지나 파일 등도 오류가 발생한다면 우리 S3에 별도 업로드해서 디버깅을 할 수 있도록 하자. 물론, 사용하지 않는 파일이 될 수도 있고, 용량도 차지하고, 비용도 나가겠지만?
10월1일 기준, GB 당 0.021(30원) 이다. 파일 하나의 크기가 대략 4MB 이니까
1GB / 4MB = 250 0.021 / 250 = 0.000084$
정도의 비용이 발생한다. 무턱대도 낭비를 하는건 안되지만, 우리가 현상 파악 및 재현을 하기 위해 필요한 요소들에 대해선 아끼지말고 투자하자.
앞으로라
다음에는 1년차 개발자 회고로 돌아오지 않을까..?
그때까지, 더욱 팀원들에게 인정받는 & 경험을 쌓는 개발자가 되고 싶다. 아직까지도 부족함을 많이 느낀다.
추가로, 요새 AI 의 발전을 몹시 빠르게나마 느낀다. 그럼에도 아직은 한계점이 존재하는거 같다는 생각이 든다.
GeekNews 만 봐도 AI 에 대해 부정적인 의견들 역시 강렬히 존재한다.
나름대로 나의 생각은
작성해준 코드의 책임을 지는건 우리다 아직 100% 완벽히 신뢰할 수 없으므로, 그 코드는 결국 검수를 거치게 된다. 오히려, 개발자의 생각을 제한하고 시야를 좁게 만들뿐더러 시간을 낭비 시키게 만든다.
200% 컨텍스트를 이해하지 못한다 사실, 단순 코드 데이터 컨텍스트 만으론 해결할 수 없는 무언가가 존재한다. 이슈가 왜 나왔는지, 궁극적으로 어떤걸 해결해야 하는지 등등 아무리 우리가 Jira MCP 를 붙이고, Wiki MCP 를 붙이고 하더라도 사람의 생각을 넣지 않는 한 정답을 도출하지 못한다.
AI 를 위한 튜닝이 무슨 의미인가 이렇게 말해도, AI 에 꽤나 관심이 많다. MCP 나, 어떤 기술들이 추가가 되가는지, 오픈 소스 모델로 어떤게 나오는지 등등 SuperClaude, SuperGemini 같은 AI 의 두뇌를 업그레이드 해주는 프레임워크 들도 있고 순차 생각, 컨텍스트 캐싱 등등 MCP 들도 다양하다. 근데 이 모든게 무슨 의미일까. 우리가 코드를 짜야 의미가 있는거지, 주객전도가 되는걸 느꼈다.
오히려 나는 AI 를 통해 사이드 이펙트 생산성을 높였다는게 맞다고 생각한다. 그렇기에, 아마 다음 글은 AI 로 생산성을 어떻게 향상시키는지
에 대해 다룰 예정이다.
이상!