서론
다음 주 7월 10일 월요일부터 네이버 부스트캠프 챌린지 과정을 진행해서 더 늦기 전에 인턴십 회고를 작성하기로 했습니다.
코딩테스트, 면접 후기는 네이버파이낸셜 2023 WINTER DEV INTERNSHIP 코딩테스트, 면접 회고를 확인해 주세요.
정규직 전환은 실패해서 아쉬움은 있지만, 배운 게 굉장히 많았습니다.
인턴 정보
인턴 기간동안 배운 내용을 회고하기 전에 기본적인 인턴 과정 정보를 먼저 설명드리겠습니다.
인턴 기간은 2023년 1월 16일(월) ~ 2023년 3월 3일 (금) 총 7주 간 진행되었습니다.
최종 면접 진행 결과는 인턴 과정이 끝나고 일주일 뒤 발표되었어요.
부서마다 인원은 천차만별이었는데, iOS 인턴은 저 혼자였습니다.
(혼자였지만 TO 경쟁이 없었던 건 아닙니다... ㅎ)
대면/비대면도 궁금하실텐데요. 기본적으로는 비대면 진행이지만, 오피스 출근도 가능했습니다.
(참고로 네이버 파이낸셜의 오피스는 네이버 1784입니다.)
저는 거리가 굉장히 멀었지만 오피스 출근을 주로 했어요.
멘토님과 대화하면서 배우는 게 굉장히 많았기 때문에 웬만하면 오피스 근무를 진행했습니다.
눈 올 때의 네이버 그린팩토리 ㅎㅎ
그린팩토리 바로 뒤에 네이버1784 건물이 있습니다.
오피스 근무를 하니 구내식당을 많이 이용할 수 있었어요.
아래는 맛있었던 구내식당 메뉴입니다 ㅋㅋ ㅎ
네이버는 구내식당 밥도 다르구나... 생각을 했어요.
너무 맛있었고 또 먹고 싶네요.
그리고 네이버1784에는 외부 식당이 들어와 있는 푸드코드도 있습니다.
제 최애였던 안심 돈가스, 인턴 종료 기간에 출시된 신메뉴 마제소바...
안심 돈까스 너무 맛있었어요 ㅠ
인턴 과정에서 배운 점
가벼운 이야기는 끝났고, 본격적으로 기술적인 회고를 진행해 보겠습니다.
모든 인턴 과정은 부서마다 다를 수 있는 점 참고해 주세요.
실무 프로젝트에 참여한 부서가 있었고, 토이 프로젝트를 진행한 부서가 있었는데 저는 후자였습니다.
특정 앱을 적절히 변경하여 클론 하는 과제를 진행했어요.
자세한 내용을 언급할 수는 없고, 과제를 진행하면서 배운 점 위주로 작성하겠습니다.
(이외 궁금한 점이 있다면 댓글을 남겨주세요. 가능한 선에서 최대한 말씀드리도록 하겠습니다.)
프로토콜 활용
이번에 제가 가장 크게 배운 점은 프로토콜의 활용입니다.
아시다시피 Swift는 프로토콜 활용이 굉장히 중요합니다.
값 타입의 활용도를 높이고, 추상화와 다형성을 구현할 수 있기 때문입니다.
인턴 전에는 프로토콜을 제대로 활용하지 못했습니다.
전혀 사용 못했다는 게 더 맞는 표현이겠네요.
이번 인턴을 진행하면서 클린 아키텍처의 각 레이어를 구현하였고,
이 과정에서 UseCase, Repository 등의 인터페이스를 프로토콜로 구현했습니다.
프로토콜 타입을 이용하면서 다형성을 이해할 수 있었고, DI 과정에서 필요에 따라 맞는 객체를 주입한다는 개념도 배울 수 있었습니다.
Delegate 패턴도 적절히 사용하면서 프로토콜을 활용하는 능력을 키울 수 있었습니다.
인턴이 끝나고 제 토이 프로젝트에 프로토콜을 활용해 리펙토리를 진행했는데요.
프로젝트가 확장에 유연한 구조로 변하는 것을 크게 체감할 수 있었습니다.
물론 아직 완벽하게 사용하는 건 아니고, 현업 개발자들과 비교하기엔 오히려 활용을 못하는 수준이겠죠.
하지만 프로토콜이 낯설지 않게 되었다는 점에서 iOS 개발자로서 중요한 마음을 배웠다고 생각합니다.
클린 아키텍처
이번 인턴 과제에서 강제된 몇 가지 조건 중 클린 아키텍처가 있었습니다.
클린 아키텍처를 활용해서 프로젝트 구조를 잡아야 했어요.
처음 적용해 본 클린 아키텍처
저는 인턴 과정에서 클린 아키텍처를 처음 배웠습니다.
이전에는 클린 아키텍처라는 존재도 몰랐어요...
하지만 배워보니 너무 어렵지만 적절히 사용한다면 유용한 기술이라는 것을 느꼈습니다.
Application, Presentation, Domain, Data 레이어로 나눠 구현을 하기 때문에 역할에 따라 관심사를 분리할 수 있어요.
관심사가 분리되고 레이어 위치만 봐도 어떤 역할인지 유추가 가능하기 때문에 코드를 작성할 부분을 찾기 쉬웠습니다.
클린 아키텍처를 적용해 보면서 이 장점을 직접 느낄 수 있었습니다.
코드를 작성하는 새로운 세계에 눈을 뜬 거 같아서 너무 기분이 좋았습니다.
인턴이 끝난 뒤에 기존 토이 프로젝트에도 클린 아키텍처를 적용해 보았고, 구조가 확실히 개선되었다는 것이 느껴졌습니다.
그런데 아직도 Usecase 개념은 어려운 거 같아요.
정확히는 개념 자체는 간단하지만 구현할 때는 항상 고민을 하게 되는 거 같아요.
프로젝트의 행위를 구현하는데, 행위의 범위를 어떻게 적용할지 항상 고민이 됩니다.
예를 들면, CoreData와 관련된 행위를 하나로 묶는 게 나을지, CRUD 행위를 분리해서 4개의 Usecase를 만들지 어떤 게 더 적절한지 판단이 잘 안 서네요...
이건 경험이 쌓이면 해결될 문제라고 생각하지만 인턴 때 제대로 못 익힌 거 같아 아쉽습니다.
새로운 지식을 학습하는 방법
간접적으로 배운 건 새로운 지식을 학습하는 방법입니다.
인턴 기간은 7주였지만, 앱 클론 과제는 3주의 시간이 주어졌습니다. (이후에는 다른 과제를 진행했고 바로 다음 챕터에 기재함)
학습에 쓸 시간은 부족한데 익히기 쉬운 것도 아니라서 고민이 있었습니다.
이에 대해 멘토님께 상담을 요청했는데요.
배우면서 적용하고, 모르는 부분을 추가로 학습하는 게 좋을 거 같다고 조언해 주셨습니다.
현업에서도 학습 시간은 늘 부족하고, 적용하면서 저절로 알게 되는 것과 또 다른 모르는 부분이 계속 생기기 때문에
완벽하게 학습하고 적용하는 건 힘들다고 말씀해 주셨어요.
이후로는 일단 적용해 보고 모르는 걸 추가 학습하는 방향으로 진행했습니다.
같이 인턴을 진행한 안드로이드팀 인턴분이 이걸 참 잘했는데, 함께 인턴 생활하면서 많이 배웠습니다 ㅎ
라이브러리 구현
3주간 앱 클론 과제를 진행했고, 이후 3주는 사용한 라이브러리를 직접 구현해 보는 과제를 진행했습니다.
(7주 중 6주 간 과제 진행, 남은 1주는 회고 시간)
저는 Kingfisher에서 이미지 캐시 부분에 집중해서 구현해 보기로 했습니다.
그래서 나온 게 JeongImageCache이에요. (https://github.com/jeongju9216/JeongImageCache)
(인턴 과정 중에는 괜찮아 보였는데, 인턴 끝나고 살펴보니 불편한 점이 많았다는...;;;)
타인의 입장에서 코드 작성하기
라이브러리를 구현해 보면서 가장 크게 배운 건 타인의 입장에서 코드를 작성하는 방법이었습니다.
저만 사용할 코드라면 저만 편하면 되겠지만, 협업을 하게 된다면 팀원들도 사용하기 편한 코드를 작성해야 합니다.
메서드 하나를 구현해도 파라미터는 어떻게 해야 할지, 네이밍은 어떻게 해야할지, 오버로딩은 얼마나 해야할지, 상속은 필요할지 등 고민사항이 많다는 걸 배웠어요.
접근제어자 고민
관련해서 접근제어자에 대한 고민도 깊게 해 보았습니다.
기존에는 private, private(set), internal이 대부분이었지만, public, open도 사용해 볼 수 있었고,
subclass 지원 유무에 따라 public과 open을 고민해보기도 했습니다.
인턴 전에 혼자서 토이 프로젝트를 진행할 때는 이런 접근제어자에 대한 고민은 거의 하지 않았어요.
위에서 말했듯 private냐 아니냐만 고민했을 뿐이었습니다.
라이브러리를 구현하는 과정에서 타인의 입장을 고려하면서, 이 메서드 혹은 프로퍼티에 접근해도 되느냐 안 되느냐, 접근만 가능하게 할 거냐 설정도 가능하게 할거냐 등의 고민을 하면서 접근제어자에 대한 깊은 고민을 할 수 있었습니다.
타인 코드 분석
킹피셔를 분석하고 직접 구현하는 과정이어서, 킹피셔의 코드도 분석해야 했습니다.
솔직히 제대로 분석하진 못했어요...
킹피셔 코드에서 이미지 캐시 부분만 골라야 하는데 이 고르는 과정도 쉽진 않았습니다.
종이에 하나하나 적으면서 깃허브 코드를 따라갔고 그 결과, 어떤 원리로 이미지 캐시가 진행되는지 알 수 있었어요.
근데 그뿐... 똑같이 구현할 순 없더라고요...
특히 킹피셔는 ImageView를 한 번 Wrapping 해서 imageview.kf. 메서드 형태로 사용했는데,
저는 이 부분을 이해하지 못해서 ImageView extension으로 구현하는 게 최선이었습니다.
진짜 아쉬웠어요..
타인의 코드 분석하는 게 어렵다는 걸 뼈저리게 느꼈습니다.
멘토님은 원래 어려운 거라고 너무 속상해하지 않아도 된다고 하셨지만 그래도 아쉽긴 하더라고요 ㅎㅎ;
메모리 캐시를 딕셔너리로 직접 구현하고, 메모리 캐시 -> 디스크 캐시 -> 네트워크 순서로 이미지 캐시를 구현했다는 거로 위안을 삼았습니다.
비동기 처리
비동기 처리 경험치도 쌓을 수 있었습니다.
메모리 캐시를 구현할 때 NSCache를 사용하지 않고 딕셔너리를 이용해 직접 구현했습니다.
NSCache를 사용하면 쉽게 구현할 수 있겠지만, 메모리 캐시에 대한 고민도 해보고 싶었기 때문입니다.
이 과정에서 비동기 처리에 대한 고난이 좀 있었어요.
딕셔너리는 thread-safe 하지 않습니다.
여러 thread에서 같은 키에 동시 접근하면 크래시가 발생해요.
그래서 lock을 이용해서 thread-safe 하게 만들어야 합니다.
비동기 처리 방법으로 DispatchQueue와 NSLock 중 고민했습니다.
DispatchQueue를 이용하면 completionHandler를 이용해 리턴값을 반환해야 하는데,
제 프로젝트에서는 필요성에 비해 코드 복잡성을 크게 증가시켰기 때문에 NSLock을 사용했어요.
NSLock을 사용할 때는 Lock의 범위를 얼만큼 설정해야 할지 고민을 많이 했습니다.
처음에는 성능을 위해 lock과 unlock 범위를 빡빡하게 설정했습니다.
(딕셔너리를 사용하기 직전에 lock, 사용한 직후에 unlock을 해주었어요.)
근데 막상 적용하고 테스트를 하니 제대로 동작은 하는데 안전성에 대해 고민이 되었어요.
그래서 코드리뷰를 진행할 때 질문을 드렸습니다.
Lock은 안전성이 1순위라는 피드백을 듣고 범위를 메서드 시작, 끝으로 다시 설정하고,
defer도 적용하여 unlock이 확실히 될 수 있도록 수정했습니다.
덕분에 라이브러리를 구현하면서 안전한 비동기 처리가 무엇인지 고민하고 적용해 볼 수 있었습니다.
마무리
아쉽게도 전환은 실패했지만, 배운 게 많았던 과정이었습니다.
"과제 결과도 좋았고, 팀과도 잘 어울렸는데 시기가 안 좋았다"는 말을 듣고 현타도 많이 오긴 했지만,
그래도 제가 잘못된 길을 걷는 건 아니었구나라는 걸 알 수 있었습니다.
(이 현타를 못 이겨서 상반기 네이버 코테까지 떨어진 건 비밀...)
더 궁금한 내용이 있다면 댓글 달아주세요.
가능한 범위 내에서 답변드리겠습니다.
감사합니다.