명색이 개발자인데 더 이상 종이 단어장을 쓸 수는 없다!!!
전처리문을 활용해서 하나의 코드로 macOS와 iOS에서 작동하는 프로그램을 만들어 봅니다!
Image를 Data로 바꿔야 하는 이유 구현할 기능 단어장에 텍스트만 저장할 수 있다면 긴 일본어 문장을 전부 키보드로 작성해야합니다. 아직 일본어 타자에 익숙하지 않은 제가 이렇게 문장 연습 단어장을 만든다면 단어를 입력하는 시간이 너무나도 오래 걸릴 것입니다.
구현할 기능 일본어 문장을 타이핑 하라고???!!! 제가 만들고자 하는 앱은 단어장이지만 좀 더 긴 문장을 다룰 수도 있어야 했습니다. 하지만 일본어를 처음 공부하는 입장에서 일본어 단어도 아니고 문장을 타이핑한다는 것은 거의 불가능에 가까운 영역이었습니다. 그냥 이미지로 저장하자 따라서 좀 긴 문장을 저장할 때는 글이 아니라 캡쳐한 이미지로 저장할...
구현할 기능 일본어 공부를 하다보면 짧은 단어를 학습할 때도 있고 긴 단어를 학습할 때도 있습니다. 짧은 단어를 학습할 때는 아이폰을 세로로 그리고 긴 문장을 학습할 때는 아이폰을 가로로 놓고 학습을 하면 좋을 것 같습니다. 하지만 이런 기능을 구현하기 위해서는 화면이 회전할 때마다, 즉 orientation이 바뀔 때마다 화면의 가로 길이를 계산해서 ...
구현할 기능 오늘 구현하고자 하는 기능은 WordCell을 탭하면 단어의 뜻 → 히라가나 (혹은 히라가나 → 뜻)이 전환되고 더블탭을 하면 단어의 Success / Failure 여부를 초기화하는 기능입니다. (이미 외운 단어는 Success(초록색)으로 표시하고 아
구현하고자 하는 기능 같은 단어장으로 계속 공부하다 보면 위아래에 위치한 단어가 은근히 힌트의 역할을 할 때가 있습니다. 이럴 때는 가끔 단어의 위치를 랜덤으로 섞어주어야 단어 학습의 능률이 오르게 됩니다. 이 점이 노트에 단어장을 작성하는 것 보다 앱으로 단어를 외우는 것이 좀 더 효과적일 수 있는 부분입니다. 따라서 우리가 구현하고자 하는 기능은 주...
구현하고자 하는 기능 우리 단어장은 텍스트 뿐만 아니라 이미지도 지원합니다. 텍스트에 비하면 이미지는 네트워크를 통해 불러오는 시간이 훨씬 오래 걸리며 무엇보다 처음에 전부 fetch해오는 것이 아니라 url만 fetch 해와서 사용자에게 보여지는 순간에 실제 이미지
구현할 기능 보통 브라우저에서 키보드의 Tab키를 입력하면 다음 입력창으로 넘어가게 됩니다. 브라우저를 자주 사용하다보니 이게 습관이 되어서 Mac의 TextEditor에 입력을 할 때도 자연스럽게 Tab키를 통해서 다음 TextEditor로 커서를 옮기고 싶습니다.
구현할 기능 우리 앱은 단어 뿐만 아니라 문장도 다루므로 텍스트의 길이가 상당히 길 때가 많습니다. 기존의 앱은 이 경우에 아래처럼 그냥 truncated 되어 버렸습니다. 이렇게 하면 문장 공부를 할 수가 없습니다. 이번에는 텍스트가 길 때 font 사이즈를 줄여
🪲 고쳐야 할 버그 이전에 랜덤으로 단어들을 랜덤으로 섞어주는 기능을 개발했었는데요. 사용자들이 이 기능을 사용하는 이유는 같은 단어를 랜덤한 순서로 다시 한번 테스트하기 위함입니다. 따라서 단어들은 랜덤으로 섞이는 순간 다시 앞면(한글)이 보여야 합니다. 하지만
구현하고자 하는 기능 보통 단어장에 틀린 단어와 외운 단어를 구분하는 이유는 틀린 단어를 나중에 모아서 공부하기 위함입니다. 물론 지금도 단어의 색으로 틀린 단어만 모아서 공부하는 기능을 구현이 가능합니다만 틀린 단어가 몇개 밖에 없다면 그 단어들을 공부하기 위해서
구현해야 하는 기능 현재 단어장을 개발하면서 가장 트러블을 일으키고 있는 부분은 단어 list를 담당하는 상위 View인 StudyView와 각각의 단어의 정보를 표시하는 하위 View, WordCell 간의 정보를 어떻게 전달할 것인가입니다. 먼저 상위 View에
구현하고자 하는 것 예전에 구현한 것인데 포스팅을 깜빡하고 잊었네요. 지금 구현하고자하는 것은 드래그 제스처를 활용해서 단어의 암기 여부를 DB에 기록하는 기능입니다. 그리고 맞은 단어는 초록색, 틀린 단어는 노란색으로 색도 바꾸어 줍니다. 물론 UITableVie
Mac용 App을 만들 때 창의 사이즈를 정의하는 법을 알아봅니다!
문제 현상 아무것도 안하고 그냥 성공 ↔ 실패 드래그만 했는데 갑자기 ForEach 안에 있는 Cell들이 전부 reinit 되는 현상이 있었습니다. 성공 ↔ 실패의 경우는 Cell 내부의 property를 변경하는 것이기 때문에 의도된 대로 동작을 한다면 그냥
이번 포스팅에서는 Gesture 객체를 body 안에 직접 선언하지 않고 View의 property로 선언해서 사용하는 방법을 알아보도록 하겠습니다. 기존의 코드 기존의 코드의 단점은 View에 gesture를 선언하는 부분에 Gesture의 종류와 제스쳐에 연결하
기능 개발에만 집중을 하다보면 View의 body 부분이 엄청나게 길어지고 중복되는 요소도 많아지게 됩니다. 이렇게 되면 나중에 유지보수에 엄청난 시간과 고생이 필요하게 됩니다. 따라서 중간중간 리팩토링을 통해서 코드를 정리하는 작업이 필요합니다. body 부분의
이 포스팅에서 FocusState를 다루는 방법을 배웠었는데요. 아래 코드처럼 View에 Binding으로 연결해서 사용했습니다. FocusState로 선언된 변수가 equals와 동일한 값으로 바뀌면 해당 View로 focus를 변경해주는 기능이었습니다. 하지만 V
SwiftUI의 alert에 TextField 추가?
🎉 JWords의 최초 업데이트인 1.1.0 업데이트에 추가된 기능을 소개합니다.
🎉 1.2.0 업데이트를 통해서 새로운 기능이 추가됩니다!
🎉 JWords가 1.3.0 업데이트로 돌아왔습니다. 새로운 기능들을 소개 합니다!
🎉 JWords의 1.4.0 업데이트로 추가될 새로운 기능을 소개합니다.
🎉 가장 핵심적인 단어장의 기능만을 갖춰 빠르게 개발한 1.0.0 버전을 나왔습니다. 아주 핵심적인 단어 추가 + 학습 기능만 구현을 했습니다. (포스팅 순서가 꼬여서 늦었네요…) 앞으로 사용하면서 더 좋은 앱으로 개선해나가도록 하겠습니다.
🤔 nil인 단어장을 선택하고 싶다. Picker는 여러 선택지 중에 하나를 선택하는 입력을 받는 View입니다. 저의 경우는 단어장을 마감하는 기능을 만들면서 마감할 단어장에서 틀린 단어들을 이동할 단어장을 고를 때 Picker를 사용할 생각이었습니다. 하지만
3시간…😭 오늘 단어장을 마감하는 기능을 구현하기 위해 Modal View를 하나 만들고 있었습니다. 해당 View에서는 기존의 단어장 중에 하나를 골라서 마감하려는 단어장에서 아직 학습이 완료되지 않은 단어들을 그 단어장으로 이동시키는 작업을 할 생각이었습니다.
개발하고자 하는 기능 현재 단어장을 마감하는 기능을 구현하고 있습니다. 간단하게 설명하면 공부를 다한 단어장을 마감처리하고 단어장을 공부 목록에서 제거하는 기능입니다. 단어장을 마감하기 위해서는 아직 공부를 마무리하지 못한 단어들을 새로운 단어장으로 보내야 합니다.
현재 발생하는 버그 단어장 목록에서 현재 단어장을 성공 / 실패 여부를 초기화하고 싶을 때 (하얀 배경) 더블 탭을 통해 초기화할 수 있습니다. 그리고 이 결과는 바로 View에 반영되어야 합니다. 하지만 아래 캡쳐에서 보듯이 바로 반영되지 않는 버그가 발생했습니다
다소 황당한 버그… 아이폰 쓰시는 분은 다 아시겠지만 부분을 드래그해서 올리면 사용 중인 앱들을 모아보는 화면을 볼 수 있습니다. 이 동작을 앞으로 “모아보기 화면으로 나간다”라고 부르겠습니다. 이렇게 해서 앱 간에 전환을 할 수 있습니다. 저도 단어장을 사용하면서
예전에 제가 다른 프로젝트들을 했을 때는 디바이스에 직접 저장하는 CoreData를 사용하거나 MySQL를 활용한 웹서버를 이용해서 데이터를 저장했었는데요. 둘 다 SQL 계열의 DB라서 많이 익숙했었습니다.
🎉 JWords가 1.5.0 업데이트로 돌아왔습니다. 이번에 추가된 기능을 소개합니다.
Dependency Injection이란? 한 객체에서 사용할 객체를 외부에서 주입하는 것을 의미합니다.
😵💫 Firebase.config()이 실행이 되기 전에 Firebase를 쓰려고 한다고??? 제가 만들고 있는 앱은 MacOS와 iOS에서 둘 다 사용할 수 있는 나름의(?) 크로스 플랫폼 앱인데요. 지금 테스트를 위해서 Singleton 패턴을 사용하던 API 부분을 Dependency Injection으로 리팩토링하는 와중에 아래와 같은 에러를...
Phase 2의 목적은 기존에 있는 코드들의 Unit test를 작성하는 일입니다. UITest도 함께 작성하려고 했으나 일단은 Unit test에만 집중할 수 있도록 해보겠습니다. Unit test를 작성의 대상은 대부분 각 View의 ViewModel들이 될 텐데요. Unit test는 해당 객체만 독립적으로 테스트 해야 하므로 다른 객체에 의존하지 ...
Phase 1에서는… 지난 번에 Phase 1에서는 그저 기능구현에 집중했습니다. 중간에 몇번 View에 대한 리팩토링을 하기는 했지만 코드 퀄리티는 전혀 신경 쓰지 않고 일단 기능을 구현하는데 집중했습니다. 원래는 아주 필수적인 기능인 단어 추가와 단어 공부 기능만 추가하고 바로 Phase 2로 넘어가려고 했습니다만 실제로 제가 일본어 공부를 하면서 ...
이번 포스팅에서는 외부 모듈 (Firebase)를 Protocol로 구현해보겠습니다. 지금 앱에서 사용하는 DB는 Firebase인데요. Firebase 안에 있는 메소드들을 그대로 가져다가 사용하게 되면 나중에 DB를 다른 것으로 교체하고자 할 때 Service 단의 메소드들을 전부 다 다시 구현해야할 수 있습니다. 따라서 Protocol을 활용해서 Fi...
지금까지 포스팅을 통해서 protocol을 활용해서 Service 객체와 DB 객체를 만들어두었습니다. 이제 해당 객체를 필요한 곳에 주입하는 Dependency Injection을 구현해야 합니다. 어떻게 구현했는지 한번 보겠습니다. Dependency 객체 만들기 우리가 구현한 Service 객체는 총 3종류입니다. 모든 객체를 하나하나 init에 ...
이전까지 Service들을 Protocol로 구현해보았습니다. 이제는 Model들을 Protocol로 구현해보도록 하겠습니다. Protocol 구현하기 model은 상대적으로 아주 쉽습니다. let으로 선언하는 property들은 getter만 정의하고 var로 선언해서 재할당할 property들은 setter도 정의해주어야 합니다. 아래 Word의 ...
🎉 1.6.0 버전으로 업데이트 되었습니다.
🎉. 지난 번에 규칙적인 복습을 위해서 1.6.0 버전을 업데이트 했었는데요. 제가 생각하는 복습을 완벽하게 구현하기에는 아직 부족한 점이 좀 있는 것 같아서 빠르게 1.7.0 버전을 준비했습니다.
[Phase 1]이 끝났습니다. 거의 3개월에 거친 단어장 개발의 1단계가 끝났습니다. 원래는 1달 컷으로😅 빠르게 주요 기능만 개발하고 끝내려고 했는데 하다보니까 이런저런 기능에 욕심이 생겨서 상당히 오랜 기간 진행하게 되었네요. 회사를 다니면서 사이드 프로젝트를 하는 것도 쉽지 않았고요. Test가 필요하다!!! 다양한 기능을 추가하면서 앱이 ...
Mock 객체가 필요한 이유: Test는 독립적으로 이제 ViewModel에 대한 Unit Test를 본격적으로 작성해보고자 하는데요. 이 작업을 위해서는 Unit Test의 대상 즉 ViewModel이 의존하는 객체를 Mocking해야 합니다. 즉 가짜 객체를 만드는 일입니다. 이러한 Mock이 필요한 이유는 Unit Test는 독립적으로 실시되어야 ...
테스트는 독립적이어야 한다! 지난 번에 Mocking에 대해서 포스팅을 하면서 해당 멘트를 적었던 것 같은데요. 이번 포스팅에도 이 원칙은 적용이 됩니다. 이번에는 Test를 전체 하나로 보지 말고 테스트 클래스 안에 있는 각각의 Test를 별개의 테스트로 보도록 합시다. 이 경우에도 마찬가지로 각각의 Test는 서로 독립적이어야 합니다. 하나의 Tes...
이 테스트의 단점: 특정 String에 테스트가 의존 아래 테스트를 보도록 하겠습니다. 두 번째 context 안에 있는 테스트를 보시면 viewModel.bookName에 특정한 문자열을 할당하고 있습니다. 그저 empty 여부에 따라서만 변수의 값이 정의되는 이런 간단한 테스트에서는 문제가 없지만 어떤 테스트에서는 문자열의 길이, 영문/한글 여부 등에...
에러 메시지 Unit test를 작성하고 실행할 때 위와 같은 에러가 발생했습니다. Firebase가 없다는 것이었는데요. 저는 분명히 Test를 위한 코드 어디에서도 import Firebase를 하지 않았는데 말입니다. Test가 Firebase가 있어야지만 실행이 된다는 것도 찝찝하고 말입니다 😭 별 짓 다해봤는데… 거의 3일 간을 이 에러를...
기존의 Protocol과 Model Test를 작성하면서 외부 모듈에 의존성을 최대한 끊어내는 방식으로 코드를 작성하고 있으니 Model 부분에 하나의 문제가 있었습니다. 바로 Model에 정의된 property들이 Firebase에 정의된 객체들을 사용하고 있다는 것이죠. 이렇게 되면 만약에 앱에서 Firebase를 사용하지 않게 되면 Model 자체를...
구현하고자 하는 기능 이번에 구현하고자 하는 기능은 각각의 단어장을 나타내는 Cell에 단어장을 만든 날짜를 표시하는 것입니다. 즉 오늘 만든 단어장이면 우하단에 今日(오늘)이 뜨도록 하고 어제 보다 이전에 만든 단어라면 n日前이라고 표시하는 기능입니다. Date와
🎉. 아직 추가하고 싶은 기능이 많이 있는데요. 일단은 살짝 쉬어가는 느낌으로 몇가지 버그만을 수정했습니다. 1.7.1 버전의 패치노트입니다. 단어 추가 화면에서 closed된 단어장 보이지 않음 예전에 단어 추가 화면에서는 closed된 단어장을 picker로
Unit Test를 만들다가 랜덤 Date를 구현할 필요성이 생겼습니다. 하지만 너무 터무니 없는 랜덤 Date를 만들면 테스트에 지장이 있을 수도 있으니 일단 오늘로부터 1년 이내의 날짜 중에 하나를 랜덤으로 뽑고자 합니다. 이 기능을 만들기 위해서 Date의 tim
🎉. 1.8.0 버전의 패치노트입니다. 사용을 하면서 불편했던 점 몇가지를 추가하고 오랫 동안 벼러왔던(?) 사이드 바 메뉴를 추가했습니다. (사이드 바의 경우 아직 개선하는 중입니다.) 미래의 단어장의 오늘의 학습에 추가되는 것을 방지함 제가 하루에 50개 단어
이번 포스팅에서는 사이드 바 메뉴 만들기를 해보도록 하겠습니다. 이번 포스팅이 완전한 사이드 바 메뉴는 아니지만 일단 최소한의 기능을 가지고 있는 사이드 바 메뉴를 만들어 보도록 하겠습니다. 예전에 개인 프로젝트에 사이드 바 메뉴를 활용한 적이 있는데요. 그 때는 외부 라이브러리를 활용해서 구현을 했습니다. 이번에는 직접 구현해보고자 합니다. UI 구현...
기존의 단어장에 한자와 한자를 풀어서 읽은 히라가나를 둘 다 저장하기 위해서는 일본어를 2번 입력해야 했습니다.
JLPT를 준비하면서 문자어휘 파트를 공부할 때는 미리 많은 양의 단어를 외우고 문제를 풀어야 합니다. 그래서 문자어휘 파트 교재는 많은 단어를 포함하고 있습니다. 저는 이 단어를 미리 저장해두고 하루에 50개 씩 외우고 있는데요. 문제는 이 단어를 미리 다른 단어장에 저장해두고 오늘 공부할 50개만 빼오려고 할 때 기존의 기능을 활용해서 이동시키려면 상...
🎉. 1.9.0 버전의 패치노트입니다. 이번 패치에는 지난 번 버전에서 기능을 하나만 추가한 버전인데요. 하지만 아주 강력한 기능을 하나 추가했습니다. 개인적으로 너무나 맘에 드는 기능인데요. 한번 소개해보도록 하겠습니다. 한자 → 가나 자동 변경 제 단어장은 한
🎉. 1.10.0 버전의 패치노트입니다. 이번 패치는 제가 실사용을 계속 하면서 불만이었던 부분을 모아서 앱을 수정했습니다. 단어를 선택하고 다른 단어장으로 이동하는 기능 이전 버전까지에서는 단어를 이동시키기 위해서는 단어장을 마감하면서 틀린 단어를 이동하는 수
구현하고자 한 기능 sample 기능을 활용할 때 불편한 점이 있습니다. sample은 같은 단어를 입력했을 때 기존에 저장되어 있던 한자와 가나를 검색해서 보여주는 기능인데요. 이미 저장되어 있지만 다시 한번 공부하고 싶은 단어를 저장할 때 유용한 기능입니다. 다만 이 기능을 활용할 때 한자 field는 비어 있고 가나 field에 한자와 가나가 모두 ...
왜 그의 블로그 포스팅은 멈췄는가? 포스팅은 멈췄지만 끝임 없이 달리고 있던 그의 토이 프로젝트 후기!