"안녕하세요. iOS 개발자 김정민입니다."
• 다양한 분야에서 일을하며 프로그래밍으로 세상을 바꿀 수 있다는 경험을 통해 개발 분야에 관심이 생겼고 iOS 앱 개발을 통해 문제해결의 즐거움을 경험하며 즐겁게 프로그래밍을 하고 있습니다.
• 단순한 기능 구현이 목표가 아닌 "왜"라는 질문을 스스로 던지며 다양한 각도에서 문제를 해결하고자 합니다.
• 혼자 일하는 것보다는 다양한 사람들과 의견을 주고 받으며 어려운 문제를 해결하는데 희열을 느끼는 사람입니다.
• 끊임없는 고민을 통해 가독성 높은 코드를 작성하고자 노력하며, 새로운 개념을 공부하고 적용하여 Quality 높은 코드를 작성하고자 노력합니다.
• 운동을 좋아하고 운동을 통해 스트레스를 해소합니다. 매일 크로스핏과 러닝을 통해 컨디션을 관리하고 활동적인 성격을 갖고있습니다.
• 다양한 사람들을 만나는것을 즐거워하며 서로가 알고 있는 내용과 서로의 생각을 공유하는 시간을 즐깁니다.
• 영어공부하는 것을 좋아하고 외국인과 영어로 대화하는것을 즐깁니다.
사용해본 라이브러리 목록: Alamofire/RxAlamofire, RxSwift, RxCocoa, Moya/RxSwitf, AVFoundation, Kingfisher, Loaf, Progress HUD, Gallery, SnapKit, Then, Swift/SwiftUI, Combine 등
• 문제: 플레이어의 상태에 따라 재생/일시정지를 확인하는데 어려움을 느꼈습니다.
• 해결방안: Key-Value Observation을 통해 AVPlayer의 상태가 바뀔 때마다 UI를 업데이트하도록 구현했습니다.
• 관련 코드: 플레이어 상태에 따른 이미지 변경 Code
• 문제: 플레이어가 재생될 때 마다 실시간으로 변경되는 현재 재생 시간을 받아와서 현재 재생 시간 및 UISlider의 value와 남은 시간을 업데이트 했습니다.
• 해결방안: AVPlayer에서 제공하는 메소드인 addPeriodicTimeObserver(forInterval:queue:using:)을 통해 특정 interval마다 completion block에 구현한 코드를 실행하여 실시간으로 값을 업데이트하도록 구현했습니다.
• 관련 코드: 비디오 재생에 따른 UISlider value 변경 Code
• 문제: RxSwift로 리팩토링하는 과정에서 라이브러리(RxAudioVisual)에서 제공하지 않은 기능들이 있어 플레이어의 빨리감기, 되감기, 10초 앞뒤로 이동 등의 기능을 구현하는데 어려움을 겪었습니다.
• 해결방안: 라이브러리에서 제공하지 않는 기능들은 직접 메소드를 정의하여 작업했습니다. currentTime, presenstationSize, canPlayFastForward 등
• 관련 코드: 라이브러리에서 제공하지 않은 기능 추가 Code
• 문제: 라이브러리에 없는 기능을 구현하고 앱을 빌드했을 때 해당 기능(빨리감기, 뒤로감기, 앞뒤로 10초 이동, 이전&다음영상으로 이동)이 정상적으로 작동되지 않았습니다.
• 해결방안: MP4플레이어 화면에 진입할 때, viewDidLoad()에서 AVPlayer의 currentItem을 구독하고 currentItem을 파라미터로 전달하여 subscribeCurrentItem(_:)메소드를 호출하는 로직으로 문제를 해결했습니다.
• 관련 코드: 라플레이어 컨트롤 기능 오류 Code
• 문제: Firebase를 통해 이메일 로그인을 구현하고, 로그인된 정보를 바탕으로 로그인이 되었던 유저의 경우 추가 로그인 과정을 거치지 않고 바로 앱의 메이화면으로 진입할 수 있게 구현하고 싶었습니다.
• 해결방안: 로그인 절차를 마친 경우 해당 로그인 정보를 UserDefaults에 저장했습니다. SceneDelegate에서 UserDefault에 저장된 User객체의 정보를 확인하여 기존에 로그인했던 User인경우 바로 앱의 메인화면으로 이동하도록 구현했습니다.
• 문제: 공공데이터에 저장된 전기차 충전소 위치는 경,위도 정보가 없고 주소 정보만 있었습니다. MapView에 전기차 충전소 위치를 표시하기 위해 경,위도 정보가 필요했습니다.
• 해결방안: GLGeocoder 클래스에서 제공하는 메소드를 이용하여 일반적인 주소(User friendly place name)에서 CLLocationCoordinate2D객체로 변환하여 앱에 전기차 충전소 위치를 표시했습니다.
• 관련 코드: GLGeocer를 이용해 CLLocationCoordinate2D로 변환
• 블로그 작성 글: [iOS - CLGeocoder 를 활용하여 주소를객체로 변환하기]
• 문제: 로컬 데이터베이스를 사용하지 않고 Firebase에 커뮤니티 글 객체를 저장하여 해당 화면에 진입 시 저장된 커뮤니티 글을 가져오는데 업데이트된 내용이 바로 적용되지 않은 어려움이 있었습니다
• 해결방안: View Life Cycle을 다시 공부하면서 View가 Load된 후 어떤 흐름으로 View의 생명주기가 진행이 되는지 정리했습니다. 이를 통해 viewWillAppear(_:)메소드에서 저장된 커뮤니티 글 정보를 다시 가져오고 난 후 tableView를 reload하도록 구현하여 해당 문제를 해결했습니다.
• 관련 코드: 커뮤니티 글 표시 Code
• 관련 공부 내용: View Life Cycle
• 문제: API통신을 통해 받은 이미지 데이터를 collectionView(_:cellForItemAt:) 메소드에서 UIImage로 변환하여 화면에 표시했더니, 앱이 버벅거려 사용을 할 수 없었습니다.
• 해결방안: Kingfisher를 통해 이미지 캐싱 작업을 진행하여 계속해서 이미지 데이터를 받아 화면에 표시하는 상황에서도 앱이 버벅거리지 않고 정상적으로 작동하게 되었습니다.
• 관련 코드: Kingfisher이용한 이미지 캐싱 Code
• 문제: Cat 이미지 업로드시 HTTP Header가 multipart/form-data여서 해당 형식을 지켜 서버에 이미지를 업로드해야 했습니다.
• 해결방안: multipartFormData 형식의 상수를 선언하여 이미지 데이터 및 이미지 정보를 전달하여 서버와 통신했습니다.
• 관련 코드: multipart/form-data 관련 Code
• 문제: 서버로부터 Cat이미지를 불러와 Local catList에 저장했습니다. 화면을 아래로 당겼을 때 Refresh가 정상적으로 작동되지 않았습니다.
• 해결방안: pullToRefresh(_:) 메소드가 호출 된 경우 기존의 catList배열을 새로 fetch한 배열로 변경함으로써 해결했습니다.
• 관련 코드: Cat 이미지 Refresh Code
• 문제: 앱 데이터를 저장하고 필요할 때 불러와서 화면에 표시할 수 있는 여러가지 프레임워크 중 어떤 프레임워크를 써야할지 많은 고민을 했습니다. 고민을 하면서 실제로 다양한 방법의 앱 데이터를 저장하는 방법을 공부했습니다.
• 해결방안: UserDefaults, KeyChain, FileManager, CoreData 등 애플에서 제공하는 프레임워크 외에 Firebase를 공부하면서 어떠한 프레임워크를 써야할까 많은 고민을 했습니다. 먼저 각 프레임워크가 제공하는 기본적인 기능을 기준으로 프레임워크를 분류하여 앱을 가장 효율적으로 구동할 수 있는 방법인 CoreData 프레임워크를 사용하여 앱 데이터를 저장하고 필요한 시점에 저장한 데이터를 불러오도록 구현했습니다.
• 관련 코드: Core Data Code
• 관련 공부: iOS에서 데이터 저장하기
• Keychain Services 정리: Keychain Services
• 문제: 코어 데이터 저장한 Todo객체를 업데이트할 때 각 항목을 업데이트하는 메소드를 하나하나 선언해서 업데이트 해서 Todo객체를 업데이트 하는데 충돌이 발생하고 정상적으로 데이터가 업데이트 되지 않았습니다.
• 해결방안: 각 항목(isCompleted, isMarked, isReminder, notiDate, memo)를 업데이트하는 메소드를 하나로 통일하고 각 파라미터를 옵셔널 형식으로 선언하여 업데이트 되지 않은 항목은 무시하도록 구현했습니다.
• 관련 코드: Core Data Todo Object Update Method
• 문제: 다른 ViewController에서 업데이트 된 Todo 객체를 전달하는 여러가지 방법 중(Noticifation, Delegate, Completion Handler)중 어떠한 방법으로 구현해야 효과적일지 결정하기 어려웠습니다.
• 해결방안: Notification, Delegate Pattern, Completion Handler를 이용했을 때의 각각 의 장단점을 공부했습니다. 공부한 Notification을 먼저 적용하여 코드를 구현하고 추후에 리팩토링을 통해 개선하고자 했습니다.
• 관련 코드: 업데이트된 todo 객체 전달 방법 Code
• Delegate, Notification, Completion Block 정리: Delegate vs Block vs Notification
• 문제:
기존 코드에서 Notification과 Delegate을 이용해 이벤트를 전달했습니다. 하지만 RxSwift로 리팩토링 하면서 다른 방법을 생각보았습니다.
• 해결방안: todo를 저장할 경우 saveButton을 클릭시 todoTextField에 입력되어 있는 text를 방출하는 방법으로 이벤트를 처리하도록 했습니다.
• 관련 코드: Rx 이벤트 처리 Code
• 문제:
사용자가 설정한 시간에 알림 이벤트를 전달하기 위해 Local Notification을 구현하고자 했지만, 처음 적용해보는 기능이고 공식문서만을 참고하여 구현을 하고싶은 마음에 어려움이 있었습니다.
• 해결방안: Apple에서 제공하는 공식 문서를 읽고 정리햇습니다. 그리고 제공하는 코드를 통해 어떠한 흐름으로 로직이 실행이되는지 분석하여 개인 프로젝트에 적용했습니다.
• 관련 코드:
Local Notification 적용 Code
• Local Notification 정리:
Local Notification
• Push Notification 정리:
Push Notification
• 문제: 처음 진행하는 프로젝트인 만큼 기능을 구현하는데 많은 어려움이 있었습니다. 하지만 무엇보다 제일 어려웠던 점은 커뮤니케이션이었습니다. 서로의 의견을 공유하고 내용을 정리하는 과정이 처음에는 미숙하여 몇번이고 프로젝트를 처음부터 다시 시작해야했습니다. 또한, 각 팀원들이 원하는 방향이 달라서 의견을 조율하는데 힘들었습니다.
• 해결방안: 매주 회의를 통해 각 팀원들의 의견을 정리하여 의견이 갈리는 경우에는 충분한 대화를 통해 의견 조율을 하기위해 노력했습니다. 충분한 의견조율을 통해 UI 및 기능을 정리하고 서로의 역할을 나누어 프로젝트를 진행했습니다. 매주 서로가 느낀 어려운점을 공유하고 도움을 줌으로써 어려운 문제들을 해결해 나갔습니다.
• 회의 자료: 팀프로젝트 UMate 회의 일지
• 문제: 댓글 및 대댓글을 구현하는 과정에서 계속해서 추가되는 댓글 및 대댓글을 구분하여 저장하는ㄴ데 어려움을 느꼈습니다.
• 해결방안: 새로운 댓글을 저장할 때 postID를 댓글 객체에 저장하여 각 게시물에 따른 댓글을 표시하였습니다. 대댓글을 저장할 때는 commentId를 저장하여 각 댓글의 대댓글을 표시했습니다.
• 관련 코드: 댓글, 대댓글 저장 Code
아래의 경험들은 앞으로 마주하게될 문제를 다양한 각도에서 분석하고 해결 방법을 모색할 수 있는 소중한 경험이라고 생각합니다.
"(주)밀리크레센" 초기에 합류하여 약 2년동안 운송 및 상품을 해외로 배송하는 업무를 담당했습니다. 또한, 각종 국가사업에 참여하기 위한 사업계획서 작성을 담당했습니다.
국립국제교육원에서 진행하는 "EPIK"프로그램의 영어 보조강사로 활동하여 국내 초,중,고등학교에서 영어를 가려쳐줄 외국인 선생님의 한국 문화적응을 돕고 각종 프로그램 진행에 도움을 주었습니다.
항해사로서 약 4년간 HMM에서 근무하면서 다양한 나라의 사람들과 업무를 진행했습니다. 또한, 업무를 수행하기 위한 최적의 환경이 아닌 상황에서도 착실하게 주어진 업무를 처리하였습니다.
패션 숏폼(Short-form)영상 스트리밍 서비스 개발 회사에서 iOS개발자로 근무했습니다.
기존에 MVC 패턴에서 MVVM으로 변경 및 Reactive Programming(RxSwift) 적용
스트리밍 서비스 내 광고 배너 삽입 아이디어 제안 및 광고 배너 표시 기능 개발
Clonet 앱 Google Analytics 연동 작업 진행: Google Analytics 연동하여 사용자의 비디오 시청 데이터 및 상품 클릭 이벤트 기록 → 비디오 시청 데이터를 활용한 마케팅 전략 수립에 필요한 데이터 제공
Kakao, Apple Login 기능 추가
신규 프로젝트 셋팅 작업 진행(MVVM + Coordinator, RxSwift)
• Clonet Corporation: https://introdution.clonet.co.kr
(주)밀리크레센(前 샬롯그룹)은 국내 주얼리 디자이너의 제품을 미국 및 유럽에 판매하는 기업입니다. 단순히 물건을 판매하는 것이 아닌 국내의 주얼리 디자이너의 제품을 리브랜딩하여 해외 소비자들에게 소개하고 있습니다.
약 2년동안 원활한 해외 배송을 위한 각종 문서 및 절차들을 구축했습니다. 초기 스타트업인 만큼 다양한 기관에서 투자를 받기위해 사업계획서 작성에도 참여했습니다. 신용보증기금의 Start-up Nest 9기에 선정되었으며, 우리은행의 디노랩(DinnoLab) 2기에 선발된 경험이 있습니다.
약 2년간 스타트업에서 근무하면서 스타트업만의 특수한 환경에 대해 다양한 경험을 했습니다. 또한, 초기 스타트업의 성장과정을 지켜보면서 스타트업만의 매력을 알게되었습니다.
• 밀리크레센 홈페이지: https://www.miliemoon.com
• 디노랩(DinnoLab) 2기 기사: http://www.fintechpost.co.kr/news/articleView.html?idxno=134976
• Start-up Nest 9기 기사: http://www.epnc.co.kr/news/articleView.html?idxno=213178
2020년 2월 국립국제교육원에서 매년 진행하는 EPIK(Enlgish Programm In Korea)프로그램에 영어 보조강사로 참여하여 미국, 캐나다, 뉴질랜드, 호주, 영국, 남아프리카 공화국에서 선별된 외국인 교사들의 한국 문화 적응에 도움을 주었습니다.
한국 문화 알리기 프로그램 기획 및 진행을 했습니다. 다양한 나라의 사람들과 소통함으로써 의사소통 능력을 향상 시킬 수 있었을 뿐만 아니라 프로그램 기획 및 진행을 통해 서로의 의견을 조율하는 방법을 배울 수 있었습니다.
HMM에서 항해사로 3년 8개월동안 일을했습니다. 미주, 구주, 아프리카 등 많은 나라를 입항하고 화물작업을 하면서 현지인들과 영어로 의사소통을 했습니다. 또한, 서로의 의견을 조율하고 선박에서 발생하는 여러 문제들을 회의를 통해 사고를 방지하고자 노력했습니다.
해상이라는 특수한 환경에서 항해사로서 안전 항해와 선원 및 화물의 안전을 위해 매 순간 꼼꼼하게 일을 처리했습니다. 기상악화로 인한 회사와 통신이 불가능한 경우 회사 메뉴얼에 따라 통신이 맡은 바 책임과 직무를 열심히 수행했습니다.
똑같은 어려움을 겪을 다른 항해사들을 위해 제가 겪은 문제점과 어려움 및 해결 방안 등을 자세히 기록하여 인수인계할 인수자에게 전달하여 큰 도움을 주기도했습니다.
또한, 일을하면서 7척의 선박에 승선을 하면서 새로운 환경에 적응하는 방법을 배웠습니다. 승선하는 선박마다 시스템이 다르고 같이 일하게 될 선원들이 달라 그 환경에 쉽고 빠르게 적응하는 방법을 배웠습니다.
항해사로서 일했던 경험은 앞으로 좋은 개발자로 성장하는데 큰 도움을 줄 것이라고 확신합니다.
다양한 사람들과 의사소통을 하며 문제를 해결했던 경험과 영어활용 능력은 뛰어난 엔제니어로 성장하기 위한 없어서는 안될 중요한 능력 중 하나라고 생각합니다.
kxCoding iOS Maestro Camp
2021.05 - 2021.12
핸드폰을 소유하지 않은 사람은 한 명도 없고 결국 모바일 애플리케이션이 가까운 미래에 각광받는 분야가 될 것이라고 생각했습니다. 그 중에서도 남들이 많이 선택하지 않는 개발 분야를 공부하고 싶다는 생각으로 iOS 개발 공부를 시작했습니다.
KxCoding 캠프를 수강하며 전반적인 iOS 앱 개발과 효율적인 코드를 작성하는 방법, 공식 문서 보는 방법과 문서화의 중요성을 배웠습니다. 또한, 팀 프로젝트를 진행하면서 Git의 전반적인 사용법과 팀원들과 커뮤니케이션하는 방법을 배웠습니다.