저는 대덕소프트웨어마이스터고등학교에 재학중인 3학년 유찬홍이라고 합니다.
주로 Flutter를 이용한 모바일 프론트엔드 개발을 공부하고있고, 현재는 취업을 준비하고 있습니다.
Lotura는 본교 기숙사에 있는 세탁실 현황을 스마트폰으로 간편하게 볼수 있는 서비스입니다.
세탁기와 건조기를 분해하지 않고 직접 만든 장치를 부착함으로써 훼손없이 동작상태를 체크할 수 있고, 특정 기기의 동작이 완료되면 스마트폰으로 알림을 보내주어 잊어버리지 않고 세탁물을 챙길 수 있다는 장점이 있습니다.
약 100명 이상의 교내 사용자를 보유하고 있으며, 현재는 유지보수중인 애정이 담긴 프로젝트입니다 :)
프로젝트에 처음부터 끝까지 참여한 팀원으로써 그동안 걸었던 발자취를 되돌아볼까 합니다.
늘 그랬듯이 세탁기에 빨래를 넣고 나서 공부하던 날이였습니다.
...까먹었더라구요;;
아니 돌려놓고 하루를 방치해서 다시 돌렸던.. 불편한 기억이 있었습니다.
빨래를 돌리러 세탁실에 갔는데 세탁기가 다 차있어서 다시 돌아오는 등 불편한게 한두개가 아니였습니다.
당시에 뭔가 불편하면 임베디드가 해주겠지~ 라고 말하는게 습관이였어서 임베친구를 만나면 "세탁기 API를 만들어줘!", "자판기 API를 만들어줘!"라고 말하는게 일상이였습니다.
한 7번인가 8번인가 말하고 나니 임베 친구도 고민을 하는게 보였습니다.
남자 기숙사가 3, 4, 5층에 있었고 세탁실이 2층 맨 끝에 있어서 여간 불편한게 아니였던지라,, 한번은 동아리 프로젝트로 해볼려다가 너무 스케일이 커서 부결당했다고 말해준게 기억이 나네요..
그래도 어떻게든 만들거라고 해서 응원의 말도 해줬습니다.
기기의 상태를 웹 페이지에 띄워준다길래..
"자주 볼거같은데 웹 페이지보단 앱으로 만들어보는게 어떨까?"
라는 제 인생 최고의 조언을 해버리고 말았습니다.
다음날에 임베친구 A와 B가 절 납치하더라구요..
"앱으로 만들수 있겠냐", "우리가 보내주는 상태를 띄워만 주면 된다"
사실 준비되지 않은 상태에서는 도전하지 않는게 제 성격입니다. 만...
실력은 좀 부족했더라도 저도 느끼는 불편함이기에 프로젝트에 동참하기로 했습니다.
물론 그렇게 어렵지는 않았습니다. 말 그대로 보내주는 상태를 띄워만 줬기 때문에 한 20분..? 세탁기 / 건조기 아이콘으로 뭘 쓸지 고민하는 시간이 절반이였던거같습니다.
만들고 나니 요구사항이 하나가 더 추가되었습니다.
특정 기기 동작이 끝나면 앱에서 푸시 알림 수신 가능 여부를 물어봤는데, FCM 관련 글을 보고 나서 해볼만 하겠다는 생각이 들어 구현해보겠다고 말했습니다.
말하고 나서 FCM 공부하다보니 후회가 밀려왔습니다.
flutter FCM 관련 글 하나만 띡 보고 해볼만해서 OK 한거같은데 막상 해볼려니까 안되서 너무 막막했습니다.
flutterfire cli라는걸 설치했어야했는데 이거에만 이틀을 썼고, 네이티브 설정도 시행착오를 많이 겪었습니다.
특히 iOS는 개발자 계정이 있어야 해서 학교 iOS 개발자 계정에 앱을 등록하고 사용하려고 했는데, iOS 관련 세팅도 그당시엔 빡셌던 기억이 납니다.
어떻게 어떻게 알림을 받는건 성공했지만 백그라운드에서는 알림이 안와서 정말..정말 많이 관련 글을 찾아보았습니다.
firebase FCM이 개편되었는지 예전 글에 있던 onResume..? onLaunch..? 이런 메소드들이 안먹더라구요..
그걸 제외하고나서도 분명 똑같이 따라한거같은데..왜 안되는지 너무 막막해서 처음부터 꼼꼼히 공식문서를 보면서 따라했습니다.
@pragma를 달고 나니까 귀신같이 백그라운드에서도 메시지가 와서 울뻔했던 기억이 납니다 ㅎㅎ
iOS는 APNs니 p12 파일이니 인증서니... 플러터만 공부해왔던 저한테 제일 어려운 부분이 아니였나 싶습니다. iOS FCM을 성공했을땐 임베디드 친구와 부둥켜안고 한바퀴 돌았던 기억도 나네요 ㅋㅋㅋㅋ
개발을 하다가 세탁기나 건조기의 상태가 변경되면 어떻게 클라이언트에서 받을지 몰라 질문을 했던적이 있습니다.
"어떻게 바뀐 상태를 받을수 있지?"
"http 요청을 1분에 한번씩 보내"
"?"
아마 이런 플로우였던거같은데... 근데 아무리 생각해도 너무 비효율적이라 소켓을 사용해보는게 어떻냐고 제안을 해보았습니다.
사실 이때도 소켓 1도 몰랐었는데 룸메이트가 소켓을 사용한 실시간 채팅 어쩌고..를 개발하는걸 보고 실시간이 된다길래 생각나서 한 말이였는데 이것도 막상 해볼려니까 너무 막막했었습니다.
소켓iO를 사용해야 하는데 검색하면 나오는건 죄다 웹소켓 연결방법, firebase realtimeDB를 이용한 채팅.. 이런것만 나오고 소켓 iO는 정보가 그닥 많지 않았던 걸로 기억합니다.
이때 처음으로 스트림에 대해 공부하게 되었습니다. 이벤트를 생성하고.. 수신하고.. 확실하게 스트림을 공부하면 소켓이 될지 확신은 서진 않았지만 할수 있는 방법이 이거밖에 없었던 터라 지푸라기 잡듯이 공부했던 기억이 납니다 ㅎㅎ;;
하고 나니까 별거 아니더라구요 ^^7
소켓통신 자체는 성공했지만 이걸 어떻게 스트림으로 넣어야 할지, 어떻게 뷰에 표시해줄지, 어떻게 파싱해야할지 여기서 많은 시간을 보낸것 같습니다.
다만 파싱 과정에서 진짜진짜 시간을 많이 보냈는데, 왜 안되나 계속 머리를 싸매고 개발하다가 조금 충격적인 사실을 마주쳤습니다.
원래 백엔드 개발 언어로 php를 사용하던 도중 node.js로 마이그레이션 하면서 보내주는 JSON 형식에 약간의(?) 수정이 있었습니다.
디바이스 타입이 분명 deviceType이였는데 바꾸고 나서 device_type이 되었지만, 저희가 API 명세서도 없이 그냥 박으면서 개발하다보니 저는 모르고 있었습니다.
이것때문에 자꾸 플러터에서 파싱하면 null이 들어온다길래 이상하다 싶어서 내가 파싱을 잘못하는건가 하고 2주일동안 삽질했던 기억이 납니다..
아무리 생각해도 제 문제는 아닌거같은데 말은 못하겠고.. JSON 유심히 보다가 어 설마..? 하면서 소문자 T로 바꿨는데 드디어 와가지고 그자리에서 드러누웠습니다;;
말하지 않으면 모르기때문에 이슈가 발생하면 꼭 팀원 모두에게 공유해야 한다는 점과 명세서 작성의 중요성을 이때 깨달았습니다.
학교 애플 개발자계정을 사용하기까지는 많은 과정들이 있었습니다.
방학이였는데 담당 선생님이 메일도 안보고 연락도 안보시질 않나..
막상 학교에 가서도 바쁘셔서 매번 자리에 안계시질 않나..
멤버쉽이 만료됐는데 결제가 늦질 않나..
계정을 빌려쓰는 입장에서는 뭐라 할 말이 없지만 학교측에서 이쪽에 너무 관심이 없으신게 아닌가 하는 생각이 많이 스쳐가던 때였습니다.
학교 개발자 계정에 저를 등록 후 들어가려고 하는데 자꾸 하얀 화면만 떠서 배포에 어려움을 겪었던 적도 있었습니다. 검색해도 안나오고 선생님은 모른다고 하셔서 울며 겨자먹기로 취업을 앞둔 선배님을 찾아간 일이 있었습니다.
너무 다행히도 선배님께서 관리자 권한을 갖고 계셨는데, 저를 다시 등록해주시고 나니까 말끔히 해결되었습니다.
항상 감사하게 생각하고 있습니다 :)
알림 신청 기능을 만들고 나서 내가 어떤 알림을 신청했는지 몰라 신청한 리스트를 보여달라는 의견이 있었습니다. 추가적으로 신청한 알림을 취소할수 있는 기능도 요청받아 간단해보여서 바로 개발에 들어갔습니다.
어렵진 않았지만 신청 리스트도 소켓을 사용했던 터라 만들다보니 한가지 문제가 생겼습니다.
알림을 신청하든 취소하든 한가지 행위를 해도 이전에 했던 요청이 화면에 보여진다는 것이였습니다.
백엔드쪽에서는 알림 신청 요청, 알림 취소 요청, 갱신 요청 이렇게 3가지가 있었는데, 신청 또는 취소와 함께 바로 갱신 요청을 보내어 요청사항이 바로 적용되지 않았던 것이 문제였습니다.
3일동안 고민해보다가 아 설마 하면서 강제로 0.5초 딜레이를 주고 나서 해결하였습니다.
현재는 신청 관련 로직을 모두 http 통신으로 바꿔서 보다 효율적으로 개선하였습니다.
IoT기능이 없는 기기에도 부착해 사용할수 있다는 장점을 살려 SK Planet에서 주관하는 Smarteen App+ Challenge (2023) 미래산업부문에 참가하였습니다.
가정, 군대처럼 세탁기나 건조기를 사용하는 모든 곳을 타겟으로 커스텀하여 기기를 추가/삭제할수 있는 어플리케이션 제작을 맡았습니다.
추가하고자 하는 장치에 고유번호를 붙여 중복 등록을 제거하고, 혹시라도 군대와 같은 공공장소에서의 사용성을 고려하여 관리자 / 일반 사용자로 나누어 관리자만 기기를 추가 / 삭제할수 있도록 권한을 분리하였습니다.
MVP를 보고 좋게 평가해주신 심사위원분들 덕분에 대상인 중소벤처기업부 장관상을 수상하게 되었습니다. 대회에 나가서 상을 타본게 처음인데 그것도 가장 높은 상을 수상하게 되어 정말 감격스러웠습니다 ㅎㅎ
경주 비즈쿨 페스티벌에서 수상작 전시와 시상식을 마친 후 촬영한 사진입니다.
아래 링크에 관련 기사와 블로그가 있으니 궁금하신 분들은 찾아보시면 좋을 듯 합니다. 저는 맨 왼쪽에 있습니다 :)
SK플래닛-중기부, ‘스마틴 앱 챌린지 2023’ 시상식 개최
[STAC 2023] "Lotura, 언제 어디서나 세탁기와 건조기를 확인하세요"
스마틴 앱 챌린지 2023 "대상" 수상 | 작성자 대마불사
학교로 돌아오는 일요일 저녁이였는데 수상 후 플랜카드가 걸려있는걸 보고 뿌듯함을 느끼기도 했습니다.
사실 플랜카드보다 상금 500만원이 더 뿌듯했습니다 ㅎㅎㅎㅎㅎ
저희 학교에서는 매년 11월쯤 되면 소프트웨이브에 전시할 출품작을 선정하여 3일동안 학생들이 직접 전시하는 행사를 진행하고 있습니다.
마침 Lotura 프로젝트가 외부 대회에서 대상을 수상하여 선생님들께 좋은 이미지를 받아 학교 대표 프로젝트로 소프트웨이브 2023에서 전시할 좋은 기회를 가지게 되었습니다.
3일동안 많은 기업체 관계자분들, 많은 사람들에게 저희 팀이 만든 프로젝트를 소개해보았고, 이때 마주한 분들께서 남겨주셨던 피드백들을 바탕으로 더 나은 서비스를 위한 고민을 해보는 등 뜻깊은 경험을 하였습니다.
아래 링크에는 같이 참가한 다른 팀 친구들의 회고록입니다. 이것 역시 궁금하시면 읽어보는걸 추천드립니다^^
모르는 사람에게 인사를 어떻게 해요? 친절하게 말을 걸라구요?
고2가 교내 취업 관리 서비스를 만들기까지
운 좋게도 서비스 설명중에 뉴스기자님을 만나게 되어 관련 기사도 같이 나오게 되었습니다.
[소프트웨이브 2023]학생들이 개발한 세탁기, 건조기 IoT 솔루션
어느정도 자리를 잡아가던 중 임베친구가 알림 신청을 하는 과정이 복잡하다는 의견을 주었습니다.
스마트폰을 켜고, 앱을 찾고, 알림신청을 클릭하고.. 이 과정이 번거롭다면서 NFC를 태그해서 바로 알림 신청을 할수 있게 하면 어떨까라는 말을 해주었습니다.
듣고 보니 맞는 말이기도 하고, 괜찮은 NFC관련 패키지가 있어서 개발해보겠다고 하였습니다.
아 근데 이거 빡세더라구요;;
NFC를 태그하여 앱을 시작하게 되면 플러터에서는 읽지 못하는 문제가 발생했습니다.
검색해도 방법이 나오지 않아 플러터 오픈채팅방, 디스코드에서 자문을 구한 결과 네이티브를 다뤄야 한다는 결론이 나왔습니다.
플러터를 하다보면 네이티브를 다뤄야 할 순간이 꼭 온다고 들었는데, 그때가 이때였나봅니다..
네이티브 통신을 위한 메소드, 이벤트 채널링과 코틀린을 공부하게 되었습니다.
메소드 채널링을 배운다고 쳐도 코틀린을 이용해 구현해야 하는데, 코틀린 NFC 관련 공부를 위해 안드로이드 공식 문서를 살펴보았습니다.
NFC 기초 | Android 개발자 | Android Developer
솔직히 개발하면서 정신나가는줄 알았습니다.
소켓 연동하던 과거가 생각나면서 도대체 내가 뭘 잘못한건지.. 왜 안되는지.. 잠도 잘 안자고 밥도 잘 안먹으면서 개발에만 몰두하고 살았습니다.
혹시 이론적으로 불가능한거 아닌가.. 라는 생각도 들었는데 RN에서 성공사례를 보고 희망을 가지고 계속 갖다 박았습니다 ㅎㅎ
그래도 계속 시도해보니까 성공해서 한번 공유해봅니다.
앱의 시작지점인 onCreate 함수에서 nfcAdapter를 초기화해줍니다.
이때 nfcAdapter가 null인지 아닌지 꼭 체크를 해야합니다!
nfc를 지원하지 않는 기기서는 null이 들어가기 때문에 앱이 터져버리는데 이걸 모르고 리젝만 3번 먹은 경험이 있습니다..
인텐트 액션이 NDEF_DISCOVERED일때는 nfc에서 데이터를 읽어와 메소드 채널링으로 보내줄 변수에 저장해줍니다.
NFC 인텐트로 무언가 행위가 일어나면 인텐트에서 검사된 NFC 태그에 관한 정보를 가져올 수 있습니다. 여기서 onNewIntent 메소드는 NFC에 태그를 할 경우 호출되는 메소드인데, onCreate에서 호출되고 나서 그 다음부터 태그되었을때마다 태그 안의 데이터를 읽어옵니다. 이것 역시 onCreate 코드와 같은 코드를 넣어주었습니다.
혹여나 다른 인텐드 활동에 NFC 태깅이 묻힐까봐 포그라운드 디스패치를 적용해주었습니다. 필터를 이용해 NDEF_DISCOVERED가 찍히면 우선순위를 주장하여 가장 먼저 처리할 수 있게 됩니다.
인텐트 필터에 액션을 등록해주고, 읽어올 데이터가 text/plain 형식이라는걸 manifast 파일에 명시해줍니다.
NFC tools 앱을 이용해 태그 안에 어플리케이션 주소와 데이터를 넣고,
메소드 채널링 요청이 올 때마다 보내줍니다.
보낸 후에 -1로 변경한 이유는 앱이 백그라운드로 갔다가 다시 돌아왔을때, 태그하지 않았음에도 저장된 데이터를 보내주었기 때문에 초기화해주었습니다.
라이프 사이클 상에서 포그라운드로 돌아왔을때 실행되는 RESUMED에서 무조건 네이티브로 NFC 데이터 요청을 보내도록 만들었기 때문에, -1로 초기화함으로써 잘못된 데이터를 방지할 수 있습니다.
벨로그에선 영상을 넣을수가 없어서 보여드리지 못하는게 아쉽네요 ㅠㅠ
iOS는 또 또 막히면서...
담당 선생님은 다른 학교로 배정받으셨는데 인수인계가 잘 안되었는지 인계받은 선생님께서 비밀번호를 모른다 하시고, 이전 선생님은 연락을 안받으시고.. 실기기 빌드도 막히고 배포도 불가능하면서 개발 기간이 조금 많이 지연되었습니다.
정말 정말 다행히 전 담당 선생님과 연락이 닿아서 다시 개발에 착수하였습니다.
iOS는 친구의 도움을 받아 딥링크를 적용시켜 만들었습니다.
안드로이드와 원리는 비슷하기 때문에 설명은 넘어가겠습니다~
NFC 태그에 딥링크도 추가하여 세탁기와 건조기 앞에 부착해주었습니다.
파란색으로 붙어있는게 NFC 스티커입니다. 버스카드 찍듯이 가져다 대면 앱으로 이동하면서 알림 신청 바텀 시트가 올라옵니다.
기능적인 부분은 다 만들고 유지보수 작업에 들어가면서, 임베 친구가 데스크탑 앱을 만들어달라고 했습니다. 그냥 임베디드 장치를 작업하면서 GUI 용도로 사용하려고 하는거같은데, 딱히 어렵진 않아서 바로 만들어 주었습니다.
다만 아쉬웠던 점은 스마트폰 앱과 비즈니스 로직이 완벽히 동일하고 뷰만 다른데, 이걸 레포지토리를 따로 파서 기능을 똑같이 구현하는게 비효율적이라는 생각이 들었습니다. 나중에 melos로 비즈니스 로직을 모듈로 만들어서 기술 블로그도 작성해보려고 합니다.
사실 이것 말고도 하고싶었던 이야기가 매우 많습니다. 앱 이름 정하기, 임베디드 장치 이슈, 대회 비하인드 스토리, Websocket 이전 등 몇가지 썰이 더 있긴 하지만 프로젝트의 굵직한 부분만 놓고 보면 이정도면 될것 같습니다 :)
프로젝트를 처음부터 끝까지 참여하면서 배운 점이 많았습니다.
실시간 통신, 푸시 알림, 상태 관리, NFC 등등 참여하지 않았더라면 배우지 못했을 소중한 경험들이 너무 많았고, 사실 팀 프로젝트 한번을 안해본 저를 선택해준 친구들에게는 고맙다는 말을 하고싶습니다.
무엇보다 실사용 경험을 안겨다준 이 프로젝트에게도 많은 애정을 가지고 있습니다.
아마 제가 취업하고 학교를 나가면 누군가는 인수인계를 받아야할텐데, 그때를 위해 문서 작업도 해두고 코드도 리팩토링 한 후에 나갈 생각입니다. 사실 취업을 할수 있을진 모르겠습니다 ㅎㅎ;
긴 글 읽어주셔서 감사합니다.
혹시 코드를 뜯어보고 싶은 분들을 위해 레포 첨부하고 마치겠습니다.
https://github.com/team-osj/Loutra-Flutter
(코드 완전 더러움..!!)
너무 재밌게봤어요!