Daily/About Jyami

2022년 회고 | 2022 Year in Review

한게 없는데 올려도 될까 회고... 1월 내내 생각 날 때마다 정리하고있는데 하핫 미루고 미루다보니 2월이네..?시간 너무 빨리간다. 회사 다니고 나서부터 3년이 1년처럼 흐르는 느낌이랄까 22년은 사실 개발자로써의 성장보단 운동으로 건강찾다가 재미를 붙여버린 한해였어서 개발 얘기 거의 없는 일기장 회고이다. 자자 시작해보자!! 개발자 쟈미올해는 외부 스터디나 서브프로젝트 없이 회사 생활에만 집중했었다. 아무래도 그만큼 흥미로운 일을 하고있어서 회사 코드와 구조 그리고 일에 애정이 생기기 때문이 아닌가 싶다. 카카오지금 부서인 카카오 톡메시징파트에서 일을 하다보면, 이제 3년을 향해가고 있음에도 몰랐던 도메인지식이 나온다. 카카오톡 채팅이라는 매우 큰 서비스와 기능이 많은 서비스를 운영 개발하고있어서 그..

2022년 회고 | 2022 Year in Review

728x90

한게 없는데 올려도 될까 회고... 1월 내내 생각 날 때마다 정리하고있는데 하핫 미루고 미루다보니 2월이네..?시간 너무 빨리간다. 회사 다니고 나서부터 3년이 1년처럼 흐르는 느낌이랄까 

22년은 사실 개발자로써의 성장보단 운동으로 건강찾다가 재미를 붙여버린 한해였어서 개발 얘기 거의 없는 일기장 회고이다.
자자 시작해보자!!

 

개발자 쟈미

올해는 외부 스터디나 서브프로젝트 없이 회사 생활에만 집중했었다. 아무래도 그만큼 흥미로운 일을 하고있어서 회사 코드와 구조 그리고 일에 애정이 생기기 때문이 아닌가 싶다.

 

카카오

지금 부서인 카카오 톡메시징파트에서 일을 하다보면, 이제 3년을 향해가고 있음에도 몰랐던 도메인지식이 나온다. 카카오톡 채팅이라는 매우 큰 서비스와 기능이 많은 서비스를 운영 개발하고있어서 그런거겠지. 도메인적으로 모를때도 스스로 놀라면서 환기가 되기도하고, 사실 기술스택도 다양하고 장애양상이나 그 문제를 해결하는 양상도 다양하여 매울점이 굉장히 많은 조직에 속해있다고 자부심을 느낌다.

22년도에 회사일을 하면서 아무래도 기억에 남는 것들이 몇 개가 있다.

 

1. 회사 유튜브 출연

작년에는 회사 블로그에 내 글을 썼던걸 회고에 적었었는데, 올해는 유튜브 컨텐츠에 출연을 했다. 개발자로써 훌륭해서라기보단 우리 파트에서 가장 외향적이고, 이런 컨텐츠를 찍으면 내 회사 생활이 재밌을 것 같다고 생각해서 자원했다. 

https://www.youtube.com/watch?v=9SU1jBYZ14o 

https://www.youtube.com/watch?v=J9KsjiQs604 

예능 컨텐츠 하나, 인터뷰 컨텐츠 하나해서 두개를 찍었는데 아무래도 기억에 남는건 팀채팅 인터뷰 컨텐츠이다. 파트내에서 팀채팅 서버도 관리하고 있고 팀채팅에 대한 부분도 가끔 유지보수를 하고있는데, 이 좋은 서비스를 많이들 모르는 것 같아 아쉬웠다. 그래서 이전에 내 유튜브에도 올린 팀채팅 활용법에 대한 내용을 영상에 담았다.

그리고 겸사겸사 톡 메시징파트의 롤을 설명하는 내용도 인터뷰에 남겼는데, 덕분에 이 짤을 생성하였지 후후

 

2. 카카오 해커톤

대학생때 취준을 할 때부터 IT 기업에 가면 임직원 해커톤이 있다는 얘기를 듣고 한번은 꼭 해보고 싶다고 생각했다. 그동안은 코로나로 안열렸었는데, 22년부터 조금 완화가 되고 슬슬 개발자 관련 행사들이 많이 나왔었다. 그래서 참가한 카카오 해커톤 22K 꽤나 재밌었다. 해커톤 영상에도 내가 나온다ㅋㅋ https://youtu.be/j-nXQwSY98o?t=560

우리 팀 빌딩은 모두 카카오톡을 개발하는 크루들이었고, 톡디자인 케이, 톡 안드로이드 피터와 이안, 톡 메시징인 나 이렇게 넷이서 참가하였다. 사내 코드를 써도 되기 때문에 카카오톡 오픈채팅을 변경한 서비스를 만들었고, 지난 코로나 시대에 오픈채팅 팬미팅, 오픈채팅 콘서트가 종종 이루어진 것을 봤었어서. 팬미팅에 사용할 수 있도록 팬덤색이나 팬덤 로고들을 좀더 커스텀해서 팬들과 스타가 소통할 수 있는 채팅기능을 개발하였다. 시연영상은 내 유튜브에 비공개로 저장해뒀다ㅎㅎ 나중에 보면 매우 추억일 것 같은 느낌!

 

3. 제주도 출장

22년에 제주도만 3번을 다녀왔었는데, 그중 2번이 회사관련 출장이었다. 한번은 태경이 수영이랑 같이 제주도 여행을 다녀왔었고,
한번은 if-kakao 컨퍼런스 준비단 워크샵, 그리고 아래 vlog찍을 때 갔던건 포팅과제 집중근무를 위한 제주 출장이었다. 일도 하면서 좋은경치 맛있는 음식 잔뜩먹으면서 제주도 혼자 여행을 다녀오다보니 당시에 리프레쉬도 되었고, 22년도 기억에 남는 일중 하나였다. 본사가 제주에 있는 회사에 다니니 워크샵 제주 힐링그자체!! 

vlog에서도 언급을 했었지만 당시에 만난 케빈과 조엘이 엄청 인상적이었다. 두분은 같은 학교 동문, 그리고 당시에 두분 다 유관 부서로 한달 제주도 워케이션을 하신다고해서 한번 만남을 가졌었다. 생활패턴과 개발철학이 비슷해서 마음이 맞는친구와 한달동안 알차게 여행 겸 근무를 할 수 있는 사람이 있다는게 정말 부러웠다. 나두 23년에 조엘이랑 떠나는 스위스 여행 매우 기대중 ㅎㅅㅎ

https://www.youtube.com/watch?v=X0YzYGM7JDw 

 

4. 그리고 개발

올해는 리팩토링 업무, 그리고 기존 레거시 포팅작업이 나의 주된 과제였었는데, 그 와중에도 유저가 직접 사용하는 기능 개발에도 참여하곤했었다. 너무 내부과제에만 치중하다보니 스스로 번아웃이 오고 개발로 좀 재미를 찾고 싶었기 때문에 실제 유저가 사용할 수 있는 기능 개발을 하고싶다고 생각을 했었다.

그렇게 했던 과제가 추모 프로필이었는데 하필이면 12월 가장 바쁠 시기에 내가 여행을 일주일 다녀오는 바람에 같이 일을 했던 빈스에게 매우 죄송했다. 그래도 전후로 나름 열심히 팔로우 했던 프로젝트! 사실 서버 공수가 많지는 않았지만 23년 1월에 오픈되고 유저들의 반응이 너무 좋아서 뿌듯했다. 덕분에 사용자와 밀접한 서비스를 만들게되면 또 다른 멋진 기능을 개발, 혹은 기존 기능들을 개선 할 수 있도록 힘을 낼 수 있는 계기가 되어 개발자로 자부심있게 살 수 있게 되는 것 같다.

https://cs.kakao.com/helps?service=8&category=226&device=1&locale=ko&articleId=1073205009&controllerName=help&actionName=mobileviewpage&accountLoginUrl=https%3A%2F%2Faccounts.kakao.com%2F&without_layout=false 

 

고객센터

카카오 고객센터를 통해 각 서비스 도움말을 확인해보세요.

cs.kakao.com

 

 

5. 판교 IDC 장애 대응 / 월드컵 대응 / 신년 대응

4분기 휘몰아쳤다. 각종 대응으로 유독 새벽에 작업을 할 일이 많았었다. 

판교 장애 대응은 앞으로 개발자로 계속 산다고 해도 이정도 규모의 장애를 대응해볼 일이 있을까 싶을정도로 기억에서 안잊혀질 것 같다. 토요일 3시부터 시작해서 일요일 오전 7시까지 쉼없이 대응하고 2시간 자서 다시 일어난다음 일요일 9시부터 00시까지 일하고.. 그러고 월요일도 9시 출근해서 00시까지 일하고.. 어떻게든 빠르게 복구해야한다는 생각밖에 안들었던 당시였다. 내가 자는시간만큼 내 주변인들이 서비스를 사용하지 못한다고 생각하니, 진짜 아드레날린이 너무 몰아쳐서 심장이 계속 두근거리고 잠을 못자는 상황이었다. 그래도 물리적장애를 소프트웨어적으로 빠르게 해결하려고 대응책을 세우고 실제로 하나하나 대응되는 대로 서비스가 살아나는 것을 보면서 재밌기도했고 개발자로써 희열을 엄청 느꼈던 사건이었다.

월드컵 트래픽으로 신년 트래픽으로 혹시나 서버에 이상이 있을까 뒤에서 모니터링을 했었다. 우리 파트에 있으면 사용자의 패턴에 따라 내 서비스의 트래픽이 오르고 내리는 것을 볼 때 정말 신기함을 느낀다. 실제 대한민국 대부분 국민들의 서비스 사용성을 직접 데이터로 볼 수 있다는 점에서 항상 많은 인사이트를 얻고 그에 따른 대응 로직을 준비하고 대비하면서 많은 배움을 얻는다. 첫 직장 첫 부서가 대규모 트래픽을 감당하기 위해 많은 것을 고려해야하는 파트라는 점에 항상 감사함을 느낀다.

 

개발자 외부 활동

1. 블로그

22년 방문자수

월간 방문수 약 13000명대를 유지하고있다. 사실 글도 잘 안쓰는데.. 이전에 스프링 기본기에 대해 정리해뒀던 문서나 회고 글들이 인기가 많아서 꾸준히 유입이 있다. 23년에는 블로그에 글을 많이 쓸랑가

 

2. 유튜브

https://www.youtube.com/@developer-jyami

 

개발자 쟈미

🌱개발자 쟈미의 일상 기록🌱 클라이밍하는 개발쟈미

www.youtube.com

구독자가 3400명이 되었다. 22년에는 광고영상 1개, 카톡팁 영상 1개, 제주 vlog 영상 1개.. 하핫 올리고 싶을 때 취미로 하는 유튜브라서그런지 꾸준히 하지 못해서 구독자가 확실히 크게 우상향하지는 않는다.

그래도 가끔 회사에 신입사원분들이 들어오실 때 블로그나 유튜브와 같이 열심히 살던 과거의 영광들을 봐주시고 감사하게도 좋게봐주셔서 알아봐주시는 분들이 계시다. 그런만큼 열심히 살아야 하는데..ㅠㅠ 22년에는 아무래도 개발자로서의 성장보다 다른데 좀더 집중해서 살다보니 블로그도 유튜브도 업로드가 많이 이루어지지 않았었다.

3. 세미나

외부 컨퍼런스에 잘 나가는 편은 아니지만 지속적으로 대학교 선후배들과의 네트워크는 하려고 학교 행사에는 많이 참여하려고 하는 편이다. 22년에는 총 3번의 세미나를 진행했었는데, 아무래도 전부 취준을 앞둔 대학생 대상이다보니 커리어에 대한 이야기를 많이 했다.

  • 1월 GDSC EWHA 선배초청 세미나 : 서버개발자가 아키텍처 확장해 나가는 플로우
  • 11월 이화여대 컴퓨터공학과 클라우드 데이 : 개발자는 어떻게 공부해야할까
  • 11월 GDSC EWHA 홈커밍 데이 : 서버개발자에게 궁금한 점 QnA

발표를 준비하면서 아무래도 내가 개발을 어떻게 공부를 했었고, 앞으로는 어떻게 공부를 해야겠다는 생각을 정리할 수 있었다. 그래서 다들기술 발표를 하고 멘토링을 하라는 이유가 스스로도 되짚어볼 수 있게되기 때문인가보다. 개발자는 어떻게 공부해야할까? 라는 점에 대해서 아키텍처가 점점 확장되면서 요구사항에 따라 그때그때 공부를 확장해가면서 해야한다는 이야기를 했었다. 면접에서 cs를 본다고해서 그것을 주먹구구로 외우는 방식보다는 직접 서비스나 프로젝트를 하면서 그에 따른 지식을 익혔던 것이 기억에 많이 남는다는 것이 주된 주제였다. 다행히도 많은 후배분들이 질문도 많이 해주시고 연락도 많이 해주셔서 뿌듯함과 그들의 열정을 느끼는 일정이었던게 기억에 남는다.

 

4. 인터뷰

https://korea.googleblog.com/2022/10/GDSC-job-fair-2022.html

 

Google Developer Student Clubs와 함께 취업에 도전하는 개발자가 되어보세요!

GDSC(Google Developer Student Clubs)는 구글 기술에 관심이 있는 학생들을 위한 대학 기반 커뮤니티 그룹으로, 현재 전 세계 110개 이상의 국가 약 1,800개 대학에서 활동하고 있습니다. 대학생들이 함께 A..

korea.googleblog.com

GDSC에서 요청이 와서 서면 인터뷰를 했었다. 사실 취준기에 대해서 이 블로그를 통해 유명해지긴 했으나,, 어느새 직장을 다닌지 만으로 3년차이기에 너무 라떼는 얘기가 아닐지 걱정이된다. 운동을 하고있는 지금 입장에서는 과거에 운동도안하고 무작정 밤샘을 하던 나의 모습이 좋지 않다는 걸 특히나 더 실감하고 있어서 더 그렇다.

 

5. 스터디?

주된 관심사가 아무래도 운동이었어서 개발 공부를 해야한다는 생각은 한켠에만 있고 그러다보니 옛날만큼 퇴근 후 공부를 많이 하진 않았다. 3월부터 6월까지는 자바봄이랑 effective kotlin 책으로 코틀린 스터디를 했었다.

effective java만큼 인사이트를 주지 않을까 하여 사실 많이 기대했던 책인데 아직은 코틀린이 자바만큼 안티패턴이나, 주의해야할 점 등 사례가 많이 쌓이진 않았어서 effective java만큼 충격적으로 다가오진 않았다. 아직도 내 최고의 명서는 effective java... 오히려 코틀린은 kotlin in action 이 좀더 실용적이고 내용이 알찬게 좀 더 마음에 들었다.

마찬가지로 자바봄이랑 이펙티브 코틀린을 진행할 때 github 코드 정리와 블로그 정리를 동시에 했었는데 관련 링크는 아래에 있다

직장을 다니면서 내가 원하는 깊이로 마음맞는 사람들과 스터디를 하는게 쉽지 않다는걸 깨닫게되었다. 대학교에 다닐때 자바봄을 만난건 매우 행운이었구나 생각이 들었다. 고로 앞으로 공부를 한다면 스스로 흥미를 찾아서 꾸준히 해야할텐데 쉽지않다ㅠ 사회에는 재밌는게 너무 많다! 앞으로의 공부방법에 대해서는 항상 고민으로 두고 찾아가야 할 것 같다.

 

운동인 쟈미

사실 본론은 여기일지도 위에는 그래도 양심상 제목이 devlog니까 개발자를 위로 올렸는데, 22년의 진짜 본모습은 운동인이었다ㅋㅋㅋ 21년에 시작한 운동이 생각보다 재밌었고, 22년 2월부터 클라이밍에 빠지게 되면서 꾸준히 운동을하고있는데, 운동하나를 시작하니 다른 운동도 곧잘해서 이것저것 많이 시도하고 도전했었던 한해였다.

1. 클라이밍

2월부터 꾸준히 하고있는 운동이다. 사실 진짜 운동하는 느낌은 웨이트가 그렇고, 클라이밍은 운동이지만 승부욕이 많이 생겨서 게임하는 느낌이긴 하다. 꾸준히 했더니 처음보다 실력이 많이늘었고, 클라이밍으로 새로운 사람들을 많이 만나면서 22년을 덕분에 즐겁게 보낼 수 있었다. 

22년 클라이밍 달력

위에 달력 보면 진짜 많이도 했다 싶다..ㅋㅋㅋㅋ 암장리스트도 싹 정리하니 많이도 다녔다..ㅎㅎ

클라이밍안에도 많은 종류가 있는데 이것저것 해보기를 좋아해서 그런지 실내볼더링 인공암벽리드 자연볼더링 자연리드 가릴 것 없이 많이 했다. 클라이밍을위해 먼 지역에 여행을 가기도 하면서 참 많이 놀러다녔다. 클라이밍이 너무 해보고싶어서 언더독 클라임에 무작정 일일강습을 신청했고, 진짜 재밌었다. 그래서 이후에 혼자 암장을 가서 사람들이랑 친해지기도하고, 그렇게 친해진 사람들의 친구들을 소개받으면서 같이 클라이밍을 하고 다니면서 다양한 곳을 다니게 되었다.

3월에서 4월까지는 모란 클라임어스에서 기초반 강습을 들었었고, 그 이후에 한 5월쯤인가 부터 지금까지 계속 더클라임 회원권을 연장해서 실내 볼더링을 하고있다. 처음에 더클라임 초록도 쩔쩔맸었는데, 어느새 갈 때마다 빨강을 한두개씩 깨게 되고 22년 마지막에 보라색도 하나 했다!! 9월쯤 헬스랑 함께 클라이밍을 했을 때까지 실력이 엄청 빠르게 늘어서 매번 재밌었는데, 사실 22년 끝물에 연말이라고 술을 너무 많이 먹었더니 근손실이 왔는지 조금 정체했다..ㅎㅎ 23년에는 헬스도 클라이밍도 꾸준히 하면서 좀 더 잘해지고싶다!

무엇이든 신기한 클린이는 상반기에는 서울 근처 암장투어를 정말 많이 다녔었고, 결국엔 클라이밍을 위한 여행도 많이 가게 되었다. 부산, 속초, 대전, 제주, 양양, 진안 심지어 태국까지 어느 여행지를 가게되도 클라이밍을 연상하는 클친자가 되어가는 중이다. 하반기에는 더클라임 회원권을 끊게되면서 이곳저곳 원정을 안가게 되었고, 실내가 아닌 실외에 관심을 갖게되었다.

9월에 가을이 되면서 날씨가 좋아지고,, 날씨가 좋아지니 실내보다는 밖을 나가고 싶어서 결국 리드를 시작하게 되었다. 근처 주민인 소나언니한테 리드를 배워서  결국 리드 클라이밍을 꾸준히 하고있는 돌무리 크루에 들어오게 되었다. 가을에 이쁜 하늘을 보면서 클라이밍을 하고싶어서 배운 리드를 인공암벽에서 시작해서 결국 실제 자연바위에서도 리드를 하게 되었고, 태국 끄라비까지 가게 되었다. 끄라비 자연리드는 아무래도 22년에 가장 기억에 남는 이벤트였었고, 같이간 우리 돌무리 언니오빠들이랑 하나도 안싸우고 서로서로 챙기면서 8박9일 클라이밍 겸 태국여행을 무사히 다녀올 수 있어서 감사했다. 

외에도 더클라임에서 진행하는 걸스온탑, 클라임어스에서 진행하는 볼더링 파티도 참가해보면서 한정된 시간안에 많은 문제 혹은 고득점 문제를 풀어야하는 긴장감도 경험해볼 수 있었다. 사실 이런 이벤트를 할 때마다 내가 좀더 강했다면하고 그레이드를 많이 낮춰서 나가게 되는데, 그래도 1년안에 이정도면 꽤 잘하는거니까!!! 23년에도 다양한 이벤트를 많이 나가보는걸로 하자

재밌겠다는 생각 하나로 시작한 취미로 다양한 직군의 사람들을 만날수 있게되었고, 취미를 위해 여행을 떠나는 삶을 내가 살고있을거라고는 생각도 못했었다. 사실 올 한해 클라이밍과 운동에 푹 빠져있어서 덕분에 퇴근하고 개발공부보단 운동을 하러가는 일상이 반복되었지만 , 그만큼 많이 건강해진 패턴을 가지게되어서 다행이라고 생각한다. 22년에는 운동에만 미쳐있었다면 23년에는 그래도 현생도 조금은 챙기면서 운동을 하고 싶다.


볼더링 (실내 28 + 자연 2)

  • 언더독 클라이밍 (수원)
  • 더클라임 (양재 + 강남 + 신림 + 서울대 + 마곡 + 홍대 + 연남 + 일산)
  • 클라임어스 (모란)
  • 피커스클라이밍 (종로)
  • 서울숲클라이밍 (서울숲)
  • 클라이밍파크 (종로 + 신논현 + 한티)
  • 에픽클라임 (영통)
  • 닷클라이밍 (송파)
  • 볼더메이트 (기흥)
  • 락트리 (분당)
  • 비블럭 클라이밍 (언주 + 송도)
  • 알레 클라이밍 (혜화)
  • 손상원 클라이밍짐 (강남)
  • 원정 : 아임낫볼더 (속초)
  • 원정 : 웨이브락 (광안리, 서면)
  • 원정 : 픽스볼더 (제주)
  • 원정 : 베이스캠프 (대전)
  • 자연바위 : 양양 죽도암
  • 자연바위 : 진안 운일암반일암

리드 (인공암벽 4 + 자연 2)

  • 판교 공원
  • 뚝섬 한강 공원
  • 영등포 스포츠 클라이밍 경기장
  • 광교 스포츠 클라이밍장
  • 자연리드 : 조비산
  • 자연리드 : 끄라비 (태국)

이벤트

  • 피커스 볼빼페 (볼더링 빼고 페스티벌)
  • 더클라임 걸스온탑
  • 더클라임 강남점 오픈페스티벌
  • 모란 볼더링 파티

 

2. 헬스

그래서 3대몇? 스쿼트가 잘 기억이 안나는데 S : 55kg / B : 32.5kg / D : 75KG = 3대 162.5kg 이다.
요즘엔 헬스를 잘 안해서 3대 운동을 잘해서 아마 더 많이 내려갔을 텐데ㅠㅠ 1월부터 10월까지 꾸준히 PT를 했을때 기록이었다. PT를 22년에 꽤 많이 받았더니 돈도 많이 들고, 사실 기구 사용법이나 자극도 왠만해서는 혼자도 할 수 있는 정도가 되어 11월부터는 PT없이 혼자서 하고있다. PT거의 마지막 즈음에는 내가 고립운동을 재미없어하는걸 쌤이 느끼셨는지 크로스핏이나 역도 동작도 시켜보고ㅋㅋ 또 곧잘하니까 선생님도 재밌어하고 했었다ㅋㅋ 운동에 한번 흥미를 느끼니 "고립운동"이라서 하는게 아니라 그냥 운동이면 무엇이든지 일단 도전해보게 되었다.

22년 1월 인바디와 22년 9월 인바디 차이이다. 12월에 했어야했는데 생각을 못했다ㅠㅠ 식단없이 평소대로 식습관을 하면서 오로지 운동만으로만 이루어낸 결과이다. 목표로 운동을 한것은 아니었지만 몸 라인이 달라지고 데이터로도 나아지는 것을 보면서 보람을 느꼈고, 몸도 이전보다 많이 건강해졌다는걸 느끼고있다. 생활속에서도 옛날에는 무거운 물건을 옮기는걸 굉장히 부담스러워했는데, 어느순간 혼자서도 척척 잘 옮길 수 있게 되서 나름 삶의질도 높아졌다.

지금은 클라이밍을 주운동으로해서 헬스를 많이 하고있지는 않지만, 그래도 클라이밍과 반대되는 근육 발달을 위해 일주일에 한번이라도 헬스장을 가고있긴하다. 외에도 너무 몸이 무거울 때 유산소를 가볍게 하면 기분도 나아지고 좀 가벼워지는 기분이 든다. 하지만 앞으로 헬스를 주운동으로 하지는 않을 것 같다. 고로 3대측정도 계속 낮아지겠지.. 적당한 건강유지 정도를 위해 할 예정이다.

 

3. 일회성 운동 체험

클라이밍과 헬스로 점점 운동에 재미를 붙이다보니 사실 일회성으로도 여러 운동에 도전해보는걸 주저하지 않게되었다. 인생에서 처음 스키장에 가서 스키를 타보기도하고, 프리다이빙 체험을 하려다가 자격증 코스 수업을 듣기도했다 (근데 성격이 급해서 그런가.. 나랑은 잘 안맞아서 그만뒀다). 클라이밍의 다이나믹 무브를 잘하고싶어서 언더커버에 파쿠르 체험을 가서 파쿠르 코치님들이랑 친해지기도했다. 유산소를 진짜 싫어해서 절대 안할줄 알았던 러닝도 생각보다 처음하는 것 치고 기록이 잘나와서 꽤 흥미로웠다. (5km 6분 11초)

코딩에서 하나의 언어를 잘 알면 다른 언어를 배울 때 좀더 수월하게 배우는 것처럼 운동도 비슷한 느낌이 들었다. 어느정도 헬스와 클라이밍으로 상체와 하체 근육이 받쳐주다보니 다른 운동도 처음시작하는 것 치고 곧잘하는 느낌이 들어 빠르게 흥미를 붙일 수 있게 될 것 같다. 다만 그래도 아직은 클라이밍이 너무 재밌다..ㅎㅎ

 

그래서 23년에는..

글의 분위기에서도 느껴졌겠지만 개발 얘기할 때는 조금은 차분하게 운동얘기할 때는 매우 활기차게 글을 썼다ㅋㅋㅋ. 그런만큼 22년에는 개발자로서의 성장보다는 운동으로 건강돌리기와 재미찾기가 우선인 한 해 였다. 하지만 언제까지 재미만 찾아다닐 순 없겠지ㅠ 그래서 어떻게 하면 개발 공부를 좀 더 재밌게 할 수 있을까 고민중이다. 시니어 개발자분들중에 한분은 본인의 취미를 개발과 접목시키면 결국 관심사라서 공부를 하게 된다고 하셨었다. 그래서 퇴근하고 사이드프로젝트로 내가 쓰고싶은 클라이밍 관련 서비스를 만들어 볼까 생각도 해보고있다. 22년은 근육만 성장했다면, 23년은 근성장, 개발자로서의 성장 둘다 잡는 멋진 한 해를 만들어보자!! 화이팅!

I don't even have much to show for it, but is it okay to post a year-end retrospective... I've been jotting things down whenever they come to mind throughout January, but haha I kept putting it off and now it's February..? Time flies so fast. Ever since I started working, it feels like 3 years go by like 1 year 

2022 was honestly a year where I found fun in working out and getting healthy rather than growing as a developer, so this is more of a diary-style retrospective with barely any dev talk.
Alright, let's get started!!

 

Developer Jyami

This year, I focused solely on work life without any external study groups or side projects. I think it's because the work I'm doing is interesting enough that I've grown attached to the company's code, architecture, and the work itself.

 

Kakao

Working in my current department, the KakaoTalk Messaging Part, even as I'm approaching my 3rd year, I still come across domain knowledge I didn't know about. I guess that's because we're operating and developing KakaoTalk Chat — a massive service with tons of features. When I encounter something I didn't know domain-wise, I surprise myself and it's a nice wake-up call. The tech stack is diverse, the types of incidents and how we resolve them vary widely too, so I feel proud to be part of an organization where there's so much to learn.

There are a few things from work in 2022 that really stick out in my memory.

 

1. Appearing on the Company YouTube

Last year I wrote about publishing a post on the company blog in my retrospective, and this year I appeared in YouTube content. It wasn't because I'm an outstanding developer — I'm just the most extroverted person on our team, and I volunteered because I thought filming this kind of content would make my work life more fun. 

https://www.youtube.com/watch?v=9SU1jBYZ14o 

https://www.youtube.com/watch?v=J9KsjiQs604 

We filmed two videos — one entertainment piece and one interview piece — and the one that stands out most is the Team Chat interview content. Our part manages the Team Chat server and occasionally does maintenance on it, and I always thought it was a shame that not many people knew about this great service. So I included tips on how to use Team Chat, which I had also previously uploaded on my own YouTube channel.

While I was at it, I also explained the role of the Talk Messaging Part in the interview, and thanks to that, I got this meme-worthy screenshot hehe

 

2. Kakao Hackathon

Ever since my college days when I was job hunting, I'd heard that IT companies have employee hackathons, and I always wanted to try one. They hadn't been held due to COVID, but starting in 2022, restrictions eased up and a lot of developer events started popping up. So I participated in the Kakao Hackathon 22K, and it was pretty fun. I even appear in the hackathon video lol https://youtu.be/j-nXQwSY98o?t=560

Our team was made up entirely of crew members who develop KakaoTalk — Kay from Talk Design, Peter and Ian from Talk Android, and me from Talk Messaging, four of us total. Since we were allowed to use internal code, we built a modified version of KakaoTalk Open Chat. During COVID, I'd seen fan meetings and concerts held through Open Chat, so we developed a chat feature that let fans and stars communicate with more customized fandom colors and logos for fan meetings. I saved the demo video as unlisted on my YouTube hehe — I feel like it'll be a great memory to look back on later!

 

3. Jeju Island Business Trip

I went to Jeju Island 3 times in 2022, and 2 of those were work-related trips. Once I went on a personal trip with Taekyung and Suyoung,
once was a workshop for the if-kakao conference preparation team, and the trip I vlogged about below was a Jeju business trip for focused porting work. Working while enjoying beautiful scenery and eating tons of delicious food, basically a solo trip to Jeju, was so refreshing at the time, and it's one of the most memorable things from 2022. Working at a company with headquarters in Jeju means workshop trips to Jeju are pure healing!! 

As I mentioned in the vlog, meeting Kevin and Joel at the time was really impressive. They're alumni from the same school, and both were doing a month-long Jeju workation in a related department, so we met up. Our lifestyles and development philosophies were similar, and I was really envious that they had someone whose vibe matched so well to travel and work with for a whole month. I'm super excited for my Switzerland trip with Joel in '23 too hehe

https://www.youtube.com/watch?v=X0YzYGM7JDw 

 

4. And the Actual Development

This year, refactoring work and porting legacy code were my main tasks, but I also got involved in developing user-facing features along the way. Being too focused on internal tasks was burning me out, and I wanted to find some fun in development again, so I thought I'd like to work on features that actual users would use.

The project I ended up working on was the Memorial Profile feature, but unfortunately, I happened to go on a week-long trip during the busiest time in December, so I felt really bad for Vince who was working on it with me. Still, I did my best to follow up before and after! The server workload wasn't that heavy honestly, but when it launched in January '23 and the user response was so positive, I felt really proud. Thanks to that experience, whenever I get to build a service that's close to users, it motivates me to develop more awesome features or improve existing ones, and it makes me feel like I can live with pride as a developer.

https://cs.kakao.com/helps?service=8&category=226&device=1&locale=ko&articleId=1073205009&controllerName=help&actionName=mobileviewpage&accountLoginUrl=https%3A%2F%2Faccounts.kakao.com%2F&without_layout=false 

 

Customer Center

Check out the help guides for each service through the Kakao Customer Center.

cs.kakao.com

 

 

5. Pangyo IDC Outage Response / World Cup Response / New Year's Response

Q4 was a whirlwind. With all sorts of incident responses, I ended up working in the early morning hours a lot. 

The Pangyo outage response is something I'll never forget — even if I keep working as a developer for the rest of my life, I doubt I'll ever deal with an incident of that scale again. It started at 3 PM Saturday and I worked non-stop until 7 AM Sunday, slept for 2 hours, got back up and worked from 9 AM Sunday until midnight.. Then on Monday, went in at 9 AM and worked until midnight again.. All I could think about at the time was recovering as fast as possible. Knowing that for every moment I was sleeping, people around me couldn't use the service — the adrenaline was pumping so hard my heart wouldn't stop racing and I couldn't sleep. But watching the services come back to life one by one as we devised software solutions for a physical outage was actually exciting, and it was a moment where I felt an incredible thrill as a developer.

For the World Cup traffic and New Year's traffic, I was monitoring from behind the scenes in case anything went wrong with the servers. Being on our team, it's truly fascinating to watch the traffic on our service rise and fall based on user patterns. The fact that we can directly see usage data from most of the Korean population through actual data always gives me a lot of insights, and I learn so much from preparing and implementing response logic accordingly. I'm always grateful that my first job and first team is one that has to consider so many things to handle massive traffic.

 

External Developer Activities

1. Blog

2022 Visitor Count

I'm maintaining about 13,000 monthly visitors. I honestly don't even write that much.. but the Spring fundamentals posts and retrospective posts I wrote before are popular, so there's a steady stream of visitors. Maybe I'll write more blog posts in '23

 

2. YouTube

https://www.youtube.com/@developer-jyami

 

Developer Jyami

🌱Developer Jyami's Daily Log🌱 A dev who climbs

www.youtube.com

I hit 3,400 subscribers. In 2022, I only uploaded 1 sponsored video, 1 KakaoTalk tips video, and 1 Jeju vlog.. haha since it's a hobby YouTube channel I upload whenever I feel like it, so naturally the subscriber count isn't growing dramatically.

Still, sometimes when new employees join the company, they've seen the past glories of me working hard through the blog or YouTube, and thankfully they think positively of it and recognize me. That means I should keep working hard but..ㅠㅠ In 2022, I was more focused on things other than growing as a developer, so I didn't upload much to the blog or YouTube.

3. Seminars

I don't go to external conferences much, but I try to participate in school events to keep networking with university seniors and juniors. In 2022, I gave 3 seminars in total, and since they were all aimed at college students preparing for job hunting, I mostly talked about careers.

  • January — GDSC EWHA Alumni Seminar: The flow of how a server developer scales architecture
  • November — Ewha Womans University Computer Science Cloud Day: How should developers study?
  • November — GDSC EWHA Homecoming Day: Q&A about things you're curious about as a server developer

While preparing the presentations, I was able to organize my thoughts on how I had studied development and how I should study going forward. So I guess that's why everyone says to give tech talks and do mentoring — because it lets you reflect on yourself too. On the topic of "How should developers study?", I talked about how as architecture gradually expands, you should expand your studies on-the-fly based on the requirements at hand. The main point was that rather than rote-memorizing CS concepts just because they come up in interviews, the knowledge you gain from actually building services or projects sticks with you much more. Fortunately, many juniors asked lots of questions and reached out to me afterward, so I remember it as an event where I felt proud and could feel their passion.

 

4. Interview

https://korea.googleblog.com/2022/10/GDSC-job-fair-2022.html

 

Become a developer ready for employment with Google Developer Student Clubs!

GDSC (Google Developer Student Clubs) is a university-based community group for students interested in Google technologies, currently active at about 1,800 universities in over 110 countries worldwide. College students together A..

korea.googleblog.com

GDSC reached out to me, so I did a written interview. I actually became well-known through this blog during my job-hunting days, but now that I've been working for a full 3 years, I worry if my stories are becoming too "back in my day." Especially now that I'm working out, I realize even more how unhealthy it was to just pull all-nighters without exercising back then.

 

5. Study Groups?

Since my main interest was working out, the thought of studying development was just sitting in the back of my mind, so I didn't study much after work like I used to. From March to June, I did an Effective Kotlin book study with Javabom.

I had high expectations, thinking it would give insights like Effective Java, but Kotlin hasn't accumulated as many anti-patterns or gotchas as Java yet, so it didn't hit me as hard as Effective Java did. My all-time best book is still Effective Java... For Kotlin, I actually preferred Kotlin in Action — it felt more practical and had richer content.

Similarly, when doing Effective Kotlin with Javabom, I organized code on GitHub and wrote blog posts at the same time. The related links are below:

I realized that it's not easy to find like-minded people to study with at the depth I want while working a full-time job. Meeting Javabom in college was truly lucky. So if I'm going to study going forward, I'll need to find my own motivation and keep at it consistently, but that's easier said than done ㅠ There are too many fun things in life! I think figuring out how to study going forward is something I'll need to keep thinking about.

 

Jyami the Athlete

Honestly, this might be the real main topic. I put the developer stuff up top out of conscience since the title says devlog, but my true identity in 2022 was an athlete lol. The workouts I started in 2021 turned out to be more fun than expected, and after getting hooked on climbing starting February 2022, I've been exercising consistently. Once I started one sport, I naturally picked up others too, so it was a year of trying and challenging myself with all sorts of things.

1. Climbing

This is the sport I've been doing consistently since February. Honestly, weight training feels more like a "real workout," while climbing is technically exercise but it fires up my competitive side so much that it feels more like a game. With consistent practice, my skills improved a lot from the beginning, and I got to meet so many new people through climbing, which made 2022 a really enjoyable year. 

2022 climbing calendar

Looking at the calendar above, I really did go a LOT lolol. And when I compiled my gym list, I visited so many places too hehe.

There are actually many different types of climbing, and since I like trying all sorts of things, I did everything without discrimination — indoor bouldering, artificial wall lead climbing, outdoor bouldering, and outdoor lead climbing. I even traveled to faraway places just for climbing and went on tons of trips. I wanted to try climbing so badly that I just signed up for a one-day lesson at Underdog Climb on impulse, and it was seriously fun. After that, I started going to climbing gyms on my own, made friends with people there, got introduced to their friends, and ended up climbing together and visiting all kinds of places.

From March to April, I took beginner classes at Moran Climb Us, and after that, starting around May I think, I've been renewing my membership at The Climb for indoor bouldering ever since. At first I struggled even with The Climb's green problems, but before I knew it, I was clearing one or two red problems each visit, and at the end of 2022, I even completed a purple one!! Until around September when I was combining weight training with climbing, my skills were improving super fast and it was fun every time. But honestly, toward the end of 2022, I drank way too much because of year-end gatherings, and I think I lost some muscle because I hit a plateau.. hehe. In 2023, I want to keep doing both weight training and climbing consistently and get even better!

As a climbing newbie curious about everything, I toured a ton of climbing gyms around Seoul in the first half of the year, and eventually ended up going on lots of climbing trips too. Busan, Sokcho, Daejeon, Jeju, Yangyang, Jinan, and even Thailand — no matter where I traveled, I was becoming that climbing-obsessed person who associates every destination with climbing. In the second half, after getting a membership at The Climb, I stopped going on expeditions to different gyms and became more interested in outdoor climbing rather than indoor.

As autumn arrived in September and the weather got nicer, I wanted to be outside rather than indoors, so I ended up starting lead climbing. I learned lead climbing from Sona unnie, who lives nearby, and eventually joined the Dolmuri crew, who regularly do lead climbing. I wanted to climb while looking at the beautiful autumn skies, so I started with lead climbing on artificial walls and eventually progressed to actual natural rock faces, even traveling all the way to Krabi, Thailand. The outdoor lead climbing in Krabi was definitely the most memorable event of 2022, and I was grateful that all of us Dolmuri crew members got along without a single fight, looked out for each other, and safely completed the 8-night, 9-day climbing and Thailand trip. 

On top of that, I participated in Girls On Top hosted by The Climb and the bouldering party hosted by Climb Us, where I got to experience the thrill of solving as many problems or high-scoring problems as possible within a limited time. Honestly, every time I did these events, I wished I were a bit stronger and ended up registering in a lower grade category. But still, this is pretty good for just one year of climbing!!! Let's make sure to participate in lots of events in 2023 too.

What started from a simple thought of "this seems fun" turned into a hobby that let me meet people from all different professions, and I never imagined I'd be living a life where I travel for my hobbies. Honestly, this whole year I was so deep into climbing and exercise that my daily routine after work became going to work out rather than studying development. But I think it's a good thing because I ended up with a much healthier lifestyle. If 2022 was all about being obsessed with exercise, in 2023 I want to exercise while also taking care of real life a bit more.


Bouldering (Indoor 28 + Outdoor 2)

  • Underdog Climbing (Suwon)
  • The Climb (Yangjae + Gangnam + Sillim + Seoul National Univ. + Magok + Hongdae + Yeonnam + Ilsan)
  • Climb Us (Moran)
  • Peakers Climbing (Jongno)
  • Seoul Forest Climbing (Seoul Forest)
  • Climbing Park (Jongno + Sinnonhyeon + Hanti)
  • Epic Climb (Yeongtong)
  • Dot Climbing (Songpa)
  • Boulder Mate (Giheung)
  • Rock Tree (Bundang)
  • B-Block Climbing (Eonju + Songdo)
  • Allez Climbing (Hyehwa)
  • Son Sangwon Climbing Gym (Gangnam)
  • Expedition: I'm Not Boulder (Sokcho)
  • Expedition: Wave Rock (Gwangalli, Seomyeon)
  • Expedition: Fix Boulder (Jeju)
  • Expedition: Basecamp (Daejeon)
  • Natural Rock: Yangyang Jukdo-am
  • Natural Rock: Jinan Unil-am Banil-am

Lead (Artificial Wall 4 + Natural 2)

  • Pangyo Park
  • Ttukseom Hangang Park
  • Yeongdeungpo Sports Climbing Arena
  • Gwanggyo Sports Climbing Center
  • Outdoor Lead: Jobisan
  • Outdoor Lead: Krabi (Thailand)

Events

  • Peakers Bouldering Festival
  • The Climb Girls On Top
  • The Climb Gangnam Branch Opening Festival
  • Moran Bouldering Party

 

2. Weight Training

So what's your big three? I don't remember squat exactly, but S: 55kg / B: 32.5kg / D: 75kg = Big Three total of 162.5kg.
I haven't been doing much weight training lately so I'm not great at the big three lifts, and the numbers have probably dropped even more ㅠㅠ These were my records when I was consistently doing PT from January to October. I did quite a lot of PT sessions in 2022 so it cost a lot, and honestly I got to the point where I could handle equipment usage and muscle activation on my own well enough, so starting November I've been working out solo without a trainer. Toward the end of my PT sessions, my trainer must have noticed I found isolation exercises boring, so they had me try CrossFit and weightlifting movements too lol. And since I picked them up quickly, my trainer had fun with it too lol. Once I found interest in exercise, it wasn't about doing "isolation exercises" anymore — I became someone who just wants to try any kind of exercise.

This is the comparison between my InBody results from January 2022 and September 2022. I should have done one in December but I forgot ㅠㅠ These results were achieved purely through exercise alone, without any diet changes — just eating the way I normally do. I didn't set specific body goals, but seeing my body shape change and the data improve gave me a real sense of accomplishment, and I can feel that my body has become much healthier than before. In daily life too, I used to find it really burdensome to move heavy objects, but at some point I became able to move them easily by myself, which actually improved my quality of life.

Right now I'm not doing much weight training since climbing is my main workout, but I still try to hit the gym at least once a week to develop the muscles opposite to the ones used in climbing. Also, when my body feels really heavy, doing some light cardio improves my mood and makes me feel lighter. But I don't think I'll be making weight training my main workout going forward. So my big three numbers will probably keep going down.. I plan to do it just enough to maintain reasonable health.

 

3. One-off Sport Experiences

As climbing and weight training got me more and more into exercise, I became unafraid to try various sports even if just once. I went to a ski resort for the first time in my life and tried skiing, and I was going to just try freediving but ended up taking a certification course (though I guess I'm too impatient.. it didn't really suit me so I quit). I wanted to get better at dynamic moves in climbing, so I went to Undercover for a parkour experience and ended up becoming friends with the parkour coaches. I also tried running, which I always thought I'd never do because I absolutely hated cardio, but my times were surprisingly good for a first-timer, so it was pretty interesting. (5km in 6 minutes 11 seconds)

Just like how knowing one programming language well makes it easier to learn another, I felt the same applies to sports. Since I had built up a decent foundation of upper and lower body muscles through weight training and climbing, I could pick up other sports pretty quickly for a beginner, which made it easy to get interested fast. But still, climbing is just too fun for now.. hehe.

 

So in 2023..

You could probably feel it from the tone of this post, but I wrote calmly when talking about development and super energetically when talking about exercise lol. That's how much 2022 was a year prioritizing getting healthy and finding fun through sports, rather than growing as a developer. But I can't just chase fun forever ㅠ So I've been thinking about how I can make studying development more enjoyable. One senior developer told me that if you combine your hobbies with development, you naturally end up studying because it's something you're interested in. So I'm thinking about building a climbing-related service as a side project after work. If 2022 was a year of only muscle growth, let's make 2023 a awesome year where I achieve both muscle growth AND growth as a developer!! Let's go!

댓글

Comments

Develop/Kotlin

backingField와 recursive call | Backing Field and Recursive Call

Backing fieldclass User(name: String) { var name: String = name get() = name set(value) {name = value}}위와 같은 클래스가 있다고 할 때, 코틀린에서 해당 property를 get 혹은 set 할 때 재귀호출이 일어나게 된다.public fun main(){ println(User("mj").name) User("mj").name = "jyami"}위와 같이 name 프로퍼티를 접근하는 것이 getter를 부르는 것과 같기 때문에결국get() = this.get() 과 같이, getter를 부르면서 다시 getter를 호출하는 것과 같다.마찬가지로 name 프로퍼티를 할당하는 것도 set..

backingField와 recursive call | Backing Field and Recursive Call

728x90

Backing field

class User(name: String) {
    var name: String = name
        get() = name
        set(value) {name = value}

}

위와 같은 클래스가 있다고 할 때, 코틀린에서 해당 property를 get 혹은 set 할 때 재귀호출이 일어나게 된다.

public fun main(){
  println(User("mj").name)
    User("mj").name = "jyami"
}

위와 같이 name 프로퍼티를 접근하는 것이 getter를 부르는 것과 같기 때문에
결국get() = this.get() 과 같이, getter를 부르면서 다시 getter를 호출하는 것과 같다.

마찬가지로 name 프로퍼티를 할당하는 것도 setter를 부르는 것과 같아서. set()=this.set("jyami") 다시 setter를 호출하게 된다.

따라서 getter, setter 모두 본인의 필드를 참조하는 경우에는 StackOverflowException 을 발생시키게 된다. 친절하게도 intellij 에서는 recursive call 이라고 안내를 해주고 있다.

추가로 kotlin을 kotlinc를 사용하여 생성된 바이트코드를 보면 어떤 경우에 backing field가 생성되는지를 볼 수 있다. 즉 backing field가 인스턴스 변수로 생성되는 경우는 아래와 같다.

  • 하나이상의 기본 접근자를 사용하는 경우 (getter, setter)
  • 커스텀하게 만든 접근자에서 field 를 사용하는 경우.
data class HttpResponse(val body: String, var headers: Map<String, String>) {

    val hasBody: Boolean
        get() = body.isNotBlank()

    var statusCode: Int = 100
        set(value) {
            if (value in 100..599) field = value
        }
}

body, header는 기본 접근자를 이유로, statusCode는 커스텀 접근자를 이유로 생성되는데, hasBody는 그렇지 않다. (필드로 생성되지 않는다.)


javap -c -p com.kakao.talk.HttpResponse

 Compiled from "BackingField.kt"

public final class com.jyami.HttpResponse {
  private final java.lang.String body;
  private java.util.Map<java.lang.String, java.lang.String> headers;
  private int statusCode;

  // 함수들의 어셈블러 코드

Backing field

class User(name: String) {
    var name: String = name
        get() = name
        set(value) {name = value}

}

Given a class like the one above, in Kotlin, accessing the property via get or set will cause a recursive call.

public fun main(){
  println(User("mj").name)
    User("mj").name = "jyami"
}

Since accessing the name property is essentially the same as calling its getter,
it ends up being equivalent to get() = this.get() — calling the getter triggers the getter again.

Likewise, assigning to the name property is the same as calling its setter, so set()=this.set("jyami") ends up calling the setter again.

So if both the getter and setter reference their own field, it will throw a StackOverflowException. Thankfully, IntelliJ is kind enough to warn you with a "recursive call" message.

Additionally, if you look at the bytecode generated by kotlinc, you can see when a backing field is actually created. In other words, a backing field is generated as an instance variable in the following cases:

  • When at least one default accessor is used (getter, setter)
  • When a custom accessor uses the field identifier.
data class HttpResponse(val body: String, var headers: Map<String, String>) {

    val hasBody: Boolean
        get() = body.isNotBlank()

    var statusCode: Int = 100
        set(value) {
            if (value in 100..599) field = value
        }
}

body and headers get backing fields because they use default accessors, and statusCode gets one because of its custom accessor — but hasBody does not. (It is not generated as a field.)


javap -c -p com.kakao.talk.HttpResponse

 Compiled from "BackingField.kt"

public final class com.jyami.HttpResponse {
  private final java.lang.String body;
  private java.util.Map<java.lang.String, java.lang.String> headers;
  private int statusCode;

  // Assembler code for functions

댓글

Comments

Develop/Kotlin

Kotlin Void vs Unit vs Nothing | Kotlin Void vs Unit vs Nothing

Void자바의 voidjava.lang 패키지안에 있는 Void 클래스 : java의 primitive type인 void를 래핑하는 객체이다. (int wrapper인 Integer과 같다고 보면 된다.)자바에서는 void 말고 Void를 리턴해야하는 경우가 많지 않다. : 제네릭에서 Void를 사용하는 정도의 용례package java.lang;/** * The {@code Void} class is an uninstantiable placeholder class to hold a * reference to the {@code Class} object representing the Java keyword * void. * * @author unascribed * @since 1.1 */publi..

Kotlin Void vs Unit vs Nothing | Kotlin Void vs Unit vs Nothing

728x90

Void

자바의 void

java.lang 패키지안에 있는 Void 클래스 : java의 primitive type인 void를 래핑하는 객체이다. (int wrapper인 Integer과 같다고 보면 된다.)

자바에서는 void 말고 Void를 리턴해야하는 경우가 많지 않다. : 제네릭에서 Void를 사용하는 정도의 용례

package java.lang;

/**
 * The {@code Void} class is an uninstantiable placeholder class to hold a
 * reference to the {@code Class} object representing the Java keyword
 * void.
 *
 * @author  unascribed
 * @since   1.1
 */
public final
class Void {

    /**
     * The {@code Class} object representing the pseudo-type corresponding to
     * the keyword {@code void}.
     */
    @SuppressWarnings("unchecked")
    public static final Class<Void> TYPE = (Class<Void>) Class.getPrimitiveClass("void");

    /*
     * The Void class cannot be instantiated.
     */
    private Void() {}
}

Void를 코틀린에서 사용할 때

fun returnTypeAsVoidAttempt1() : Void {
    println("Trying with Void return type")
}

이때 컴파일이 되지 않는다.

Error: Kotlin: A 'return' expression required in a function with a block body ('{...}')

그래서 코틀린에서 Void 객체를 만들어서 return 해야하나. 위의 Void 클래스 정의와 같이 private constructor로 인스턴트화가 막혀있다.

따라서 위 경우에는 어쩔수 없이 Void를 nullable로 만들고 Void? null을 리턴해야한다.

fun returnTypeAsVoidAttempt1() : Void? {
    println("Trying with Void return type")
    return null
}

작동하는 솔루션이 있긴하나. java의 void와 같이 동일한 결과를 낼 수 있는 방법으로 Unit 타입이 있다. (의미 있는 것을 반환하지 않는 함수의 반환 유형)

https://www.baeldung.com/kotlin/void-type

 

Unit

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/#unit

https://kotlinlang.org/docs/functions.html#unit-returning-functions

반환값이 필요없을 때, 함수의 반환타입으로 Unit을 사용한다.

반환타입이 Unit일 경우네는, return Unit;. return; 모두 선택적으로 작성해도 된다.

fun printHello(name: String?): Unit{
    if (name != null) {
        println("hello $name")
    } else {
        println("Hi")
    }
}

java에서의 void와 대응한다. 그러나 자바에서 void는 반환 값이 없음을 의미하는 특수 타입이지만, Unit은 class로 정의된 일반타입이다.

Unit은 기본 반환 유형이므로 그리고 return 타입 명시를 안했을 때도 함수가 작동한다.

// Unit.kt
package kotlin

/**
 * The type with only one value: the `Unit` object. This type corresponds to the `void` type in Java.
 */
public object Unit {
    override fun toString() = "kotlin.Unit"
}

따라서 Unit 타입을 반환하는 함수는 return을 생략해도 암묵적으로 Unit 타입 객체를 리턴한다 (싱글턴 객체이므로 객체 생성은 하지 않는다.)

즉 기원적으로 Void는 Java를 사용할 때 만들어진 클래스, Unit은 Kotlin을 사용할 때 만들어진 클래스인 듯

 

Nothing

kotlin에서는 throw가 expression 이다. 그래서 이때 throw의 타입이 Nothing 이다.

이 타입은 값이 없으며, 도달할 수 없는 코드 위치를 표한하는데 사용된다. Nothing을 사용하면, 도달할 수 없는 코드의 위치를 컴파일단에서 체크가 가능하다.

fun fail(message: String): Nothing {
    throw IllegalArgumentException(message)
}

컴파일단 체크 덕분에 잠재적인 버그와 좋지 않은 코드로부터 확인이 가능하다. 반환 유형이 Nothing인 함수가 호출되면 이 함수 호출 이상으로 실행되지 않고, 컴파일러에서 경고를 내보낸다.

fun invokeANothingOnlyFunction() {
    fail("nothing")
        println("hello") // Unreachable code
}

또한 Nothing은 type inference (타입추론)에도 사용이 가능하다.

  • null을 사용하여 초기화된 값일 때의 타입추론
  • 구체적인 타입을 결정하는데 사용할 수 없는 경우에서의 타입추론
val x = null // "type : Nothing?"
val l = listOf(null) // "type : List<Nothing?>"

Nothing은 java에서 대응되는 개념이 없으며, 자바에서는 주로 throw 처리를 할 때 void를 사용했었다.

// Nothing.kt
package kotlin

/**
 * Nothing has no instances. You can use Nothing to represent "a value that never exists": for example,
 * if a function has the return type of Nothing, it means that it never returns (always throws an exception).
 */
public class Nothing private constructor()

마찬가지로 Nothing도 객체를 생성할 수 없다. (값을 가지지 않는다.)

따라서 Nothing이 값을 가질 수 있는 경우는 Nothing? 에서 null 이 할당되었을 때 뿐이다.

Void

Java's void

The Void class in the java.lang package: It's an object that wraps Java's primitive type void. (Think of it like Integer being the wrapper for int.)

In Java, there aren't many cases where you need to return Void instead of void — it's mostly used in generics.

package java.lang;

/**
 * The {@code Void} class is an uninstantiable placeholder class to hold a
 * reference to the {@code Class} object representing the Java keyword
 * void.
 *
 * @author  unascribed
 * @since   1.1
 */
public final
class Void {

    /**
     * The {@code Class} object representing the pseudo-type corresponding to
     * the keyword {@code void}.
     */
    @SuppressWarnings("unchecked")
    public static final Class<Void> TYPE = (Class<Void>) Class.getPrimitiveClass("void");

    /*
     * The Void class cannot be instantiated.
     */
    private Void() {}
}

Using Void in Kotlin

fun returnTypeAsVoidAttempt1() : Void {
    println("Trying with Void return type")
}

This won't compile.

Error: Kotlin: A 'return' expression required in a function with a block body ('{...}')

So should we create a Void object and return it in Kotlin? Well, as you can see from the Void class definition above, instantiation is blocked by a private constructor.

So in this case, you have no choice but to make Void nullable as Void? and return null.

fun returnTypeAsVoidAttempt1() : Void? {
    println("Trying with Void return type")
    return null
}

While this is a working solution, there's a better way to achieve the same result as Java's void — the Unit type. (It's the return type for functions that don't return anything meaningful.)

https://www.baeldung.com/kotlin/void-type

 

Unit

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/#unit

https://kotlinlang.org/docs/functions.html#unit-returning-functions

When you don't need a return value, you use Unit as the function's return type.

When the return type is Unit, both return Unit; and return; are optional — you can write either or omit them entirely.

fun printHello(name: String?): Unit{
    if (name != null) {
        println("hello $name")
    } else {
        println("Hi")
    }
}

It corresponds to void in Java. However, while void in Java is a special type meaning "no return value," Unit is a regular type defined as a class.

Since Unit is the default return type, functions work even when you don't explicitly specify a return type.

// Unit.kt
package kotlin

/**
 * The type with only one value: the `Unit` object. This type corresponds to the `void` type in Java.
 */
public object Unit {
    override fun toString() = "kotlin.Unit"
}

So a function that returns Unit implicitly returns the Unit object even if you omit the return statement. (Since it's a singleton object, no new object is created.)

In other words, it seems like Void is a class that originated from Java, while Unit is a class that originated from Kotlin.

 

Nothing

In Kotlin, throw is an expression. And the type of that throw expression is Nothing.

This type has no value and is used to mark code locations that can never be reached. By using Nothing, unreachable code locations can be checked at compile time.

fun fail(message: String): Nothing {
    throw IllegalArgumentException(message)
}

Thanks to compile-time checks, you can catch potential bugs and bad code. When a function with a return type of Nothing is called, execution never continues beyond that function call, and the compiler emits a warning.

fun invokeANothingOnlyFunction() {
    fail("nothing")
        println("hello") // Unreachable code
}

Nothing can also be used in type inference.

  • Type inference for values initialized with null
  • Type inference when a concrete type cannot be determined
val x = null // "type : Nothing?"
val l = listOf(null) // "type : List<Nothing?>"

Nothing has no corresponding concept in Java. In Java, void was typically used when handling throw.

// Nothing.kt
package kotlin

/**
 * Nothing has no instances. You can use Nothing to represent "a value that never exists": for example,
 * if a function has the return type of Nothing, it means that it never returns (always throws an exception).
 */
public class Nothing private constructor()

Likewise, Nothing cannot be instantiated either. (It holds no value.)

Therefore, the only case where Nothing can hold a value is when null is assigned to Nothing?.

댓글

Comments

Daily/About Jyami

2021년 회고 | 2021 Year in Review

우선 회고를 시작하기 전에, “올해도” 연말에 카톡 메시징 서버 문제 없었다!!! 올해는 내가 직접 연말 대응을 핸들링 하게 되었어서, 연말 기록까지 남기고 싶어서 회고를 뒤로 미루게 되었다.20년도 9월에 입사를 하고 12월부터 실질적인 실무 업무를 시작하게 되었는데 22년이된 지금!! 내가 3년차라니?!! 너무 놀랍다ㅋㅋㅋ 사실상 실무를 1년 1개월 정도 한 상태인데 3년차라니.. 다시 한번 놀랍다.그래서 21년도는 나에게 입사 후 실무 개발자로써 적응을 하는 시기, 이제 개발을 직업으로 삼게 되면서 일과 일상의 밸런스를 위해 개발 외에 것들을 시도해보는 시기였다. 그렇다면 지금부터 회고를 시작해보자이번 회고는 1년치 일기장쓴 기분이라 가독성이 없다. 1. 회사1-1. 업무를 숙제처럼?매일매일 업무일..

2021년 회고 | 2021 Year in Review

728x90

우선 회고를 시작하기 전에, “올해도” 연말에 카톡 메시징 서버 문제 없었다!!! 올해는 내가 직접 연말 대응을 핸들링 하게 되었어서, 연말 기록까지 남기고 싶어서 회고를 뒤로 미루게 되었다.

재택근무 쾌-적-

20년도 9월에 입사를 하고 12월부터 실질적인 실무 업무를 시작하게 되었는데 22년이된 지금!! 내가 3년차라니?!! 너무 놀랍다ㅋㅋㅋ 사실상 실무를 1년 1개월 정도 한 상태인데 3년차라니.. 다시 한번 놀랍다.
그래서 21년도는 나에게 입사 후 실무 개발자로써 적응을 하는 시기, 이제 개발을 직업으로 삼게 되면서 일과 일상의 밸런스를 위해 개발 외에 것들을 시도해보는 시기였다. 그렇다면 지금부터 회고를 시작해보자

이번 회고는 1년치 일기장쓴 기분이라 가독성이 없다.

 

1. 회사

1-1. 업무를 숙제처럼?

매일매일 업무일지를 쓰면서 회사 일을 하나씩 처리했는데, 확실히 상반기와 하반기를 비교하면 많이 달라진게 느껴진다.
상반기만해도 일반채팅 개발버전 배포하는 것만해도 엄청 놀라워하고 가슴떨려하고 그랬는데, 하반기에 와서는 그 일반채팅을 리얼 버전으로 서버를 증설해서 배포하기도하고, 서버 배포 설정을 수정하려고 ansible을 이래저래 고치기도하고 결국 마지막엔 연말대응까지 이것이 짬이 차는 과정인가..?😳

빼곡하게 적었던 나의 업무일지 (내용은 비공개)

확실히 상반기 후반기 사이 내가 업무를 하는 모습에서 차이는 있었던 것같다. 상반기만해도 내가 이런 커다란 과제를 해도 될까? 잘 모르는데 메시징 일을 받아도 될까? 망설이면서 시니어분들이 지정해주시는 일만 했었다면, 하반기에는 상반기에 비해서 내가 먼저 일을 찾아서 했었던 것 같다. 파트에서 묵혀둔 이슈를 몇개 가져가기도하고, 클라이언트분과 친해지면서 적극적으로 커뮤니케이션하면서 메시징 로직 가이드를 드리기도하고, 코드에서 고치고 싶은 사항이 있다고 하면 먼저 이슈를 따서 진행하기도하고 그랬었다. 상반기 초에 파트 시니어 분께 “쟈미는 일을 숙제하듯이 해” 라는 말을 들었었는데, 이 말이 변하게 된 계기였던 것 같다. 처음 이 말을 들었을 때는 아무 생각없이 음 나는 숙제 항상 잘했고 퀄리티 높게 해왔었으니까. 되게 정성적으로 한다는 뜻인가? 하고 생각했었는데, 이 말이 신경쓰여서 은님께 여쭤보니, 일을 좀더 능동적으로 해야한다는 말이라는 것을 알게되었기 때문이다.

1-2. 어떤 개발자가 좋은 개발자일까?

그래도 아직은 이슈를 자잘자잘하게 가져가는 느낌이긴 하다. 자진해서 c > java 포팅작업을 주도하겠다 라는 시니어 개발자 분이 있었는데, 이분처럼 나중에는 정말 큰 이슈도 내가 먼저 이슈업 하는 날이 오지 않을까?라는 생각이 들기도한다. 이런 걸 보면 확실히 메시징파트에는 참 배울 분들이 많다고 느낀다. 그런데 그때문에 입사 전과 후로 어떤 개발자가 되어야하나라는 생각에 변동을 겪고있다. 이전에는 당연히 자바, 스프링 좋아하니까 그걸 마구마구 파고 막 클린코드, DDD이런거 다 적용하는 개발자가 좋고, 당연히 실무에 들어가면 spring구조 다 까보고 그러고 있으면 좋은 개발자가 되지 않을까? 라고 생각하고 있었다, 그런데 입사 이후에는 어떻게 하면 좀 더 좋은 구조의 서버 구조를 가지고, 여러가지 컴포넌트를 올바르게 사용할 수 있는지도 매우 중요하구나를 깨닫고있다.

왜냐하면 아무래도 장애가 나거나, 새로운 컴포넌트에 대한 계획을 세울때는 코드를 어떤방식으로 짜고.. 보다는 어떻게 하면 좀더 성능을 높일 수 있고, 이런 엣지케이스에는 어떻게 대응할 것이고 등등의 실무적인 관점을 접했기 때문이 아닐까 싶다. 그래서 이전에는 redis를 사용한다하면, spring-data-redis를 사용할 때 어떤 메서드를 사용해야 좋은 코드 좋은 테스트 코드를 짤 수 있다! 이런거를 고려했다면, 지금 메시징 파트에 와서는 redis 자체에 대해서 고민을 해야한다는걸 깨달았다. redis가 가지는 자료구조, failover 정책, evction 정책, 백업 정책 등등 그 자체에 대해서 먼저 알고가는게 더 중요할 수 있다는 걸 경험적으로 습득하게 되었다. 그래서 그냥 어떤 언어를 잘하는 보다는 문제상황이 발생하면 잘 해결하는 개발자가 사실 일하기는 가장 좋은게 아닐까 하면서 생각이 변하는 중이다. 파트장님과도 여러번 고민을 공유했었는데, 다 다른길을 걷고있고 어떤 개발자가 좋다는 정답은 없다고 조언을 주셨었다.

1-3. 인턴멘토 / 공채 신입 코드리뷰어

그리고 하반기부터 내 아래로 인턴 / 신입분들이 들어왔다. 나는 내가 아직도 신입같은데.. 내가 인턴분의 멘토를 했었고, 공채 신입 분들의 코드리뷰를 담당하고 있다. 사실 처음에는 나보다 나이가 많으신 분들을 대상으로 괜찮으려나 걱정도 했었는데 괜찮았다.✌️ 어찌됐든 신입 과제가 내가 알고있는 선에서 나왔고 모르면 공부하면 되니까라고 생각했다.
나도 연차가 많이 높진 않지만 인턴 멘토를 하면서 회사가 어떤 사람을 신입개발자로 뽑고 싶어하는지를 파악하면서 가이드를 드렸었다.

더보기
많은 신입개발자분들이 과제를 하다보면, 정말 실무자처럼 잘하고 싶어하고 물어보지 않아도 본인이 척척 다 하는 모습을 보여주고 싶어한다. 그래서 멘토가 준 요구사항 명세를 꼬치꼬치 캐묻고, 그러다보면 정량적으로 요구사항을 충족하게 된다. 그런데 그러다보면 놓치기 쉬운 것이 “왜 이렇게 개발을 해야겠다고 결정했는가, 왜 이런 결과물을 내야겠다고 생각했는가”라는 왜라는 질문이다. 서버 성능 테스트라는 요구사항이 있다고 해보자. 신입은 그 요구사항을 보고, 서버 성능테스트에 대해 찾아보고 멘토에게 ngrinder라는 툴을 추천받아서 서버의 tps가 잘 나온다는 것을 확인해서 결과 보고서로 낸다. 그런데 최종 면접관은 이렇게 물어본다. “왜 서버 성능테스트의 비교 대조군을 이렇게 했어요?”, “만약 N명의 유저가 접근해도 문제가 없으려면 이 서버 tps로는 부족할 거 같은데 혹시 다른 지표가 있을까요? / 어떻게 개선이 가능할까요” 등등…의 질문을 유도한다. 왜 이런 코드를 짰는지, 이런 툴을 왜 썼는지, 왜 이런 구조로 서버가 되어있는지 의사결정을 하게된 논리적인 흐름을 중요시한다.

근데 이런 질문리스트까지 멘토가 미리알고 하나하나 신경써주고 대비시켜준다는건 사실 쉽지않다고 생각한다. 따라서 본인이 여러 참고자료를 찾아보고 이툴과 다른 툴과의 비교해서의 장점부터 시작해서, 현재 본인이 활동중인 파트에서는 어떤방식으로 사용되고있는지 멘토한테 조언을 얻고, 인턴과제로 구현을 하지 않더라도 확장계획이나 현재 부족한 점들을 미리 알고 대비하는 그런 열정있는 모습과 성장가능성을 회사는 보고싶어하는 것 같다. 이렇게 써놓고 보니 쉽지않다…😳


인턴분의 근처에 가장 가까이서 일하면서 많은 것들을 느끼게 되었고, 최대한 합격을 하는데 도움이 되도록 코드단부터 의사결정단까지 조언을 열심히 해주었다. 그러나 당시 인턴분보다 나의 열정이 더 과했던거 같았다..하핫 그래서 사람과의 협업과 매니징이 쉽지않다고 이 당시에 느꼈던게 가장 생생하고, 개발자로서 이 시기에 조금 고민이 있던 것 같다. 앞으로는 많은 사람들의 선배개발자가 될텐데 어떤방식으로 조언을 드려야 도움이 될까를 고민해보게 되었다. 그래서 요즘 신입분들 코드리뷰하면서, 우선 코드단부터 읽으면 좋은 책과 아티클을 PR에 던져드리고 있다🙌 (리뷰를 좀 빡세게 하는 편이라.. 제 리뷰이분들 화이팅..ㅎ)

근데또 써놓고 보니 어렵다 ~_~ 원래 인생 계획없이 사는 타입이라 (지독한 ESTP) 대충 현생에 충실하다보면 미래에도 꽤 괜찮은 사람이 되어있지 않을까

2. 개발 외부 활동

올해에는 커뮤니티 활동을 줄였다. GDSC EWHA 리드였다보니 카카오 면접볼때 받은 질문이 “개발커뮤니티 하는거 좋아하시나요?” 였는데, 그 답변을 충실히 수행했다. “3-2학기 리드활동에 몰입하면서 많은 사람들에게 기여했다는 뿌듯함과 새로운 경력을 쌓은건 좋았다. 그러나 그 때는 개발자로서의 성장이 멈춘 학기였다. 연사섭외 행사준비 등등을 하다보니 개발 공부를 할 시간이 부족했고, 3-1학기의 제 개발 실력과 거의 비슷해서 현타가 왔었다. 그래서 회사에 입사한다면 초반에는 개발공부와 회사 적응에 집중하기 위해 개발커뮤니티쪽에서 눈을 조금 돌리 생각이다.” 라는 답변이었다. 그대로 실천했다. 원래 뭐를 하자는 결심보단 뭐를 하지말자라는 결심이 더 편해서😝

근데 또 막상 되돌아보니 이것저것 하긴 했었더라..? 어쩔 수 없는 관종인가 싶기도하다.

2-1. 유튜브

유튜브는 한달에 한번을 목표로. 블로그는 최대한 기술적인 것들 위주로 쓰고 싶었는데 부진했다. 뭐 어쩔수 없지, 현생을 살면서도 이만큼 챙긴게 어딘가!! 흠흠 유튜브는 (22년 1월 16일 기준) 2813명의 구독자가 생겼다. 정말 소소한 VLOG 동영상만 올리는데도 다들 좋아해주셔서 신기하다. 정작 나는 유튜브는 정말 킬링타임용 및 힐링용으로 예능(더지니어스, 크라임씬, 워크맨 , 문명특급), 게임(파카, 쌀튜브, 여왕럭스) 이런류만 보는편이라 나는 브이로그를 안보는 유튜버다..! (당당)🙄
회사분들이 유튜브 수익 물어보시는데 없다. 유튜브 수익을 얻으려면 구독자 1000명이상 시청시간 4000시간 이상이어야하는데, 내가 영상을 많이 올리지 않아서 시청시간이 부족해서 광고수익이 없다. 아 그런데 상반기에는 멋쟁이사자처럼, 마스슬립에서 협찬 및 광고 제안을 해주셔서 관련 영상을 찍었었는데, 이렇게 협찬을 받고 제작하는 영상은 뭔가 일이 되는 느낌이라 유튜브 영상 올리는게 재미가 없어져서 그 이후부터는 모든 협찬을 거절하고있다. 개발 관련 제품 요청이 아니면 앞으로도 화장품이나 등등의 잡화 요청은 거절할 것 같다ㅋㅋ (뭔가 전자제품이나 파우치 이런거는 유용하지 않을까 싶기도🤔)

유튜브 스튜디오를 보면 분석 전략이 나오는데, 여기 보면의외로 코드윗미가 재생이 많이된다. 그래서 뭔가 나도 다른 코드윗미처럼 이쁜 인테리어 이쁜 조명으로 올리고싶은데..! 음 나는 인테리어가 그렇게 어렵더라;;; 뭔가 내가하는 인테리어는 감성이 부족함 좀더 연구해보겠다😵‍💫 시청자 층은 아무래도 개발자들이 많이 보는지 연령으로는 18~34세가 성별으로는 2:1(남:여) 이더라. 판교뚜벅초(아 진짜 좋아하는 유튜버다 영상이 너무 재밌음), 조코딩, 노마드 코더 유튜브로 흘러들어오는 사람들이 많은듯.

2-2. 블로그

블로그는 사실 올 한해 책을 읽은 달이 훨씬 더 많은데, 책내용을 정리해두긴 했으나 뭔가 내가 정리해둔 정리본을 다시 보기다는 그냥 한번더 읽지 라는 생각이 요즘 들어서 깃에만 저장해두고 블로그에는 따로 정리해서 안올렸다. 그러다보니 블로그에 올라오는 글이 현저히 줄어들었다. 그래서 블로그 인기 글이 대부분 회고록/ 취뽀기 인데,, 흐음 기술 글보다 회고록이 인기가 많은 개발자 블로그라니 🙄이게 맞나? 파트에서 일하면서 ansible이나 이것저것 정리해보고 싶은 주제가 몇개가 있는데 아 주말에 블로그 쓰기/ 유튜브 편집하기가 정말 쉽지않더라 직장인에게 꿀같은 주말이기 때문에…😘 22년에는 시간을 좀 내보는걸로 하자.

아근데 생각해보니, 내 블로그가 아니라 회사블로그에 글을 썼다.ㅋㅋㅋㅋ 카카오 테크 블로그에 내 글이 있다는게 뿌듯하기도하고.. 한번쯤은 해보고 싶었는데 유관부서에서 먼저 요청이 왔다 하핫. 글은 아래에 있다.

https://tech.kakao.com/2021/05/24/jyami/

 

뉴크루의 카카오 백엔드 개발자 이야기

안녕하세요, 톡플랫폼개발팀 톡메시징파트의 신입 개발자 쟈미(jyami)입니다. 저는 자바, 코틀린을 좋아하는 백엔드 개발자이고, 카카오에 들어온 지는 약 반 년이 되어갑니다. 제가 카카오에 입

tech.kakao.com


https://tech.kakao.com/2021/10/25/grace-hopper-celebration/

 

Grace Hopper Celebration 참가기

카카오에서는 크루의 주도적인 성장과 역량 향상을 위해 글로벌한 인사이트 확대를 경험할 수 있도록 해외 컨퍼런스 참관 참여를 지원하고 있습니다. 안녕하세요, 톡플랫폼개발1팀의 jyami입니

tech.kakao.com


위에있는 뉴크루의 백엔드 개발자 이야기가 당시에 페북에서 공유가 엄청 많이 되었던 기억이 있다. 확실히 취업/신입 개발자 관련 주제는 엄청 핫한가 보다. 다음에 회사블로그에 또 글을 쓴다면 그건 꼭 기술에 대한 적용기 이야기를 쓰고 싶다. 그동안 너무 커리어적인 글만 양산한거 아닌가 싶어서 내가 과연 기술적으로 성장하였는가? 라는 고민이 있었기 때문이다.🙌 (근데 요즘 공부를 안함…흠…)

2-3. 외부 인터뷰

상반기에 이곳저곳에서 인터뷰가 생각보다 많이 들어왔었다. 다 비슷비슷하게 취업기 관련 커리어 글이었는데, 학교에서도 들어오고 대학 잡지, 기술 뉴스레터 등 다양한 곳에서 나의 이야기를 담아주셨다.

http://inews.ewha.ac.kr/news/articleView.html?idxno=32531

 

선배들의 따끈따끈 ‘취뽀’ 성공담 – 카카오(Kakao) 개발자 편 - 이대학보

코로나19의 여파로 취업 시장이 얼어붙었다. 청년층의 실업자 수는 2017년 이후 최고치를 기록했다. 이런 취업난에도 최근 다양한 분야에 취뽀(취업뽀개기)한 이화인들이 있다. 본지는 이들의 이

inews.ewha.ac.kr

https://maily.so/1step/posts/4a440c

 

📑 IT 대기업 입사는 공채만이 답?

프로합격러가 들려주는 주니어 상시채용 취준 꿀팁

maily.so

http://www.campl.co.kr/contents/content_read.asp?idx=10483

 

“하고 싶은 건 다 해보고, 끊임없이 배우는 것이 중요해요” 카카오톡 김민정

캠퍼스플러스

campl.co.kr

 

3. 스터디

신입일 때는 이것저것 막 공부해야하는거 아닌가 싶어서 상반기 하반기 모두 채찍질 하면서 스터디를 생각보다 많이 했던 것 같다. 그런데 지금 되돌아보면 이것저것 일을 벌리면서 스터디를 하는 것 보다 정말 관심있는 것 몇가지만 집중해서 하면 좋았을텐데라는 아쉬움이 있다. 현재는 스터디를 이것저것 했지만, 그 시간을 헛으로 보낸 것 같다는 느낌이 들어서 전부다 그만두고 쉬고있는 상황이다. 내가 공부하고 싶을 때 하고, 스터디를 시작한다면 상황적으로 여유가 될 때 하나만 집중해서 하고싶다.

3-1. Next Step Effective Kotlin (2월 ~ 3월)

혼자서 코틀린 인액션 책을 읽었는데 챕터 5까지 정도밖에 안읽고 실제로 쓸 일이 없으니까 코틀린을 적당히 자바 문법이랑 호환되는 부분만 사용할 줄 알지, 실제 코틀린 문법을 알고 적절하게 사용하고있다는 느낌이 안들었다. 그래서 자바봄에서, 우아한 프리코스에서 했던대로 코틀린을 써보면 좀 더 익숙해지지 않을까 생각해서 넥스트스텝 교육을 신청했다. 리뷰를 받으면서 내가 몰랐던 코틀린 문법이나 패턴들을 알게된 건 좋았으나, 퇴근하고 미션을 수행하는게 정말 쉽지않더라.. 그래서 미션 4개중에 2~3개 정도까지만하고 완수는 못했다. 그래도 리뷰 받은 내용들이 모두 도움이되는 내용이었고, 감사했다. 따로 다시 공부해야하는데… 이번에 코틀린 관련 업무를 시작하면서 좀 더 봐야겠다.
https://edu.nextstep.camp/c/Z9QeJlCi/

 

이펙티브 코틀린(Effective Kotlin) with TDD, Refactoring, Clean Code

edu.nextstep.camp


3-2. 자바봄

대학교 3학년때부터 하던 스터디이다. 사실 이 스터디 덕분에 자바를 좀더 집중적으로 공부할 수 있었고, 취업할 때 덕이 컸다고 생각한다. 모든 인원이 전부 취업에 성공하면서 배민2 / 네이버 / 카카오 / 마리트 이렇게 모두 직장을 갖게되었는데, 그럼에도 나름 꾸준히 올해도 책을 조금씩 읽어나가면서 서로 질문하고 답변하고 찾아보는 형식의 스터디를 계속해서 진행했다. 자바봄에서 올해 했던 책 리스트에 대한 건 아래 링크에서 볼 수 있는데, 어느 순간 이 리포가 스타 200을 넘어섰다!! 다들 열심히 정리하고 관리하는 레포지토리라서 많은 사람들이 참고한다는 점에 되게 뿌듯하고 신기해했던 기억이 있다.
https://github.com/Java-Bom/ReadingRecord

 

GitHub - Java-Bom/ReadingRecord: 📚 책 읽고 정리하기 📚

📚 책 읽고 정리하기 📚. Contribute to Java-Bom/ReadingRecord development by creating an account on GitHub.

github.com

자바봄에서는 총 3가지 책을 했는데, 각 책에 대한 느낌은 아래와 같다. (괄호에 들어간 이름으로 issue 라벨을 관리중이다.)

  • 토비의 스프링 (Spring of Toby) : 확실히 스프링을 하는 개발자라면 한번은 읽어 봐야하는 책이었다. 대충 읽고 넘어간 부분도 있고, 집중해서 읽고 넘어간 부분도 있었는데, 이 책을 다시본다면 그때는 스프링 내부 코드와 함께 봐야겠다는 생각이 들었다. 다만 이번에 책을 읽을 때는 호흡을 길게 가져가면서 읽어서 이전에 읽었던 내용도 까먹고 넘어가고 했던게 종종 있었다. 앞으로는 두꺼운 책이라도 호흡을 짧게 가져가면서 읽고싶다. (쉽지않겠지만..)
  • 쿠버네티스 입문 (Kubernetes introduction) : 음 개인적으로 재미없었다. 이책 읽은 것중에 쿠버네티스 구조 부분 좀더 보고싶어서 쿠버네티스 인액션이랑 공식문서 함께 보면서 혼자 정리한 부분은 재밌었는데, 그 외에는 yml 다 따라치면서 어떤 기능이 있다 소개하는 거였기 때문이다. 나는 아무래도 이미 쿠버네티스를 사용해본적이 있다보니 yml 작성하면서 각 오브젝트의 기능을 소개하는 부분은 이미 알고있는 내용이라 그랬을수도 있다. 그래서 쿠버네티스 입문 책보다는 이후에 읽은 쿠버네티스 인액션 책이 좀 더 재밌었다. 그치만 쿠버네티스를 배워본적이 없어서 핸즈온랩처럼 따라하면서 가고싶다면 이책도 나쁘지 않은듯?
  • 스프링 배치 완벽 가이드 (Definitive Guide to Spring Batch) : 이 책을 읽으면 좀 더 스프링 배치를 잘 짤 수 있지 않을까 라는 기대로 시작했는데, 정작 소득이었던건 배치 repository 구조를 좀 보게된 것 정도인 것 같다. 내가 리딩을 하지 않으면 적당히 책을 읽고 넘어갔었기 때문이다. (이때 쯤부터 책읽는걸 조금 힘들어했었다.) 배치 인터페이스를 소개하면서 각종 구현체들에 대한 설명까지 간략하게 나와있는데, 이런게 있구나 하고 알고 넘어가고 사용할 때 직접 써보지 않는다면 잘 와닿지 않는다는 느낌이 있어서 그랬던 것 같다. 역시 책만 읽기보다는 직접 코딩 해보면서 감을 잡아보는걸 좋아하는 타입이다. 그러나 사용하고 싶은 구현체가 있다면 이 책으로 간단히 개요를 보고, 스프링 배치 공식문서를 본다면 빠르게 파악하고 넘어갈 수 있을것 같다.

지금은 자바봄 스터디를 멈춘 상태이다. 다들 일이 바쁘고, 의욕이 안살아서 조금 휴식기를 가지기로했다.

3-3. 설계 스터디 (8월 ~ 11월)

  • 가상 면접 사례로 배우는 대규모 시스템 설계 기초

GDSC로 알게된 정동오빠가 주도해서 하게된 스터디이다. 아예 인연이 없는 새로운 개발자 분들과 스터디를 하게 되었고, 배민 / 토스 / AWS / 카카오 조합으로 책을 봤다. 다양한 회사의 사람들이랑 이 책을 읽었을 때 좋았던 점은 각 회사 본인의 도메인에서 봤던 설계에 대해서, 실제로 어떻게 사용하고있는지 경험담을 들을 수 있던게 좋았다. 이 책 내용이 조금 대략적으로 간단하게 설계에 대한 이야기를 하고있는데, 책의 내용으로는 가벼울 수 있는 내용을 각 구성원들의 경험과 지식으로 채우면서 생각보다 재밌었다. 이 스터디를 하면서 위에 말했던 애플리케이션 코드의 중요성 뿐만아니라 설계에 대한부분도 좀더 보는 개발자가 되어야하지 않을까? 라는 생각을 하게되었다.

정동오빠가 설계 관련해서 공부하기 좋은 아티클 링크나, 유튜브 영상 링크를 보내줬는데, 올해중에 맘잡고 전부 싹 훑어보고 블로그에 하나씩 업로드하는게 목표이다. 이 책을 읽은 것 만으로는 조금 빈약한 부분이 있었기 때문이다. 그리고 이 책을 읽으면서 면접에서 서버당 TPS 이런 수치들은 어떻게 추측할 수 있는지 우리파트 시니어 개발자 분께 여쭤봤는데 경험의 영역이라고 한다. 그래서 파트에서 사용하고있는 서버의 대수나 그에 대비하는 TPS, 구조를 좀 더 기억하거나, 정리하는게 중요하다는 인사이트를 받을 수 있었다. 실제로 파트에서 장애나, 연말대응같은 빅 이벤트에서의 회고를 진행하면서 여러 수치적인 지표를 한번 더 짚고 넘어가고 있는데, 할 때마다 되게 좋긴하다.


3-4. 책 스터디 (1월 ~11월)

GDSC로 알게된 원범오빠가 본인의 대학 친구들하고 하고있는 스터디이다. 왜하게된건지 기억은 안나는데, 이 스터디는 자바봄과는 다르게 엄청나게 짧은 주기로 책을 읽고 리뷰한다. 책 한권을 잡으면 일주일에 2번 모이고, 각 모일때마다 한챕터씩 읽어야한다 (약 60~70페이지 분량). 기존에 책을 널널하게 읽는데에 익숙해져있어서, 하루에 한 챕터 읽기도 힘들어했던 내가 (소설아니면 책읽는거 진짜 싫어한다 원래). 그냥 하루에 열심히 한 챕터 정도는 읽어보자하면서 변화하게 되었다. 그러다보니 생각보다 많은 책을 읽을 수 있다는 점은 좋았지만, 집중해서 보고싶은 부분을 시간에 쫓겨서 넘어간 적도 많았었다.

  • 마이크로 서비스 패턴 : 가장 맨 처음에 읽었던 책이라서 기억이 잘 안난다ㅠㅠ 그런데 되게 여러가지 패턴이나 도식도를 보면서 최대한 내가 알고있는 예제들과 적용시키면서 이해하려고 했던 기억이 난다. 아무래도 파트에서 이미 적용하고 있는 부분도 있고, 아닌 부분도 있어서 이런 이해 방식이 가능했던 것 같다. 가장 어려웠던 부분은 아무래도 분산 트랜잭션 부분이었다.
  • DDD Start : DDD를 모르는 스터디 원들도 계셨기에 앞에있는 MSA 책 이전에 이 책을 읽으면 좋았겠다 싶었다. 좋았던건 내가 그동안 객체지향이라고 부르던 것들이 애그리거트 / 도메인 / 도메인 모델 등등 특정 단어로 명명되고 있다는 걸 알게되었다는 점이었다. 이 책을 읽기는 했지만 나는 DDD를 하고있는가? 라고 제대로 알고 사용하고 있는 것 같지는 않다고 대답할 것 같다. 위에서 말한 용어들을 의식적로 인지하고 구현하고 있지 않기 때문이다. 책 자체는 엄청 쉽게 설명이 되어있어서 말 그대로 DDD를 시작하는 사람이 읽으면 좋을 것 같다.
  • 리팩터링 (2판 사진을 올렸으나 자바로 되어있는 1판을 읽었다.) : 파트에서 리팩터링 과제를 맡고있어서 이 책을 읽으면 엄청 도움이 되지 않을까? 기대를 하고 봤는데 사실 조금 실망인 부분도 있었다. 여기서 소개하는 일부 패턴 및 전략들이 intellij ide로 대체가 가능 한 것들이 있었는데, 옛날 책이라 어쩔 수 없는 것 같다. 그러나 개발자 교양서라고 부르는건 인정.
  • 쿠버네티스인액션 : 쿠버네티스 yml을 짜기는 하지만, 좀더 깊게, 혹은 구체적으로 알지 못했던 부분을 하나씩 추가하는 느낌이라 좋았었다. 그러나 뒷부분으로 갈 수록 사용을 안해본 오브젝트이거나 하는 경우에는 이해나 응용을 떠오르기 어려웠었다. 근데 etcd, api 서버, kubelet 등 쿠버네티스 구조와 관련된 컴포넌트들을 이 책을 통해 열심히 봤었다.
  • 데이터중심 애플리케이션 설계 : 아 진짜 어려웠다. 이 책이랑 대규모 시스템설계 기초 책을 함께 봤었는데, 그러다보니 더더욱 분산 시스템 설계의 중요성에 대해서 공부해봐야겠다고 생각이 들었던 때가 이 때쯤이었다. 아근데 진짜 어렵다. 책의 모든 내용이 나에게 도움이 되진 않았고, 한 앞에서부터 2/3 지점까지가 굉장히 좋았다. 뒷부분은 하둡, 스파크 등 데이터 분석에 대한 내용이었는데, 아무래도 관심이 가질 않았기 때문이다.

이 스터디역시 마무리했다. 올해 스터디를 전부다 책 스터디만 하면서 스터디 시간으로 인해 책만 읽고 실제 코드로 구현을 해보거나 더 찾아본다거나 하는 일이 없었어서 조금 현타가 왔었다. 그래서 지금은 전부다 그만둔 상태! 리프레시 하고 다시 원하는 공부를 하는걸로 하자.

3-5. 사내 스터디

  • redis 스터디 : 사내 스터디로 파트 대부분의 분들이 참여했었는데, 여기에서도 redis-cluster를 k8s helm과 함께 사용하는 방법에 대한 발표를 내부적으로 진행했었다. 이때 bitnami 레포를 분석하면서 분석한 내용을 바탕으로 내부적으로 어떤 명령어들이 실행되어서 이런 설정들이 가능한지를 발표했었다. 그러나 현재 파트에서 진행하는 redis-cluster 전환 작업은 참여하고있지는 않다. 전환 작업을 하고계시는 분들의 진행과정 발표를 들었었는데, 공부한 내용을 직접 적용하기 위해 많은 것을 공부하고 설정값 확인부터 모니터링까지 모든 것을 염두하기 쉽지않을텐데 정말 대단하시다고 생각했다.
  • UNIX 고급프로그래밍 : 내가 입사하기 9개월전에 입사하신 주니어 개발자 분과 둘이서 하고있다. 아무래도 우리 파트 코드중에 C로 되어있는 코드가 있어서 이 책을 읽으면 조금 진입장벽이 낮아지진 않을까?! 기대를하면서 이책을 시작하게 되었는데. 엄.. 어렵다. unix에서 사용하는 함수나 용법에 대한 설명이 있어서 와닿기 어려울 때도 있고, 어쩔때는 운영체제 수업, 컴퓨터 구조 수업을 잘 들어둘껄 생각도 든다. 그래도 회사 분이랑 함께 시작 한 스터디니까, 어찌저찌 끝마추지 않을까


3-6. 외에 개인적으로 본 책

  • 네티 인액션 : 이전에 내가 검증형계약직에서 정규직으로 전환될 때 했던 과제가 네티가 필요해서 읽었었다. 그런데 인턴분이 진행하신 프로젝트 역시 네티를 사용해서 코드리뷰와 적절한 가이드를 위해 한번 더 이 책을 읽었다. 한번 읽으면 슈루룩 읽는데 뭔가 응용해서 짜보려하니 쉽지 않았다.
  • 코틀린 인액션 : 읽다가 말았다ㅠ 책을 읽는거에 그치지 않고 책에 있는 예제를 하나하나 따라해보고 실행해보아야 온전한 내 것이 될 것 같아서 눈으로 읽기를 그만두었으나. 다른 책 스터디에 밀려서 우선순위가 후순위가 되었다.
  • redis 운영 관리 : 간단하게 읽기 좋은데 진짜 꿀팁만 담겨져 있다. 100페이지도 안되서 더 좋다. 간략 정리글은 내 블로그에 있다 : https://jyami.tistory.com/141
  • 프로그래머의 뇌 : 요즘 읽고있다. 개발 책만 읽는게 힘들어서 개발 인문학(?) 느낌으로. 근데 읽다보니 내 뇌가 마치 컴퓨터처럼 되어있나라는 생각이 든다. 사람의 기억을 램과 디스크와 CPU로 비유해서 서술한다.

 

4. 이화여대

4-1. 토익과 졸업

졸업했다!!! 드디어!! 토익 졸업 자격 요건 때문에 졸업을 못할 뻔 했는데 이것도 통과했다!!! 사실 원래대로라면 20년 말에 토익을 보고 21년 2월 졸업을해서 바로 칼졸업을 하는게 베스트였는데, 20년 말에 카카오 정규직 전환 인터뷰를 준비를 하면서 학교 졸업요건들을 잘 챙기지 못했었다. 그래서 유예하고 21년 8월 졸업을 노렸었는데.. 이것 역시 까먹고 얼레벌레 살다가 한 6월쯤 되서 생각나서 토익 점수 마감일 계산해서 공부를 딱 2주 할 수 있는 시간이 있었다.
원래 20년 말에 노베이스로 토익을 그냥 공부 안한 상태로 봤을 때 565점이었다. 그런데 졸업을 위해 700점을 2주만에 맞춰야하는 상황이었다..!! 미리 공부좀 해두었으면 좋았을걸, 나중에 나중에 미루다가 2주동안 공부해서 135점을 올려야하는 상황이었다. 그래서 당시에는 9시 출근 6시나 7시 퇴근하고 밥 먹고 10시 11시까지는 토익공부에 집중하고 힐링을 위해 롤 1~2시간 정도 하는 삶을 살았었다. 그렇게 해서 결국 나온 결과는 710점. 영어공부 목적이 아니라 정말 졸업만을 생각하고 달렸었기 때문에, 700점만 넘으면 되서 더도말고 덜도 말고 딱 2주동안 해서 700점 넘었다는게 너무 좋았다 (더 공부했으면 억울할 뻔)

그렇게 진짜로 졸업했다!! 우리학교 기준 평점 4.3 만점 3.85 학점으로 졸업을 할 수 있었다. 학점에 대한 비결은,, 나는 전공을 좋아해서 전공 학점은 거의 A대 였다. 그래서 전공을 늘리고 교양을 줄였는데, 교양은 대부분 패논패로 처리해서 최대한 전공학점이 반영이 되게 학점관리를 했었다. 그래서 전공학점을 기준으로하면 4.3 만점 4.05 학점이다. 나름 학교 생활을 성실하게 했다는 지표이기 때문에 이력서에도 열심히 넣었었다. (아.. 이력서 업뎃도 해야하는데..)

4-2. 학관 리모델링 재건축기금 기부

작년 2월 학관 리모델린 재건축기금 기부를 받는다고해서 이제 막 월급 따박따박 받는 사회초년생이 된 기념으로 바로 300만원 기부를 했었다. 후원자 기념판 이름에 등재된다고 해서 매우 기대가 된다. 학교에 기부해서 내 이름이 학교 어딘가에 걸려있는게 나름의 버킷리스트였는데, 당시 기회가 있을 때 잡자! 생각해서 일단 신청은 CMS로 했는데.. 다음날에 대외협력처에 바로 전화해서 그냥 일시불로 입금했던 기억이 있다. 지금처럼 당당하게 나를위한 삶을 살 수 있게 된게 우리학교를 다닌게 영향이 분명히 있고 학교에 애정이 있기 때문에 꼭 해보고 싶었다.

5. 일상

5-1. 운전 면허

5월인가 운전 면허를 땄다. 그동안 돈이 없다는 핑계로 못했던 거였는데, 직장인이 되고 일상, 수익이 안정되니까 이제 한번 해볼까? 하고 도전하게 되었다. 필기 기능 도로주행 모두 실패없이 한번에 통과했다!!! 그런데 지금 사는 곳이 교통이 좋아서 딱히 자차가 필요가 없어서 그런데 정작 차는 없어서 장롱면허가 될 예정이다ㅋㅋ 캐스퍼가 막 출시됐을때 무리해서라도 차를 살까 하는 뽐뿌가 엄청 왔었는데, 그래도 정작 써먹을 데를 생각해보니 없는 것같아서 한 30살에 가까워 질 때쯤 사야지 생각했다.
아 면허를 따면서 웃겼던 기억은..ㅋㅋㅋ 나는 길치인데, 도로주행 길이 진짜 너무 안외워져서 그냥 길이나 내가 해야하는 행동을 종이에 적어서 다 외워갔다. 운전학원 유튜브에 도로주행 연습하는 영상이 있었는데, 그 영상으로 보면서 "신한은행 간판이 보이면 우측 깜박이" > "이후 사거리에서 우회전 (핸들은 빠르게 한바퀴)" 이런식으로... 친구들이 듣고 경악했다. 나중에 실제로 운전해야 할 때는 연수 제대로 받고 해야지..

5-2. 머리색 근황

그동안 살면서 탈색을 한번도 안했었다. 다들 염색한번 해보는 시기인 고3 수능 끝나고에는 “한국사람이면 그냥 검정머리가 제일 이쁘지” 이렇게 생각하고 머리를 해도 파마만 했었는데ㅋㅋㅋ 그냥 문뜩 올해 5월 지금 20대 초반일때 탈색 한번도 안하면 평생에 앞으로 할 일 없지 않을까? 하고 질렀다 그러고 지금까지 유지중이다. 탈색하고 헤어제품도 엄청 많이사고 발열현상이나 등등 미용사 쌤한테 들으면서 알게 된게 많은데, 확실히 머리색을 바꿀 때 기분전환이 잘 되었다. 내 머리가 발열현상이 잘일어나서 탈색을 3번했는데도 백금발 탈색은 어려워서ㅠ 애쉬그레이 같은 색은 제대로 색이 안나와서 주로 붉은 계열로 염색을 한다. 근데 이게 탈색을 하다보니 머리색이 옅어지는 것 같기도..? 앞으로 한 일년정도 더 유지해볼까 고민중이다.

인스타에 #머리색근황 이렇게 하고 올려서 내사진만 뜬다.

5-3. 운동

재택근무를 하다가 어느순간 너무 오래 앉아있었는지 허리가 아파서 이제 슬슬 운동을 해야하나? 생각이 들었다. 재택근무를 위주로하니까 처음에는 의자를 시디즈로 바꾸는걸로 시작했는데, 그거와는 별개로 자취도하다보니 식습관이나 건강이 급 걱정이되었다. 작년 여름부터 계속 은님이 “조져지기 전에 운동하세요” 했었는데, 이러다가 조져지고 나서 운동하려나 싶어서 최대한 빨리 시작하자 하고 PT를 시작했다. PT를 하면서 아쉬웠던게 선생님이 많이 바뀌었던건데ㅠ 지금 하고있는 피티까지 다하면 40회정도되는데 선생님 변경만 3번이 있었다. 처음에 만났던 선생님이 잘맞아서 운동에도 재미붙이고 개인운동도 나가고하면서 20회를 결제했는데, 그 선생님이 퇴사를 하게되어서 7회는 중간에 다른 선생님이랑 하면서 또 적응하고, 새로운 헬스장으로 옮기면서 그 헬스장에서 다른 선생님이랑 지금 20회를 진행하고있다.
처음 받았던 쌤이랑 했을 때 매일매일 피티 받은 내용을 안잊으려고 쌤이 했던 조언들을 빼곡히 적어놨었다. 지금은 strong 어플을 사용하고있다.

확실히 지금 근력이 처음보다는 나아지고 관심이 많아지고있다는걸 느끼고있긴한데, 처음받았던 선생님이랑 쭉했으면 좋았겠다 싶어서 너무 아쉽다. 처음에 맨몸스쿼트만 하던내가 지금 랙에서 40KG 바벨들고 스쿼트 하고있다는거 보시면 와 처음에는 이랬는데, 지금은 이렇네요 이러면서 같이 뿌듯해하고 좋아해주셨을텐데 싶어서 말이다ㅠ. 그래도 처음 만났던 그 선생님 덕분에 뭔가 목표를 하나씩 깨는 느낌이 좋았었고, 주변에 재연언니나 은님 등등 운동에 관심많은 사람들이랑 얘기하면서 더 알아보다보니까 운동하는게 생각보다 재밌다. 원래는 슬라임, 달팽이 소리하면서 운동 귀찮아아 이러고 다녔는데 반년만에 생각이 바뀌다니 신기하다.
운동은 주에 3~4회정도 가고있다. 피티 받으면서 좀 더 스트레칭에 신경쓰려고 폼롤러 마사지도 많이 해주고있다. 개발자다보니 확실히 목 어깨 겨드랑이쪽 근육이 많이 뭉쳐서 업무 중간중간 마사지볼이나 폼롤러로 근육이 뭉치지 않게하려고 조금씩 해주고있다. 이렇게 해주면 좋은게 업무할 때도 리프레쉬 될 때도 있고, 상체운동 할 때 근육이 안뭉쳐있는 상태로 하면 덜 아프긴하더라. 여튼 피티를 시작으로 여러 운동에 관심이 갔고, 실제로 다른 운동들에도 좀 더 근력 더 키우고 해보고싶다라는 마음도 많이든다. 작년과 비교하면 내 인생에서 운동이 정말 큰 변화였던 것 같다.


이렇게 회고 끝!! GDSC 리드했던 멤버들이랑 매년 회고 릴레이를 하고있는데, 귀찮아 하면서도 막상 쓰면 엄청 길게 일년동안의 내 생각들을 주저리주저리 적고있는 것 같다. 1년치 일기장이라서 당연히 그럴 수 있지.

마무리는 대충 24살의 내사진

다들 회고록에 내년 목표를 적는데, 적당히 살자. 적당히 현생 챙기면서 살다보면 해피한 미래가 있겠지 👀 장기 계획세우면서 사는 타입이 아니라😳 2022년에도 활기차게 에너지 넘치는 쟈미로 살자 2021년 고생 많았다 안녕🙌🙌

Before I start this retrospective, “once again this year,” there were no issues with the KakaoTalk messaging server at year-end!!! Since I was the one directly handling the year-end response this time, I wanted to document the year-end experience too, which is why I ended up delaying this retrospective.

Working from home — so comfy~

I joined the company in September 2020 and started doing real hands-on work from December, and now it's 2022!! I can't believe I'm in my 3rd year?!! It's so surprising lol. I've really only been doing actual work for about 1 year and 1 month, yet I'm a 3rd-year developer.. That's amazing all over again.
So 2021 was a time for me to adapt as a working developer after joining the company, and since development became my profession, it was also a time to try things outside of coding to find a balance between work and life. With that, let's dive into the retrospective!

This retrospective feels like writing a year's worth of diary entries, so the readability isn't great.

 

1. Work

1-1. Treating work like homework?

I wrote daily work logs and tackled company tasks one by one, and comparing the first and second halves of the year, I can definitely feel a big difference.
In the first half, just deploying the dev version of the regular chat was thrilling and nerve-wracking, but by the second half, I was scaling up servers and deploying that same regular chat to the real/production version, tweaking ansible configs here and there for deployment settings, and eventually even handling the year-end response. Is this what it means to gain experience..?😳

My densely written work logs (contents are private)

There was definitely a noticeable difference in how I approached work between the first and second halves. In the first half, I kept wondering, "Am I really good enough to take on such a big task? I don't know much — should I really be taking on messaging work?" I hesitated and only worked on things that senior developers assigned to me. But in the second half, compared to the first, I started proactively seeking out work. I picked up a few issues that had been sitting around in our team, got closer with the client-side developers and actively communicated with them to provide messaging logic guidelines, and when I found something in the code that I wanted to fix, I'd create an issue and work on it myself. Early in the first half, a senior on my team told me, "Jyami, you do your work like it's homework." When I first heard this, I thought nothing of it — like, "Well, I've always done my homework well and with high quality. Does that mean I'm very meticulous?" But it kept bugging me, so I asked Eun about it and realized it meant I needed to be more proactive with my work.

1-2. What makes a good developer?

Still, I feel like I'm only picking up small, minor issues for now. There was a senior developer who volunteered to lead the C-to-Java porting effort, and I wonder if someday I'll be the one raising big issues like that too. Seeing things like this, I really feel there are so many people to learn from in the messaging team. But because of that, my thoughts on "what kind of developer should I be" have shifted since before and after joining the company. Before, I naturally thought since I love Java and Spring, I should dig deep into them and apply clean code, DDD, and all that stuff, and that once I started working, if I dug into Spring's internals, I'd become a good developer. But after joining, I've been realizing that knowing how to design better server architectures and properly use various components is also extremely important.

I think it's because when outages happen or when planning for new components, what matters more than how you write the code is the practical perspective — how to improve performance, how to handle edge cases, and so on. So before, when it came to using Redis, I used to think about which methods to use with spring-data-redis to write good code and good test code. But now, working in the messaging team, I've realized you need to think about Redis itself first. I've learned from experience that understanding Redis's data structures, failover policies, eviction policies, backup strategies, and so on is more important. So my thinking is shifting toward the idea that rather than being good at a particular language, a developer who can solve problems well when issues arise is probably the best to work with. I shared these thoughts with my team lead several times, and they advised me that everyone walks a different path and there's no single right answer for what makes a good developer.

1-3. Intern mentor / New hire code reviewer

Starting in the second half, interns and new hires began joining under me. I still feel like a newbie myself.. but I mentored an intern and am now responsible for code reviews of new hires who came in through the regular recruitment process. Honestly, I was a bit worried at first since some of them were older than me, but it turned out fine.✌️ After all, the new hire assignments were within the scope of what I knew, and anything I didn't know, I could just study up on.
Although I don't have a ton of experience myself, while mentoring the intern, I figured out what kind of person the company wants to hire as a new developer and guided them accordingly.

더보기
Many new developers, when working on their assignments, really want to perform like experienced developers — they want to show they can handle everything on their own without asking. So they dig deep into every requirement spec the mentor gives them, and as a result, they quantitatively meet the requirements. But in doing so, what's easy to miss is the "why" — "Why did you decide to develop it this way? Why did you think this should be the output?" Let's say there's a requirement for server performance testing. The new hire looks into it, gets a recommendation from their mentor to use a tool like ngrinder, confirms the server TPS looks good, and submits a results report. But then the final interviewer asks things like: "Why did you choose these comparison groups for the performance test?", "If N users access the server, this TPS might not be enough — do you have other metrics? / How could you improve it?" and so on. They value the logical reasoning behind your decisions — why you wrote the code this way, why you chose this tool, why the server is structured this way.

But I think it's honestly not easy for a mentor to anticipate all these questions and prep the mentee for each one. So ideally, the mentee should research various references on their own, compare the pros and cons of this tool versus others, ask the mentor for advice on how things are done in the team they're currently working in, and even if they don't implement it in the intern assignment, come prepared knowing about expansion plans and current shortcomings. The company seems to want to see that kind of passion and growth potential. Writing this out, I realize it's really not easy…😳


Working closely alongside the intern, I learned a lot, and I did my best to help them pass — advising them on everything from code to decision-making. But looking back, I think my enthusiasm might have been even greater than the intern's.. haha. That's when I most vividly felt that collaboration and managing people isn't easy, and I think I was going through some growing pains as a developer during that period. I started thinking about how, as I'll eventually become a senior to many people, what's the best way to give advice that's actually helpful. So these days, while doing code reviews for the new hires, I first share books and articles that are good to read at the code level and drop them in the PR🙌 (I tend to give pretty tough reviews.. so hang in there, my reviewees..heh)

But then again, writing all this out, it is tough ~_~ I'm originally the type who lives without plans (a hardcore ESTP), so I figure if I just do my best in the present, I'll probably turn out to be a pretty decent person in the future too.

2. Activities outside of development

This year, I cut back on community activities. Since I was the GDSC EWHA lead, one of the questions I got during my Kakao interview was, "Do you enjoy participating in developer communities?" And I stayed true to my answer: "During my 3-2 semester as lead, I felt proud of contributing to many people and building new experience. But that semester, my growth as a developer stalled. Between inviting speakers and preparing events, I didn't have enough time to study development, and my skills were about the same as in my 3-1 semester, which was frustrating. So if I join the company, I plan to step back from developer communities early on to focus on studying and adapting to work." I followed through on that. I've always found it easier to commit to NOT doing something rather than committing to doing something😝

But looking back, I actually ended up doing this and that..? Maybe I just can't help being an attention-seeker.

2-1. YouTube

My goal was to post on YouTube once a month. I wanted to focus my blog on technical content, but that didn't go well. Oh well, what can you do — at least I managed this much while living my life!! Hmm, as of January 16, 2022, my YouTube channel has 2,813 subscribers. It's amazing that people enjoy it even though I only upload casual VLOG videos. Meanwhile, I personally only watch YouTube for killing time and relaxation — variety shows (The Genius, Crime Scene, Workman, Civilization Express), gaming channels (Paka, Ssal Tube, Queen Lux) — so I'm a YouTuber who doesn't watch vlogs..! (proudly)🙄
People at work ask me about YouTube revenue, and the answer is none. To earn YouTube revenue, you need over 1,000 subscribers and 4,000+ hours of watch time, but since I don't upload many videos, I don't have enough watch time for ad revenue. Oh, but in the first half of the year, I got sponsorship and ad offers from Likelion and Mars Sleep, so I filmed some sponsored content. But making videos with sponsorships felt like work, which took the fun out of uploading YouTube videos, so I've been declining all sponsorships since then. Unless it's a dev-related product, I'll probably keep turning down cosmetics and other miscellaneous product requests lol (though I do think electronics or pouches could actually be useful🤔)

When I look at YouTube Studio analytics, it shows strategy insights, and surprisingly, "Code With Me" videos get a lot of views. So I kind of want to film them with nice interior decor and pretty lighting like other Code With Me channels..! But ugh, interior decorating is really hard for me;;; My decorating attempts always lack that aesthetic vibe. I'll do more research😵‍💫 As for the viewer demographic, since it's mostly developers watching, the age range is 18–34 and the gender ratio is 2:1 (male:female). It seems like a lot of people find my channel through Pangyo Walker (ah, I genuinely love this YouTuber — their videos are so fun), Jocoding, and Nomad Coders.

2-2. Blog

As for the blog, I actually spent more months reading books this year, and while I did take notes, lately I've been thinking "instead of re-reading my notes, I'd rather just re-read the book," so I've only saved them on Git and haven't organized them into blog posts. As a result, the number of posts on my blog dropped significantly. So my most popular blog posts are mostly retrospectives and job-landing stories,, hmm — a developer blog where retrospectives are more popular than technical posts 🙄 is this right? While working with my team, there are several topics I want to write about like ansible and other things, but ah, writing blog posts and editing YouTube videos on weekends is really not easy when weekends are so precious for office workers…😘 Let's try to make some time in 2022.

Oh wait, now that I think about it, I didn't write on my own blog — I wrote on the company blog lol. It feels pretty great to have my article on the Kakao Tech Blog.. It was something I'd always wanted to do, and a related team actually reached out to me first, haha. The posts are below.

https://tech.kakao.com/2021/05/24/jyami/

 

뉴크루의 카카오 백엔드 개발자 이야기

안녕하세요, 톡플랫폼개발팀 톡메시징파트의 신입 개발자 쟈미(jyami)입니다. 저는 자바, 코틀린을 좋아하는 백엔드 개발자이고, 카카오에 들어온 지는 약 반 년이 되어갑니다. 제가 카카오에 입

tech.kakao.com


https://tech.kakao.com/2021/10/25/grace-hopper-celebration/

 

Grace Hopper Celebration 참가기

카카오에서는 크루의 주도적인 성장과 역량 향상을 위해 글로벌한 인사이트 확대를 경험할 수 있도록 해외 컨퍼런스 참관 참여를 지원하고 있습니다. 안녕하세요, 톡플랫폼개발1팀의 jyami입니

tech.kakao.com


The "New Crew's Kakao Backend Developer Story" post above got shared a ton on Facebook at the time. Career/new developer topics are definitely super popular. If I write on the company blog again next time, I really want it to be about applying a specific technology. I'd been feeling like I've only been producing career-related content, which made me wonder, "Have I actually grown technically?"🙌 (But lately I haven't been studying… hmm…)

2-3. External interviews

In the first half, I got more interview requests from various places than I expected. They were all pretty similar — career-related stories about landing a job. Requests came from my university, college magazines, tech newsletters, and more, all featuring my story.

http://inews.ewha.ac.kr/news/articleView.html?idxno=32531

 

선배들의 따끈따끈 ‘취뽀’ 성공담 – 카카오(Kakao) 개발자 편 - 이대학보

코로나19의 여파로 취업 시장이 얼어붙었다. 청년층의 실업자 수는 2017년 이후 최고치를 기록했다. 이런 취업난에도 최근 다양한 분야에 취뽀(취업뽀개기)한 이화인들이 있다. 본지는 이들의 이

inews.ewha.ac.kr

https://maily.so/1step/posts/4a440c

 

📑 IT 대기업 입사는 공채만이 답?

프로합격러가 들려주는 주니어 상시채용 취준 꿀팁

maily.so

http://www.campl.co.kr/contents/content_read.asp?idx=10483

 

“하고 싶은 건 다 해보고, 끊임없이 배우는 것이 중요해요” 카카오톡 김민정

캠퍼스플러스

campl.co.kr

 

3. Study Groups

When I was a newbie, I felt like I had to study everything under the sun, so I pushed myself pretty hard in both the first and second halves of the year and ended up doing way more study groups than I expected. But looking back now, I kind of regret spreading myself so thin instead of just focusing deeply on a few things I was truly interested in. I've done all sorts of study groups by now, but it started feeling like I was wasting that time, so I quit everything and I'm currently taking a break. I want to study when I actually feel like it, and if I start a study group again, I want to focus on just one when I actually have the bandwidth for it.

3-1. Next Step Effective Kotlin (Feb – Mar)

I had been reading Kotlin in Action on my own but only got through about chapter 5, and since I never really had a chance to use it in practice, I only knew the parts of Kotlin that were compatible with Java syntax — I didn't feel like I truly understood Kotlin's own idioms and was using them properly. So I thought maybe if I tried writing Kotlin the way I did at Java-Bom and the Woowa Precourse, I'd get more comfortable with it, and signed up for the Next Step course. It was great to learn about Kotlin syntax and patterns I didn't know through code reviews, but doing the missions after work was really tough... So I only completed about 2–3 out of 4 missions and couldn't finish them all. Still, every piece of review feedback was genuinely helpful and I was grateful. I need to study it again separately… now that I'm starting Kotlin-related work, I'll have to dig deeper.
https://edu.nextstep.camp/c/Z9QeJlCi/

 

이펙티브 코틀린(Effective Kotlin) with TDD, Refactoring, Clean Code

edu.nextstep.camp


3-2. Java-Bom

This is a study group I've been part of since my junior year of college. Honestly, this group is a big reason I was able to study Java more intensively, and I think it helped a lot when I was job hunting. Every single member ended up landing a job — Baemin2 / Naver / Kakao / Marit — and despite that, we still kept going this year, steadily reading books little by little, asking questions, answering them, and looking things up together. You can see the list of books we covered this year at the link below, and at some point the repo crossed 200 stars!! Everyone puts a lot of effort into organizing and maintaining the repository, so it felt really proud and amazing to know that so many people were referencing it.
https://github.com/Java-Bom/ReadingRecord

 

GitHub - Java-Bom/ReadingRecord: 📚 책 읽고 정리하기 📚

📚 책 읽고 정리하기 📚. Contribute to Java-Bom/ReadingRecord development by creating an account on GitHub.

github.com

At Java-Bom, we covered a total of 3 books, and here's how I felt about each one. (The names in parentheses are the issue labels we use to manage them.)

  • Toby's Spring (Spring of Toby): This is definitely a must-read for any developer working with Spring. Some parts I skimmed through, others I read carefully, but if I ever revisit this book, I think I should read it alongside the actual Spring source code next time. The thing is, I read it at such a slow pace this time that I'd sometimes forget what I'd read earlier and just move on. Going forward, I want to read even thick books at a faster pace. (Easier said than done, though..)
  • Kubernetes Introduction (Kubernetes introduction): Hmm, personally I didn't find it very fun. The part about Kubernetes architecture that I wanted to dig deeper into — which I studied on my own by cross-referencing Kubernetes in Action and the official docs — was interesting, but the rest was basically typing out YAML files and being introduced to various features. Since I've already used Kubernetes before, the parts introducing each object's functionality via YAML were stuff I already knew, which is probably why. So I enjoyed Kubernetes in Action more than this introductory book. But if you've never learned Kubernetes and want a hands-on-lab style experience to follow along with, this book isn't bad either.
  • The Definitive Guide to Spring Batch (Definitive Guide to Spring Batch): I started this book hoping it would help me write better Spring Batch jobs, but the main takeaway ended up being just getting a better look at the batch repository structure. When I wasn't the one leading the session, I'd just kind of read through and move on. (Around this time I was starting to get tired of reading books.) The book introduces batch interfaces and briefly explains various implementations, but if you just note "oh, this exists" and don't actually use it yourself, it doesn't really stick — that's how I felt about it. I'm definitely the type who prefers getting a feel for things by actually coding rather than just reading. But if there's a specific implementation you want to use, I think you could get a quick overview from this book and then consult the official Spring Batch docs for a fast understanding.

The Java-Bom study group is currently on pause. Everyone's busy with work and motivation is low, so we decided to take a break.

3-3. System Design Study Group (Aug – Nov)

  • System Design Interview – An Insider's Guide

This study group was organized by Jeongdong, whom I got to know through GDSC. I ended up studying with completely new developers I had no prior connection with, and we read the book as a group from Baemin / Toss / AWS / Kakao. The great thing about reading this book with people from different companies was hearing real-world stories about how system designs are actually used in each company's domain. The book covers design topics at a fairly high level, so the content could feel lightweight on its own, but it was surprisingly fun as each member filled in the gaps with their own experiences and knowledge. Through this study group, I started thinking that beyond the application code I mentioned above, I should also become a developer who pays more attention to system design.

Jeongdong shared some great article links and YouTube videos for studying design, and my goal is to go through all of them this year and upload them to my blog one by one. Reading this book alone left some gaps. Also, while reading this book, I asked a senior developer on our team how you can estimate things like TPS per server in interviews, and they said it's a matter of experience. So I got the insight that it's important to remember or document the number of servers our team uses, the corresponding TPS, and the architecture. In fact, during retrospectives for outages or big events like year-end traffic spikes, we go over various numerical metrics, and it's really great every time we do it.


3-4. Book Study Group (Jan – Nov)

This is a study group run by Wonbeom, whom I also met through GDSC, along with his college friends. I don't remember how I ended up joining, but unlike Java-Bom, this group reads and reviews books on an incredibly fast cycle. Once we pick a book, we meet twice a week, and each time we need to have read one chapter (about 60–70 pages). I was used to reading books at a leisurely pace, and I'm the type who struggles to read even one chapter a day (I genuinely hate reading books unless they're novels). But I just told myself "let's push through and at least read one chapter a day" and that changed me. The upside was that I ended up reading way more books than expected, but I also often had to rush past parts I wanted to focus on because of time pressure.

  • Microservices Patterns: This was the very first book we read so I don't remember it too well 😢 But I do recall looking at various patterns and diagrams and trying my best to understand them by mapping them to examples I already knew. Since our team was already using some of these patterns and not others, this approach to understanding was possible. The hardest part was definitely the distributed transactions section.
  • DDD Start: Since some study members didn't know DDD, I thought it would've been better to read this book before the MSA book above. What was great was learning that the things I'd been calling "object-oriented" were actually named with specific terms like Aggregate, Domain, Domain Model, etc. I did read this book, but if you asked me "are you doing DDD?" I'd probably say I don't think I'm truly understanding and applying it properly — because I'm not consciously aware of those terms when I implement things. The book itself is explained very simply, so it's great for someone who's literally just starting with DDD.
  • Refactoring (I posted the 2nd edition cover but actually read the 1st edition in Java): Since I was assigned a refactoring task at work, I had high hopes that this book would be super helpful. Honestly, I was a little disappointed in some ways. Some of the patterns and strategies introduced here can be done with IntelliJ IDE features — I guess it can't be helped since it's an older book. But I do agree it deserves to be called a must-read for developers.
  • Kubernetes in Action: I was already writing Kubernetes YAML, but it felt great to fill in the deeper, more specific knowledge gaps one by one. However, as I got into the later chapters covering objects I'd never actually used, it became hard to understand or think of applications. That said, I really dug into the Kubernetes architecture components like etcd, API server, kubelet, and others through this book.
  • Designing Data-Intensive Applications: Oh man, this one was really hard. I was reading this alongside the System Design Interview book, and that's around when I really felt the need to study distributed system design more seriously. But seriously, it's really hard. Not everything in the book was useful to me, but roughly the first two-thirds was excellent. The latter part covered data analysis topics like Hadoop and Spark, which just didn't interest me.

I wrapped up this study group too. All my study groups this year were just book study groups, and I ended up only reading books during study time without ever actually implementing code or digging deeper, which gave me a bit of an existential crisis. So now I've quit everything! Time to refresh and get back to studying what I actually want.

3-5. Internal Company Study Groups

  • Redis study group: This was an internal study group where most of our team members participated. Here, I also gave an internal presentation on how to use redis-cluster with k8s helm. At the time, I analyzed the bitnami repo and presented what commands were being executed internally to enable certain configurations. However, I'm not currently involved in the redis-cluster migration work our team is doing. I attended the progress presentations from the people working on the migration, and I was really impressed — it can't be easy to study so much to apply what you've learned in practice, keeping everything from config verification to monitoring in mind.
  • Advanced Programming in the UNIX Environment: I'm doing this with a junior developer who joined 9 months before I did, just the two of us. Since our team has some code written in C, I started reading this book hoping it might lower the barrier to entry a bit. Umm... it's hard. There are explanations of UNIX functions and conventions that are sometimes hard to relate to, and sometimes I think I should have paid more attention in my operating systems and computer architecture classes. But since I started this study group with a coworker, we'll probably muddle through to the end somehow.


3-6. Books I Read on My Own

  • Netty in Action: I had previously read this when I needed Netty for the project I did during my conversion from probationary to full-time employee. But since the intern's project also used Netty, I read it again to give proper code reviews and guidance. It's a quick read once you've been through it, but trying to actually apply and build something with it was not easy.
  • Kotlin in Action: I started reading it but never finished 😢 I felt like I wouldn't truly internalize it unless I followed along and ran each example from the book, so I stopped just reading with my eyes. But then it got pushed to the back burner by other book study groups.
  • Redis Operations & Management: Simple and easy to read, packed with nothing but golden tips. Even better that it's under 100 pages. My brief summary is on my blog: https://jyami.tistory.com/141
  • The Programmer's Brain: Currently reading this. I got tired of only reading dev books, so I picked this up as kind of a developer humanities (?) read. As I'm reading it though, I'm starting to think "wait, is my brain basically a computer?" It describes human memory using analogies of RAM, disk, and CPU.

 

4. Ewha Womans University

4-1. TOEIC and Graduation

I graduated!!! Finally!! I almost couldn't graduate because of the TOEIC score requirement, but I passed that too!!! Ideally, I should have taken the TOEIC at the end of 2020 and graduated in February 2021 right on time, but at the end of 2020, I was preparing for my Kakao full-time conversion interview and didn't keep track of the graduation requirements. So I deferred and aimed for August 2021 graduation... but I forgot about that too, and was just living life until around June when it hit me. I calculated the TOEIC score submission deadline and had exactly 2 weeks to study.
The last time I took the TOEIC at the end of 2020 with zero preparation, I scored 565. But now I needed to hit 700 within 2 weeks..!! I wish I'd studied earlier, but I kept putting it off and ended up needing to raise my score by 135 points in just 2 weeks. So at the time, I was going to work at 9 AM, getting off at 6 or 7 PM, eating dinner, studying TOEIC until 10–11 PM, then playing a game or two of LoL to unwind. The result? 710 points. My goal wasn't to actually learn English — I was purely focused on graduating, so I only needed 700. Getting exactly past 700 in just 2 weeks felt amazing (if I'd studied any more, I would've felt robbed).

And just like that, I actually graduated!! By my school's standards, I graduated with a 3.85 GPA out of 4.3. My secret to the GPA? I loved my major, so my major courses were almost all A-range. I loaded up on major courses and cut down on liberal arts, and handled most liberal arts as pass/fail so my GPA would mostly reflect my major courses. So my major-only GPA is 4.05 out of 4.3. Since it's an indicator that I was pretty diligent during school, I made sure to put it on my resume. (Ah... I need to update my resume too...)

4-2. Student Union Building Renovation Fund Donation

Last February, the school was accepting donations for the student union building renovation fund, so as a fresh working adult who had just started receiving a steady paycheck, I went ahead and donated 3 million won right away. They said my name would be engraved on the donor memorial plaque, which I'm super excited about. Having my name displayed somewhere on campus was one of my bucket list items, and I thought "seize the opportunity while it's here!" I initially signed up via automatic monthly payments (CMS), but the next day I called the Office of External Affairs and just wired the whole amount in a lump sum. Being able to live confidently and on my own terms is definitely partly thanks to attending this school, and I have real affection for it, so I really wanted to do this.

5. Daily Life

5-1. Driver's License

I got my driver's license around May. I'd been putting it off using the excuse that I didn't have money, but once I became a working adult and my daily life and income stabilized, I thought "why not give it a shot?" and went for it. I passed the written test, skills test, and road test all on the first try!!! But since I live in an area with great public transportation and don't really need a car, I don't actually own one, so it's destined to be a dusty license lol. When the Casper first launched, I was seriously tempted to splurge on a car, but when I thought about where I'd actually use it, I couldn't think of anywhere, so I figured I'd buy one when I'm closer to 30.
Oh, a funny memory from getting my license... I'm terrible with directions, and I absolutely could not memorize the road test route, so I just wrote down the roads and every action I needed to take on paper and memorized it all. There was a YouTube video from the driving school showing the road test practice route, and I watched it while writing things like "When you see the Shinhan Bank sign, turn on right blinker" > "Then make a right turn at the intersection (turn the wheel one full rotation quickly)"... My friends were horrified when they heard. When I actually need to drive for real someday, I'll make sure to get proper driving lessons first..

5-2. Hair Color Update

I had never bleached my hair in my entire life. Back when everyone experiments with hair color — right after the college entrance exam in senior year — I was like "Koreans look best with black hair" and only ever got perms lol. Then out of the blue in May this year, I thought "I'm in my early 20s — if I don't bleach my hair now, I'll probably never do it for the rest of my life," and I just went for it. I've been keeping it up since then. After bleaching, I bought a ton of hair products and learned a lot from my hairstylist about things like heat reactions and whatnot. Changing my hair color was definitely a great mood booster. My hair tends to have strong heat reactions, so even after bleaching 3 times, platinum blonde is hard to achieve 😢 Colors like ash gray don't come out right, so I mainly go with reddish tones. But I feel like my hair color is getting lighter with each bleach...? I'm debating whether to keep it up for about another year.

I post on Instagram with #haircolorupdate so only my photos show up.

5-3. Working Out

While working from home, at some point my back started hurting from sitting too long, and I thought maybe it's time to start exercising. Since I was mostly working from home, I first started by switching to a Sidiz chair, but aside from that, being on my own with my own cooking made me suddenly worried about my diet and health. Starting from last summer, Eunnim kept telling me "exercise before your body gives out," and I started thinking I'd probably end up exercising only after my body breaks down, so I decided to start personal training as soon as possible. The frustrating part about PT was that my trainer kept changing 😢 Including my current PT sessions, I've done about 40 sessions total, but I've had 3 trainer changes. My first trainer was a great fit — I got into working out, started going to the gym on my own, and bought 20 more sessions. But that trainer quit, so I did 7 sessions with a different trainer while adjusting, then switched to a new gym where I'm now doing 20 sessions with yet another trainer.
When I was with my first trainer, I wrote down all the advice they gave me after every session so I wouldn't forget. Now I use the Strong app.

I can definitely feel that my strength has improved since the beginning and I'm getting more interested, but I really wish I could have continued with my first trainer. I went from doing bodyweight squats to now squatting with a 40KG barbell on the rack — if my first trainer could see that, they'd say "wow, you started like this and now look at you!" and be proud together with me 😢. Still, thanks to that first trainer, I got that great feeling of crushing goals one by one, and talking with people around me who are into fitness — like Jaeyeon and Eunnim — and learning more from them made working out surprisingly fun. I used to go around whining like a slug or a snail saying "ugh, exercise is so annoying," and it's wild that my mindset changed in just half a year.
I go to the gym about 3–4 times a week. With PT sessions, I'm also trying to focus more on stretching and do lots of foam roller massages. Being a developer, the muscles around my neck, shoulders, and armpits definitely get really tense, so I try to use a massage ball or foam roller between work to keep the muscles from knotting up. It's nice because it also refreshes me during work, and when I do upper body exercises without knotted-up muscles, it hurts less. Anyway, starting PT led me to get interested in various types of exercise, and I genuinely want to build more strength and try other workouts too. Compared to last year, exercise has been the biggest change in my life.


And that's the end of my retrospective!! The GDSC lead members and I do a yearly retrospective relay, and even though I always grumble about how bothersome it is, once I actually start writing, I end up going on and on about my thoughts from the past year. I guess that's natural since it's basically a year's worth of diary entries.

Wrapping up with some random photos of me at 24

Everyone writes their goals for next year in their retrospectives, but I'll just say: let's take it easy. If I just keep taking care of my daily life, there'll be a happy future ahead, right? I'm not the type to make long-term plans 😳 Let's live as an energetic, vibrant Jyami in 2022 too! 2021, it's been tough — goodbye 🙌🙌

댓글

Comments

Develop/Kotlin

Ktor 찍먹하기 - 간단 HTTP API 작성 | Trying Out Ktor - Writing a Simple HTTP API

ktor 공식문서 따라해 보는 중 : https://ktor.io/docs/gradle.html#create-entry-point Adding Ktor to an existing Gradle project | Ktor ktor.io나의 소스코드 : https://github.com/jyami-kim/ktor-sample 1. 서버 실행을 위한 기본 골격- ktor embeddedServer로 실행 : https://ktor.io/docs/gradle.html#create-embedded-server- ktor engineMain으로 실행 : https://ktor.io/docs/gradle.html#create-engine-maina. embeddedServer package com.exampleimpo..

Ktor 찍먹하기 - 간단 HTTP API 작성 | Trying Out Ktor - Writing a Simple HTTP API

728x90

ktor 공식문서 따라해 보는 중 : https://ktor.io/docs/gradle.html#create-entry-point

 

Adding Ktor to an existing Gradle project | Ktor

 

ktor.io

나의 소스코드 : https://github.com/jyami-kim/ktor-sample

 

1. 서버 실행을 위한 기본 골격

- ktor embeddedServer로 실행 : https://ktor.io/docs/gradle.html#create-embedded-server
- ktor engineMain으로 실행 : https://ktor.io/docs/gradle.html#create-engine-main

a. embeddedServer 

package com.example

import io.ktor.application.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*

fun main() {
    embeddedServer(Netty, port = 8080) {
        routing {
            get("/") {
                call.respondText("Hello, world!")
            }
        }
    }.start(wait = true)
}

기본 서버 실행을 위한 골격. routing에 해당하는 부분을 주로 아래와 같이 configureXXX 와 같은 형태의 플러그인 형식으로 빼서, 분리하는 패턴을 갖고있음. (코틀린의 확장함수 사용)

// com.jyami.Application

fun main() {
    embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
        configureRouting()
    }.start(wait = true)
}

// com.jyami.plugins.Routing

fun Application.configureRouting() {

    routing {
        get("/") {
            call.respondText("Hello World!")
        }
    }
}

 

위와같이 간단한 코드만 짜서 서버 RUN을 시키면? 
서버 실행 속도가 이렇게까지 빨라도 되는건가.. spring안쓰고 간단하게 서버 만들고 싶을 때 쓰면 좋을 것 같다.

 

b. engineMain (HOCON 포맷)

위 예제는 embeddedServer로 짜는 방법을 적었는데, 만약 EngineMain 방식으로 ktor 서버를 짜고 싶다면 조금 다른 방식이다. 

// main.kotlin.com.jyami

fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)

fun Application.module() {
    configureRouting()
}


// main.kotlin.com.jyami.plugins

fun Application.configureRouting() {
    routing {
        get("/") {
            call.respondText("Hello World!")
        }
    }
}


// resource

ktor {
    deployment {
        port = 8080
    }
    application {
        modules = [ com.jyami.ApplicationKt.module ]
    }
}

HOCON 포맷이라고한다. resources 폴더안에 application.conf 파일을 이용해서 실행시킬 포트나, entry point에대한 애플리케이션 설정을 작성한다. application.conf 관련 여러 설정들 : https://ktor.io/docs/configurations.html

 

2. gradle 설정 확인

gradle application 플러그인 : https://docs.gradle.org/current/userguide/application_plugin.html

 

The Application Plugin

This plugin also adds some convention properties to the project, which you can use to configure its behavior. These are deprecated and superseded by the extension described above. See the Project DSL documentation for information on them. Unlike the extens

docs.gradle.org

 

실행가능한 JVM 애플리케이션을 만들 수 있는 기능을 제공함. 
개발도중에 쉽게 애플리케이션을 시작할 수 있도록 해주며, TAR, AIP과 같이 애플리케이션 패키지도 지원해줌

application 플러그인 안에 java / distribution 플러그인이 모두 내장되어있다. 각각 main에 대한 소스 셋, 배포를 위한 패키징 기능을 가진 플러그인 인듯 하다.

application 플러그인을 사용할 때  configuration은 main class (i.e. entry point)를 지정하는 건 꼭 필요하다.

plugins {
    application
    kotlin("jvm") version "1.6.0"
}
application {
    mainClass.set("com.kakao.ApplicationKt")
}

실행시 intellij runner사용도 되고, ./gradlew run을 사용해도 된다.

 

3. 튜토리얼 1: HTTP API 만들기

build.gradle 분석

dependencies {
    implementation("io.ktor:ktor-server-core:$ktor_version")
    implementation("io.ktor:ktor-server-netty:$ktor_version")
    implementation("ch.qos.logback:logback-classic:$logback_version")
    implementation("io.ktor:ktor-serialization:$ktor_version")

    testImplementation("io.ktor:ktor-server-tests:$ktor_version")
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version")
}
  • ktor-server-core : ktor가 제공하는 핵심 컴포넌트 제공
  • ktor-server-netty : 네티엔진을 사용하여 서버 기능을 사용할 수 있게한다. 외부 애플리케이션 컨테이너에 의존하지 않고도 가능.
  • logback-classic : SLF4J 구현
  • ktor-serialization : 코틀린 객체를 JSON과 같은 직렬화 형태로 변환해준다. 
  • ktor-server-test-host : http 스택을 사용하지 않고도 서버 테스트가 가능함. unit test로 사용가능함

 

ConentNegotiation

fun Application.module() {
    install(ContentNegotiation){
        json()
    }
}
  • 클라이언트와 서버간의 미디어타입을 중계해준다. : Accept, Content-Type Header
  • kotlinx.serialization 라이브러리 혹은 그외의 것 (Gson, Jackson)을 사용하여 컨텐츠를 특정 포맷으로 serializing/deserializing한다. (json으로 하겠지)

ContentNegotiation 플러그인을 사용하기 위하여 애플리케이션 초기화 코드에 install 함수를 사용하여 해당하는 ConetentNegotiation 플러그인을 넘겨준다.

ktor에서는 Content-Type으로 다양한 내장 함수를 제공하고 있는데 

  • kotlinx.serializtion : JSON, Protobuf, CBOR
  • Gson : JSON
  • Jackson : JSON

그이외에 커스텀한 Content-Type을 제공하고 싶다면 아래와 같이 ContentNegotiation의 register 메서드를 사용하여 등록하면 된다

install(ContentNegotiation) {
    register(ContentType.Application.Json, CustomJsonConverter())
    register(ContentType.Application.Xml, CustomXmlConverter())
}

 

request, response 파라미터 제어

1. path parameter

get("{id}") {
    val id = call.parameters["id"] ?: return@get call.respondText(
        "Missing or malformed id",
        status = HttpStatusCode.BadRequest
    )
    val customer = customerStorage.find {it.id == id} ?: return@get call.respondText (
        "No customer with id $id",
        status = HttpStatusCode.NotFound
    )
    call.respond(customer)
}

인덱스 접근자 함수 : call.parameters["myParamName"]
요청 Path를 기본적으로 string으로 가져오게 된다.

 

2. request body

post {
    val customer = call.receive<Customer>()
    customerStorage.add(customer)
    call.respondText ("Customer stored correctly", status = HttpStatusCode.Created)
}

call.recevie<T> : 제네릭 변수를 사용하여 호출한 request body를 자동으로 코틀린 객체로 역직렬화 한다. 

동시에 여러 요청이 접근될 때 문제는 이 실습의 범위를 벗어난다 : 동시에 요청/스레드에서 액세스 할 수 있는 데이터 구조 혹은 코드를 작성하면 될 것

 

3. response body

get {
    if (customerStorage.isNotEmpty()) {
        call.respond(customerStorage)
    } else {
        call.respondText("No customers found", status = HttpStatusCode.NotFound)
    }
}
  • call.respond() : kotlin 객체를 가져와 해당 객체가 지정된 형식으로 직렬화하여 http 응답을 반환한다.
  • call.respondText() : Text를 응답으로 보낼 때의 respond를 간단하게 구현해둔 함수이다. 문자열 응답을 반환한다.

 

Routing

Route 확장함수를 이용하여 경로를 정의하였다. 이렇게 할 경우 아무래도 라우팅만 역할을 빼서 코드를 관리할 수 있어서 좋아보인다. 
Application.module에 있는 라우팅 블록 내부에 각 경로를 직접 추가할 수 있긴하지만, 파일 경로들을 그룹화하여 관리하는 것이 유지보수에 더 좋다. 

Route 확장함수만을 사용하여 경로를 정의할 경우 실제 Ktor 서버에는 적용되지 않는데, 맨 처음 ktor 시작하기에 했던 것처럼, route를 Application에 등록해주는 과정이 필요하다. 즉, Route.module에 등록된 경로들을 Application.module에 등록하는 방식으로 관리하자.

Application의 확장함수를 사용함으로써 application에 등록할 path를 route dsl을 이용하여 등록할 수 있으며, 이 dsl에는 사실상 Route 모듈에 등록된 경로를 Application에 경로를 등록하도록 도와주는 것으로 보인다.

fun Route.customerRouting() {
    route("/customer") {
    	get{}
    }
}

fun Application.registerCustomerRoutes() {
    routing {
        customerRouting()
    }
}

fun main() {
    embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
        registerCustomerRoutes()
        install(ContentNegotiation){
            json()
        }
    }.start(wait = true)
}

 

4. Ktor 테스트

ktor-server-test-host : netty를 시작하지 않고도 endpoint 테스트가 가능하다.
테스트 request를 실행하기 위한 몇가지 헬퍼 메서드가 프레임워크에서 제공되며, 그중 하나가 TestApplication 이다.

HOCON방식 : 한번에 모든 configuration이 등록가능한 구조

internal class OrderRoutingKtTest {

    @Test
    fun testGetOrder() {
        withTestApplication({ module() }) {
            handleRequest(HttpMethod.Get, "/order/2020-04-06-01").apply {
                assertEquals(
                    """{"number":"2020-04-06-01","contents":[{"item":"Ham Sandwich","amount":2,"price":5.5},{"item":"Water","amount":1,"price":1.5},{"item":"Beer","amount":3,"price":2.3},{"item":"Cheesecake","amount":1,"price":3.75}]}""",
                    response.content
                )
                assertEquals(HttpStatusCode.OK, response.status())
            }
        }

    }
    
}

HOCON 포맷인 경우에 사용이 가능한 것으로 보인다. (embeddedServer 방식으로 짜는 경우에는 httpClient를 사용한 직접 호출 방식을 이용하는 것으로 보인다 : https://ktor.io/docs/testing.html#end-to-end)

핵심은 withTestApplication인데, 테스트로 실행하려는 애플리케이션을 주입한다. (Application.module() 형태로된 메서드면 무엇이든 주입이 가능한 것으로 보인다.)

HOCON 포맷의 경우에는, main에 넣기전 main밖에 있는 Application 확장함수에 정의되어있어, 해당 애플리케이션에 대한 모든 설정이 등록된채 테스트가 가능하고, 따라서 위와 같이 module() 을 넣고 테스트를 해도 무관하다.

 

embeddedServer 방식 : 필요모듈만 configuration에 등록하여 테스트할 수 있는 구조

fun Application.testModule(){
    registerOrderRoute()
    install(ContentNegotiation){
        json()
    }
}

@Test
fun testGetOrder() {
    withTestApplication({ testModule() }) {
        handleRequest(HttpMethod.Get, "/order/2020-04-06-01").apply {
            assertEquals(
                """{"number":"2020-04-06-01","contents":[{"item":"Ham Sandwich","amount":2,"price":5.5},{"item":"Water","amount":1,"price":1.5},{"item":"Beer","amount":3,"price":2.3},{"item":"Cheesecake","amount":1,"price":3.75}]}""",
                response.content
            )
            assertEquals(HttpStatusCode.OK, response.status())
        }
    }

}

다만 embeddedServer 방식으로 withTestApplication을 작성하는 경우에는, main() 함수안에 직접 선언이 되어있어 애플리케이션에 대한 모든 테스트는 불가능하고 위에서 내가 정의한 configureRouting(), registerCustomRouting(), registerOrderRouting()과 같이 Application 확장함수 단위로 테스트가 가능하다. 

다만 여기서 주의해야할 점은 configureRouting은 단일하게 넣어도 테스트가 가능하나, registerOrderRouting, registerCustomRouting의 경우에는 불가능하다 왜냐하면 이것들을 직접 넣고 돌리게되면, Application에 등록해둔 ContentNegotiation이 빠지게 될것이고, serialize과정에 문제가 생겨서 테스트가 실패하게 될 것이다. 따라서 테스트시 두개의 configuration을 함께 등록하여 테스트해야한다.

위와같이 테스트가 가능하게 되면서, ktor을 사용할 경우에는 모듈별로, 설정별로 테스트가 손쉽게 될 것으로 보인다.
사실, embeddedServer나 HOCON이나 하나의 Application 확장함수를 만들어서 테스트하는건 같아서 입맛대로 사용하도록하자.

 

Following along with the ktor official docs: https://ktor.io/docs/gradle.html#create-entry-point

 

Adding Ktor to an existing Gradle project | Ktor

 

ktor.io

My source code: https://github.com/jyami-kim/ktor-sample

 

1. Basic Skeleton for Running a Server

- Running with ktor embeddedServer: https://ktor.io/docs/gradle.html#create-embedded-server
- Running with ktor engineMain: https://ktor.io/docs/gradle.html#create-engine-main

a. embeddedServer 

package com.example

import io.ktor.application.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*

fun main() {
    embeddedServer(Netty, port = 8080) {
        routing {
            get("/") {
                call.respondText("Hello, world!")
            }
        }
    }.start(wait = true)
}

This is the basic skeleton for running a server. The routing part is typically extracted into a plugin-style pattern like configureXXX as shown below, separating concerns. (Using Kotlin's extension functions)

// com.jyami.Application

fun main() {
    embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
        configureRouting()
    }.start(wait = true)
}

// com.jyami.plugins.Routing

fun Application.configureRouting() {

    routing {
        get("/") {
            call.respondText("Hello World!")
        }
    }
}

 

If you write just this simple code and RUN the server? 
Is it even okay for the server startup to be this fast.. Seems like it would be great for quickly spinning up a server without using Spring.

 

b. engineMain (HOCON Format)

The example above showed how to write it using embeddedServer. If you want to build a ktor server using the EngineMain approach, it's a slightly different method. 

// main.kotlin.com.jyami

fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)

fun Application.module() {
    configureRouting()
}


// main.kotlin.com.jyami.plugins

fun Application.configureRouting() {
    routing {
        get("/") {
            call.respondText("Hello World!")
        }
    }
}


// resource

ktor {
    deployment {
        port = 8080
    }
    application {
        modules = [ com.jyami.ApplicationKt.module ]
    }
}

It's called the HOCON format. You write the application configuration — such as the port to run on and the entry point — in an application.conf file inside the resources folder. Various settings for application.conf: https://ktor.io/docs/configurations.html

 

2. Checking the Gradle Configuration

Gradle application plugin: https://docs.gradle.org/current/userguide/application_plugin.html

 

The Application Plugin

This plugin also adds some convention properties to the project, which you can use to configure its behavior. These are deprecated and superseded by the extension described above. See the Project DSL documentation for information on them. Unlike the extens

docs.gradle.org

 

It provides the ability to create executable JVM applications. 
It makes it easy to start the application during development and also supports application packaging like TAR and ZIP.

The application plugin has both the java and distribution plugins built in. Each seems to be a plugin that provides source sets for main and packaging functionality for distribution, respectively.

When using the application plugin, specifying the main class (i.e. entry point) in the configuration is mandatory.

plugins {
    application
    kotlin("jvm") version "1.6.0"
}
application {
    mainClass.set("com.kakao.ApplicationKt")
}

You can run it using the IntelliJ runner or by using ./gradlew run.

 

3. Tutorial 1: Building an HTTP API

Analyzing build.gradle

dependencies {
    implementation("io.ktor:ktor-server-core:$ktor_version")
    implementation("io.ktor:ktor-server-netty:$ktor_version")
    implementation("ch.qos.logback:logback-classic:$logback_version")
    implementation("io.ktor:ktor-serialization:$ktor_version")

    testImplementation("io.ktor:ktor-server-tests:$ktor_version")
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version")
}
  • ktor-server-core: Provides the core components offered by ktor
  • ktor-server-netty: Enables server functionality using the Netty engine, without depending on an external application container.
  • logback-classic: SLF4J implementation
  • ktor-serialization: Converts Kotlin objects into serialized formats like JSON. 
  • ktor-server-test-host: Allows server testing without using the HTTP stack. Can be used as unit tests.

 

ContentNegotiation

fun Application.module() {
    install(ContentNegotiation){
        json()
    }
}
  • Mediates media types between the client and server: Accept, Content-Type Header
  • Uses the kotlinx.serialization library or others (Gson, Jackson) for serializing/deserializing content into a specific format (JSON in our case).

To use the ContentNegotiation plugin, you pass the ContentNegotiation plugin using the install function in the application initialization code.

Ktor provides various built-in functions for Content-Type:

  • kotlinx.serialization: JSON, Protobuf, CBOR
  • Gson: JSON
  • Jackson: JSON

If you want to provide a custom Content-Type beyond those, you can register it using ContentNegotiation's register method like this:

install(ContentNegotiation) {
    register(ContentType.Application.Json, CustomJsonConverter())
    register(ContentType.Application.Xml, CustomXmlConverter())
}

 

Controlling Request and Response Parameters

1. path parameter

get("{id}") {
    val id = call.parameters["id"] ?: return@get call.respondText(
        "Missing or malformed id",
        status = HttpStatusCode.BadRequest
    )
    val customer = customerStorage.find {it.id == id} ?: return@get call.respondText (
        "No customer with id $id",
        status = HttpStatusCode.NotFound
    )
    call.respond(customer)
}

Index accessor function: call.parameters["myParamName"]
It retrieves the request path as a string by default.

 

2. request body

post {
    val customer = call.receive<Customer>()
    customerStorage.add(customer)
    call.respondText ("Customer stored correctly", status = HttpStatusCode.Created)
}

call.receive<T>: Uses a generic type parameter to automatically deserialize the request body into a Kotlin object. 

Handling concurrent request access is beyond the scope of this tutorial — you'd just need to write data structures or code that can handle simultaneous requests/threads.

 

3. response body

get {
    if (customerStorage.isNotEmpty()) {
        call.respond(customerStorage)
    } else {
        call.respondText("No customers found", status = HttpStatusCode.NotFound)
    }
}
  • call.respond(): Takes a Kotlin object, serializes it into the specified format, and returns it as an HTTP response.
  • call.respondText(): A convenience function for sending text as a response. Returns a string response.

 

Routing

Routes are defined using Route extension functions. This approach is nice because it lets you separate and manage just the routing logic on its own. 
While you could add each route directly inside the routing block in Application.module, grouping file paths together is better for maintainability. 

If you only define routes using Route extension functions, they won't actually be applied to the Ktor server. As we did in the initial ktor setup, you need to register the routes with the Application. In other words, manage it by registering the routes defined in Route.module into Application.module.

By using Application extension functions, you can register paths to the application using the route DSL. This DSL essentially helps register the routes defined in the Route module into the Application.

fun Route.customerRouting() {
    route("/customer") {
    	get{}
    }
}

fun Application.registerCustomerRoutes() {
    routing {
        customerRouting()
    }
}

fun main() {
    embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
        registerCustomerRoutes()
        install(ContentNegotiation){
            json()
        }
    }.start(wait = true)
}

 

4. Testing in Ktor

ktor-server-test-host: Allows endpoint testing without starting Netty.
The framework provides several helper methods for executing test requests, and one of them is TestApplication.

HOCON approach: A structure where all configurations can be registered at once

internal class OrderRoutingKtTest {

    @Test
    fun testGetOrder() {
        withTestApplication({ module() }) {
            handleRequest(HttpMethod.Get, "/order/2020-04-06-01").apply {
                assertEquals(
                    """{"number":"2020-04-06-01","contents":[{"item":"Ham Sandwich","amount":2,"price":5.5},{"item":"Water","amount":1,"price":1.5},{"item":"Beer","amount":3,"price":2.3},{"item":"Cheesecake","amount":1,"price":3.75}]}""",
                    response.content
                )
                assertEquals(HttpStatusCode.OK, response.status())
            }
        }

    }
    
}

This appears to be usable with the HOCON format. (For the embeddedServer approach, it seems you'd use a direct call method with httpClient instead: https://ktor.io/docs/testing.html#end-to-end)

The key part is withTestApplication, which injects the application you want to run for testing. (It looks like any method in the form of Application.module() can be injected.)

With the HOCON format, since the Application extension function is defined outside of main before being put into main, all configurations for that application are registered and can be tested. So testing with module() as shown above works just fine.

 

embeddedServer approach: A structure where you can register only the needed modules in the configuration for testing

fun Application.testModule(){
    registerOrderRoute()
    install(ContentNegotiation){
        json()
    }
}

@Test
fun testGetOrder() {
    withTestApplication({ testModule() }) {
        handleRequest(HttpMethod.Get, "/order/2020-04-06-01").apply {
            assertEquals(
                """{"number":"2020-04-06-01","contents":[{"item":"Ham Sandwich","amount":2,"price":5.5},{"item":"Water","amount":1,"price":1.5},{"item":"Beer","amount":3,"price":2.3},{"item":"Cheesecake","amount":1,"price":3.75}]}""",
                response.content
            )
            assertEquals(HttpStatusCode.OK, response.status())
        }
    }

}

However, when writing withTestApplication with the embeddedServer approach, since everything is declared directly inside the main() function, you can't test the entire application at once. Instead, you can test at the Application extension function level — like configureRouting(), registerCustomRouting(), and registerOrderRouting() that I defined above. 

One thing to watch out for here: configureRouting can be tested on its own, but registerOrderRouting and registerCustomRouting cannot. That's because if you plug them in directly and run them, the ContentNegotiation registered in the Application will be missing, causing issues with the serialization process and making the tests fail. So you need to register both configurations together when testing.

With testing set up like this, using ktor makes it look easy to test by module and by configuration.
Honestly, whether you use embeddedServer or HOCON, it's the same in that you create one Application extension function and test with it, so just use whichever you prefer.

 

댓글

Comments

Develop/git-github

git 종종 사용하지만 까먹는 명령어들 | git commands I occasionally use but keep forgetting

+ 조금씩 추가할 예정이미 commit한 메세지 author 변경git rebase -i HEAD~N # 원하는 수정 커밋 범위 설정# 원하는 커밋 pick > e 로 수정 후git commit --amend --author="jyami-kim " # --amend로 author 변경git rebase --continue # 다음 rebase 진행 branch upstream 변경local branch가 remote branch를 추적하도록 git branch --set-upstream-to=origin/feature/TM-5644 feature/TM-5644 tag 추가git tag tag-namegit push origin tag-name git local 설정git config --local u..

git 종종 사용하지만 까먹는 명령어들 | git commands I occasionally use but keep forgetting

728x90

+ 조금씩 추가할 예정

이미 commit한 메세지 author 변경

git rebase -i HEAD~N # 원하는 수정 커밋 범위 설정

# 원하는 커밋 pick > e 로 수정 후

git commit --amend --author="jyami-kim <mor2222@naver.com>"   # --amend로 author 변경

git rebase --continue # 다음 rebase 진행

 

branch upstream 변경

local branch가 remote branch를 추적하도록

 git branch --set-upstream-to=origin/feature/TM-5644 feature/TM-5644

 

tag 추가

git tag tag-name
git push origin tag-name

 

git local 설정

git config --local user.email "mor2222@naver.com"
git config --local user.name "jyami-kim"

+ Will be updated gradually

Changing the author of an already committed message

git rebase -i HEAD~N # 원하는 수정 커밋 범위 설정

# 원하는 커밋 pick > e 로 수정 후

git commit --amend --author="jyami-kim <mor2222@naver.com>"   # --amend로 author 변경

git rebase --continue # 다음 rebase 진행

 

Changing branch upstream

Make a local branch track a remote branch

 git branch --set-upstream-to=origin/feature/TM-5644 feature/TM-5644

 

Adding a tag

git tag tag-name
git push origin tag-name

 

Git local configuration

git config --local user.email "mor2222@naver.com"
git config --local user.name "jyami-kim"

댓글

Comments

Develop/DevOps

규모 확장 시스템 설계 기본 | Fundamentals of Designing Systems for Scale

1. 단일 서버 DNS : 도메인 이름을 이용해 웹사이트에 접속한다. DNS에 질의하여 IP로 변환하는 과정이 필요하다. http 요청을 보내고 클라이언트는 응답을 받는다2. 데이터베이스 데이터베이스 : 웹/모바일 트래픽 처리 서버 (웹 계층)와 데이터베이스 서버 (데이터 계층) 분리를 시도한다.3. 로드밸런서 로드밸런서 : 부하 분산 집합에 속한 웹서버들에게 트래픽 부하를 고르게 분산한다 데이터베이스 : 다중화로 성능과 안정성을 보장한다 (master는 쓰기, slave는 읽기)4. 캐시 캐시 : 캐시를 이용해 서버의 요청이 보다 빨리 처리될 수 있게 한다. SOPF가 되지 않게 분산한다5. 콘텐츠 전송 네트워크 (CDN) CND : 정적 콘텐츠(이미지, 비디오, CSS, ..

규모 확장 시스템 설계 기본 | Fundamentals of Designing Systems for Scale

728x90

1. 단일 서버 
   DNS : 도메인 이름을 이용해 웹사이트에 접속한다. DNS에 질의하여 IP로 변환하는 과정이 필요하다. 
   http 요청을 보내고 클라이언트는 응답을 받는다

2. 데이터베이스
   데이터베이스 : 웹/모바일 트래픽 처리 서버 (웹 계층)와 데이터베이스 서버 (데이터 계층) 분리를 시도한다.

3. 로드밸런서
   로드밸런서 : 부하 분산 집합에 속한 웹서버들에게 트래픽 부하를 고르게 분산한다
   데이터베이스 : 다중화로 성능과 안정성을 보장한다 (master는 쓰기, slave는 읽기)

4. 캐시
   캐시 : 캐시를 이용해 서버의 요청이 보다 빨리 처리될 수 있게 한다. SOPF가 되지 않게 분산한다

5. 콘텐츠 전송 네트워크 (CDN)
   CND : 정적 콘텐츠(이미지, 비디오, CSS, JavaScript)는 웹 서버대신 CDN으로 성능을 보장한다

6. 무상태(stateless) 웹 계층
   웹서버 : 무상태 웹 계층을 갖게 함으로써 자동 규모 확장(autoScaling)이 가능하다
   공유 저장소 : 웹서버를 무상태 웹 계층으로 전환하면서, 필요한 상태정보들은 공유 저장소에 저장한다.

7. 데이터 센터
   로드밸런서 : 데이터 센터를 이용해 가용성을 높이고, 전 세계 어디서도 쾌적하게 사용이 가능하다. 지리적 라우팅을 이용하여 사용자의 위치에 따라 가장 가까운 위치의 데이터 센터로 안내한다.

8. 메시지 큐
   메시지 큐 : 서버간 결합을 느슨하게 하여 (loosely coupled) 규모 확장성이 보장되는 안정된 애플리케이션 구성이 가능하게 한다.
   
9. 로그, 메트릭 그리고 자동화
   도구 : 로그, 모니터링, 메트링, 자동화는 규모가 큰 서비스 관리에 용이하다

10. 데이터베이스의 규모 확장
    데이터베이스 : 샤딩으로(수평적 확장 = 서버증설) DB부하를 줄인다.

관련 책 : 가상 면접 사례로 배우는 대규모 시스템 설계 기초


   

1. Single Server 
   DNS : You access a website using a domain name. A process of querying DNS to resolve it into an IP address is needed. 
   You send an HTTP request and the client receives a response.

2. Database
   Database : We separate the server that handles web/mobile traffic (web tier) from the database server (data tier).

3. Load Balancer
   Load Balancer : Evenly distributes traffic load across web servers in the load-balanced set.
   Database : Replication ensures performance and reliability (master handles writes, slave handles reads).

4. Cache
   Cache : Uses cache so that server requests can be processed faster. Distribute caches to avoid becoming a SPOF.

5. Content Delivery Network (CDN)
   CDN : Static content (images, videos, CSS, JavaScript) is served through a CDN instead of web servers to ensure performance.

6. Stateless Web Tier
   Web Server : By making the web tier stateless, auto-scaling becomes possible.
   Shared Storage : When converting web servers to a stateless web tier, the necessary state information is stored in shared storage.

7. Data Centers
   Load Balancer : Using data centers improves availability and enables a smooth experience from anywhere in the world. GeoDNS routing directs users to the nearest data center based on their location.

8. Message Queue
   Message Queue : By loosely coupling servers, it enables building stable applications with guaranteed scalability.
   
9. Logging, Metrics, and Automation
   Tools : Logging, monitoring, metrics, and automation make it easier to manage large-scale services.

10. Database Scaling
    Database : Sharding (horizontal scaling = adding more servers) reduces the database load.

Related Book: System Design Interview – An Insider's Guide


   

댓글

Comments

Dev Book Review

Redis 운영 관리

너무 유용해서 정리 중 관련 책 : www.kyobobook.co.kr/product/detailViewKor.laf?ejkGb=KOR&mallGb=KOR&barcode=9788968486814 Redis 운영 관리 - 교보문고 『Redis 운영 관리』는 Redis의 특징과 함께 어떻게 운영하고 관리해야 하는지를 알아보는 책이다. Redis 복제 모델과 복제시 주의해야 할 사항을 학습한다. 저자는 현장에서 얻은 노하우와 실무 팁 www.kyobobook.co.kr 1. Redis의 이해 문서 : redis.io/ 소스 : github.com/redis/redis 커맨드 : redis.io/commands Redis의 주요 특징 key-value 스토어 : 단순 스트링에 대한 Key/Value 구조를 지원..

Redis 운영 관리

728x90

너무 유용해서 정리 중

관련 책 : www.kyobobook.co.kr/product/detailViewKor.laf?ejkGb=KOR&mallGb=KOR&barcode=9788968486814

 

Redis 운영 관리 - 교보문고

『Redis 운영 관리』는 Redis의 특징과 함께 어떻게 운영하고 관리해야 하는지를 알아보는 책이다. Redis 복제 모델과 복제시 주의해야 할 사항을 학습한다. 저자는 현장에서 얻은 노하우와 실무 팁

www.kyobobook.co.kr

 

1. Redis의 이해

 

Redis의 주요 특징

  • key-value 스토어 : 단순 스트링에 대한 Key/Value 구조를 지원한다.
  • 컬렉션 지원 : List, Set, Sorted Set, Hash 등의 자료구조를 지원함
  • Pub/Sub 지원 : Publish/Subscribe 모델을 지원한다 (서버간의 통지에 유용함)
  • 디스크 저장 (Persistent Layer) :
    • 현재 메모리 상태의 스냅샷을 남기는 기능 'RDB' / 지금까지 실행된 업데이트 관련 명령어의 집합 'AOF'
    • RDB : 메모리 내용을 저장하는 기능 외에는 아무것도 지원하지 않는다. (데이터베이스가 아니다)
    • AOF (Append Only File) : set / del 등의 업데이트 관련 명령어를 그대로 기록함
  • 복제 (replication) : 다른 노드에서 해당 내용을 복제할 수 잇는 마스터/슬레이브 구조를 지원
  • 빠른 속도 : 이상의 기능을 지원하면서도 초당 100,000 QPS (Queries Per Second) 수준의 높은 성능을 자랑

 

Redis와 Memcached 비교

기능 Redis Memcached
속도 초당 100,000QPS 이상 초당 100,000QPS 이상
자료구조 Key-Value, List, Hash, Set, Sorted Set Key-Value
안정성 특성을 잘못 이해할 경우 프로세스 장애 발생 장애 거의 없음
응답 속도의 균일성 균일성이 떨어질 수 있음 전체적으로 균일

Memcached에 저장소의 개념이 추가된 것이 Redis 
저장소의 개념 == [RDB, AOF, Replication]

응답속도의 균일 성부분이 문제가 되는 이유 : 두개의 메모리 할당 구조가 다르기 때문
- Redis : jemalloc - free > 메모리 프래그멘테이션(fregmentation) 할당 비용 때문에 응답 속도가 느려진다.
- Memcached : slab 할당자 

더보기

slab 할당자

내부 단편화 문제를 해결하기 위함 (page 단위 4kb (4096byte) - 할당 받으려는 것 16바이트(16byte) = 4080byte 낭비)

솔루션
- 자주 쓰는 메모리 패턴을 정의한 후 미리 할당
- 해당 페턴에 대한 메모리 할당 요청이 있으면 메모리 할당
- 해당 패턴으로 메모리를 해제하면 우선 그대로 유지 (또 다시 해당 패턴으로 할당 요청을 할 가능성이 높음)

kmem_cache_s 구조체 : 하나의 캐시를 나타냄
keme_list3 구조체 : kmem_cache_s들의 모음. slab 관리
슬랩은 사용자에게 할당할 object들이 저장되어있는 풀구조이다.

커널이 시스템을 초기화 할 때 kmem_cache_init 함수를 통해 자주 사용되는 커널의 오브젝트들의 크기를 고려해 사용목적에 따라 캐시를 생성한다. 32, 64, 128, 256, 512, 1,024, 2,048, 4,096, 8,192, 16,384, 32,768, 65,536, 131,072 byte (페이지 단위 관리보다 내부 단편화를 줄일 수 있다)

 

2. Redis 운영과 관리

핵심 1 : Redis는 싱글 스레드다

싱글 스레드이기때문에 시간이 오래 걸리는 Redis 명령을 호출하면, 명령을 처리하는 동안에는 Redis가 다른 클라이언트의 요청을 처리할 수 없다.

1. 서버에서는 keys 명령을 사용하지 말자

keys 명령 : 원하는 패턴에 매칭되는 키들을 가져오는 명령어이다.
그러나 이걸 사용하면 장애로 이어질 가능성이 높다. 데이터 양이 늘어날 수록 해당 명령의 속도가 느려진다. 실제로 Redis 매뉴얼에 쓰지 말라고 되어있다.

redis.io/commands/keys

 

KEYS – Redis

Returns all keys matching pattern. While the time complexity for this operation is O(N), the constant times are fairly low. For example, Redis running on an entry level laptop can scan a 1 million key database in 40 milliseconds. Warning: consider KEYS as

redis.io

Warning
: consider KEYS as a command that should only be used in production environments with extreme care. It may ruin performance when it is executed against large databases. This command is intended for debugging and special operations, such as changing your keyspace layout. Don't use KEYS in your regular application code. If you're looking for a way to find keys in a subset of your keyspace, consider using  SCAN or SETS.

디버깅이나 스페셜한 명령어(keyspace layout 변경하기)로 의도된 것이라 보통의 어플리케이션 코드에서는 사용하면 안된다. 웬만하면 SCAN이나 SETS 명령어를 사용하는걸 고려해보아라.

모든 Key를 대상으로하는 명령어라서 그렇다.

2. flushall/flushdb 명령을 주의하자

db : 가상의 공간을 분리할 수 있는 개념   
- flushdb: db하나의 내용을 통째로 지우는 것
- flushall : 모든 db의 내용을 모두 지우는 것

flushall 명령은 전체 데이터를 다 지우며 keys명령처럼 많은 시간이 필요하다 (memcached는 순식간에 모든 데이터가 지워진다) - 동작방식이 다르다

아이템 개수에 비례해서 시간이 걸린다
실제 데이터를 일일히 삭제하는 로직으로 구현이 되어있다 : 지우는 속도가 O(n)

Memecached의 flush_all이 빠른 이유

Memcached에서는 실제로 데이터를 삭제하지 않는다.
해당 명령어가 실행된 시간만 기록하고, 이보다 이전에 저장된 key는 get명령을 통해서 접근할 때 없다고하면서 실제로는 지운다. (oldest_live 플래그만 세팅 : 이보다 먼저 생성된 key는 없다)

 

핵심2: Redis Persistent

Reids Persistent : Redis 데이터를 디스크로 저장할 수 있다 > 디스크에 저장된 데이터 기반으로 복구가 가능하다

1. RDB

현재 메모리에 대한 덤프를 생성하는 기능.

fork를 이용해서 자식 프로세스를 생성한다. > 현재 메모리 상태가 복제된 자식프로세스를 기반으로 데이터를 저장한다 (지속적인 서비스가 가능하다) - 근데 이렇게 하면 최악의 상황에 메모리가 2배가 필요할 것 같다.

- SAVE : 모든 작업을 멈추고 현재 메모리 상태에 대한 RDB파일 생성 : 싱글 스레드 이므로 아무 작업도 수행할 수 없음
- BGSAVE : 백그라운드 SAVE : fork 작업을 통해 자식 프로세스에서 파일을 저장한다.

#redis.conf
dbfilename dump.rdb

 

2. AOF

AOF : Append Only File
현재 수행해야 할 명령을 미리 저장해두고, 장애가 발생하면 AOF 기반으로 복구

1. 클라이언트가 Redis에 업데이트 관련 명령 요청
2. Redis가 해당 명령을 AOF에 저장
3. 파일 쓰기가 완료되면 실제로 해당 명령을 실행해서 메모리의 내용을 변경함.

AOF는 기본적으로 사용안함으로 되어있어 변경해주어야한다.

#redis.conf
appendonly yes # default no
appendfilename appendonly.aof # 파일이름 설정
appendfsync everysec # 디스크 동기화를 얼마나 자주할 것인가 (always, everysec, no)

 

AOF와 RDB의 우선순위 : 최신 데이터를 더 많이 가진 파일 - AOF 
RDB는 스냅샷인 반면, AOF는 매 작업마다 디스크에 기록을 남겨서 모든 데이터가 남아있다.

 

참고 : 레디스 프로토콜

*키워드개수\r\n
[키워드개수만큼 반복]
$키워드크기\r\n
키워드\r\n

 

 

3. Redis가 메모리를 두배로 사용하는 문제

장애 원인 : RDB저장시 fork를 사용하기 때문에.

COW (Copy on Write) : 실제로 변경이 발생한 부분만 차후에 복사한다. (그러나 redis는 부분 write가 많다)

참고 : redisgate.kr/redis/configuration/copy-on-write.php

 

Redis Copy-on-Write

copy-on-write Redis Copy-on-Write 분석 Redis Copy-on-Write 분석 개요 槪要 Outline 레디스 서버의 메모리 사용량은 실 데이터 크기에 관리 메모리(overhead)를 더해야 한다.   그리고 Copy-on-Write로 인한 추가 메모

redisgate.kr

참고 : 대용량 메모리와 Redis

Redis는 싱글 스레드임 : 멀티 코어를 활용하기 위해 여러 개의 Redis 서버를 한 서버에 띄우는 것이 성능 면에서 좋다.

Core4개 + 메모리 32GB 장비 : 프로세스별로 6G 할당하기
- 평상시 : 6 + 6 + 6 + 6 = 24GB
- fork 복제시 : 6 + 6 + 6 + 6 + (6 = 자식) = 32GB

 

4. Redis장애 : Read 성공 Write 실패

Redis 기본 설정 : RDB저장 실패 => 장비 이상으로 판단 => Write 명령처리하지 않음 
lastbgsave_status = REDIS_ERR : Write 관련 요청 모두 무시

Heartbeat체크는 읽기 관련 명령을 이용해 검사하기 때문에 문제 발생 가능.

RDB 생성 실패의 경우
- RDB를 저장할 수 있을 정도의 디스크 여유 공간이 없는 경우
- 실제 디스크가 고장 난 경우
- 메모리 부족으로 인해 자식 프로세스를 생성하지 못한 경우
- 누군가 강제적으로 자식 프로세스를 종료시킨 경우

해결 방법
1) 해당 상황이 맞는지 확인하기 : set 명령어 사용
2) info 명령어 사용 : rdb_last_bg_save_status:ok 인지 확인
3) 정책 결정 : config set stop-writes-on-bgsave-error no

 

3. Redis 복제

1. Redis 복제 모델

redis는 마스터 / 슬레이브 형태의 복제 모델 제공
-> 이때 슬레이브가 다른 장비의 마스터로도 동작할 수 있게도 할 수 있음 (M-S-S)

1. 명령어 사용 : slaveof <ip> <port>
2. redis.conf 수정 : slaveof <master ip> <master port>

redis-cli로 접속 후 info 명령어 혹은 info replication 명령어를 사용한다.

6666 - 슬레이브 / 3333 - 마스터

 

2. Redis 복제 과정

1. slave에서 slaveof 명령어를 이용해 마스터 서버를 설정한다.
2. 마스터 서버가 설정되면 replicationCron에서 현재 상태에 따라 connectWithMaster를 호출한다.
3. 마스터는 복제를 위해 RDB를 생성한 후 슬레이브에 전송한다. 
4. 슬레이브는 RDB를 로드하고, 나머지 차이에 대한 명령을 마스터에서 전달받아 복제를 완료한다.

RDB 기준 복제 순서 (full synchronization)
1. 마스터는 자식 프로세스를 시작해 백그라운드로 RDB파일에 데이터를 저장합니다.
2. 데이터를 저장하는 동안 마스터에 새로 들어온 명령들은 처리 후 복제버퍼에 저장됩니다.
3. RDB 파일 저장이 완료되면, 마스터는 파일을 복제서버에게 전송합니다.
4. 복제서버는 파일을 받아 디스크에 저장하고, 메모리로 로드합니다.
5. 마스터는 복제버퍼에 저장된 명령을 복제서버에게 전송합니다.

이때 복제중 끊어지게 되면 backlog-buffer에 데이터가 저장된다. 이후 다시 연결되었을때 이 buffer에서부터 동기화가 이루어진다.
만약 buffer가 넘쳤을때는 full synchronization을 진행한다

 

3. Redis 복제 사용시 주의 사항

주의점 1. slaveof no one을 기억하자

슬레이브는 마스터의 상태를 지속적으로 감시하면서 바뀌는 내용을 계속 전달받는다. 
- 연결 상태 이상이 생기는 경우 : 재 연결이 되면 rsync
- 마스터에 장애가 발생하여 마스터에 데이터가 없는경우 : 슬레이브의 모든 내용이 사라진다.

슬레이브 복제를 진행할 때 emptyDb() 호출로, 현재 자신(슬레이브)의 데이터를 모두 삭제하고 마스터와의 싱크를 맞추려하기 때문이다.

slaveof no one : 더이상 슬레이브로 동작하지 않도록 설정하는 것

주의점 2. 복제 시에 무조건 RDB를 백그라운드로 생성한다는 것을 주의하자

RDB를 사용한다 == 메모리를 두배로 사용할 가능성이 있다. > 설정을 꺼둠
그치만 복제를 사용한다는 것 자체가 fork를 사용해서 RDB를 생성한다는 것 : 하나의 프로세스가 너무 많은 메모리를 사용하지 않도록 나누는 과정이 필요하다.

 

4. Redis 복제를 이용한 실시간 마이그레이션

1. 데이터 이전을 위한 새로운 redis 인스턴스 실행
2. 새로운 Redis 인스턴스를 기존 마스터의 슬레이브로 설정 (slaveof) - 복제 완료
3. 새로운 장비의 slave-read-only 설정을 끈다.
4. 클라이언트들이 새로운 redis 인스턴스를 마스터로 인식하도록 설정을 바꾼다.
5. slave no one 명령어 : 기존 마스터와의 연결 종료 (완전한 마이그레이션 이후)
6. 기존 장비 제거

 

4. Redis HA와 Sentinel

1. Redis HA와 Sentinel 구성

redis master에 장애가 발생하면 sentinel은 슬레이브 중 한대를 선택해서 마스터로 승격시킨다 (내부적으로 투표과정을 거친다)
이때 sentinel이 client에 pub/sub으로 master 변경을 통지한다. 
- client(sub) -> sentinel(pub)

 

2. Sentinel이 장애를 판별하는 방법

기본 : PING 명령어의 응답을 활용해서 판단함. (PONG이 안와도 바로 장애로 판단하지는 않는다)
- SDOWN : Subjectively Down : 해당 서버의 장애를 주관적으로 판단 
- ODOWN : Objectively Down : 해당 서버의 장애를 객관적으로 판단 -> 진짜 장애 : Failover 진행한다.

sentinel이 여러대 있을 때 Quorum(쿼럼) 값 이상의 센티널에서 SDOWN으로 판단해야 ODOWN이 된다.
- 주로 Sentinel 장비 수를 홀수로
- 쿼럼 값을 해당 장비수의 과반으로 설정하는 것이 좋다
   > 대부분의 설명에서 Sentinel을 3대를 띄우고 쿼럼 값을 2정도로 주는 것으로 얘기를 하긴 한다.

SDOWN 판별 : 해당 서버의 last_avail_time과 현재 시간의 차이가 설정된 down_after_period 값보다 클 때
ODOWN 판별 : SDOWN일 경우에만 쿼럼 값을 체크하며, 이 이상일때 ODOWN

 

3. Sentinel이 마스터로 승격할 슬레이브를 선택하는 방법

sentinelSelectSlave 함수로 결정

1. SDOWN, ODOWN, DISCONNECT 된 상태의 슬레이브는 제외
2. last_avail_time이 info_validity_time 보다 작으면 제외
3. info_refresh 값이 info_validity_time 보다 작으면 제외
4. master_link_down_time 이 max_master_down_time 보다 크면 제외
5. 남은 후보들 중에서 slave_priority가 높은 슬레이브가 우선적으로 선택

slave_priorirty 값은 redis.conf 파일을 조정하여 선출시의 가중치에 영향을 줄 수 있다. 
- 0으로 설정하면 해당 슬레이브는 절대로 마스터 승격이 안된다.

 

4. Sentinel 설정과 사용

# sentinel monitor <클러스터 명> <마스터 IP> <마스터 Port> <쿼럼값>
sentinel monitor resque 127.0.0.1 2001 2 

# 다운으로 인식하는 시간
# sentinel down-after-milliseconds <클러스터 명> <시간 miliseconds>
sentinel down-after-milliseconds resque 3000 

# sentinel failover-timeout <클러스터 명> <시간 miliseconds>
sentinel failover-timeout resque 900000

# sentinel can-failover <클러스터 명>
sentinel can-failover resque yes # failover 여부 설정

# 마스터 승격후 몇개의 슬레이브가 싱크를 해야 클라이언트에 알려줄 것인지
# sentinel parallel-syncs <클러스터 명> <sync할 slave 숫자>
sentinel parallel-syncs resque 1 

psubscribe 명령을 이용해 통지를 받는다. (pub/sub)

+switch-master 감지 
<클러스터 명> <이전 마스터 IP> <이전 마스터 Port> <새 마스터 IP> <새 마스터 Port>

 

5. Redis 모니터링

python 스크립트 : info 명령어를 활용한 스크립트. (python-redis 모듈)

Percona Cacti 플러그인 : www.percona.com/doc/percona-monitoring-plugins/LATEST/cacti/redis-templates.html

Redis-stat : github.com/junegunn/redis-stat

redmon : github.com/steelThread/redmon

 

추가 참고하기 좋은 사이트 - redisgate.kr/redisgate/ent/ent_intro.php

 

Redis-Enterprise Introduction

ent_intro 레디스 엔터프라이즈 레디스 엔터프라이즈 서버의 주요 기능 I.   Redis + SQL : 데이터 활용 획기적 향상 II.  Active-Active 이중화 : 진정한 고가용성을 실현 III. 메모리 한계 극복 IV. 기타 추

redisgate.kr

 

 

 

댓글

Comments