회고

[2023년 1분기] 그래서 뭐할건데? feat. riverpod vs bloc

paran21 2023. 7. 16. 23:04

최초 작성일 : 2023.04.13

 

나름 파란만장한 1분기를 보냈다.
정신없는 와중에 그래도 한번 정리하는 시간이 필요할 것 같아서 오랜만에 회고 글을 쓴다.

1.  난 뭘했는가

1분기동안 큰 이슈는 다음과 같다.
- 회사 일
- 사이드 프로젝트
- ios 공부


1) 회사 일은 회사일이다.

벌써 회사에서 일한지 반년이 지났다.
그 사이에 신규 서비스를 (가)오픈하고, 기획이 엄청나게 바뀌면서 날리고 새로 만든 것도 많고 수정도 많이 했다.
그리고 얼마전에 드디어 정식 오픈!!!!(광고가 나가기 시작했다)
물론 지금도 수정 예정인 부분들이 많은데, 좋은 방향으로 개선되고 있는 것 같아서 기대가 된다.

한참 일이 몰아치다가 약간 쉬어가는 템포가 반복되고 있다.
정작 일이 많을 때는 '와 일이 너무 많아.....' 하면서 퇴근까지 정말 정신없이 일하다가도, 정작 일이 주어지지 않으면 '뭔가 해야할 것 같은데... 시간이 안가...'하면서 조금 불안해하는 것 같다.
일이 주어지면, 일단 코드 만지는게 재밌고, 목적이 분명하니까 신나서 일하게 되는 것 같다.

지금 서비스는 거의 시작단계부터 같이 해서 코드도 거의 알고 있고, 플러터에도 익숙해져서 이것저것 해보고 있는데(자아가 생기기 시작했다), 다른 팀원으로부터 코딩 스타일을 좀 맞춰야 할 것 같다는 얘기를 들었다.
완전 놓치고 있던 부분이라 속으로 뜨끔하면서도, '회사 코드는 회사코드구나'라는 생각을 했다. 

코드리뷰를 하고 있긴 해도 회사 상황이 시간적으로 그렇게 여유있는 편이 아니라 거의 내 코드만 pr 때 리뷰를 받고 있는데, 정말 바쁠 때는 간단하게 넘어가는 경우가 많다.
리뷰를 받으면 내가 생각하지 못한 부분이 보여서 좋은데, 가끔 코멘트가 엄청 많이 달리면 살짝 멘탈에 상처를 받긴 한다. 

한가해질 때 전체적으로 코드를 좀 맞춰보자고 얘기는 나왔는데, 새로운 task가 나오면 아에 엎는 부분도 많아서 어떻게 될지 모르겠다.
코딩 스타일 얘기가 나와서 막 리펙토링하기에 조금 조심스러워졌다.

어쨌든, 일하는 건 그래도 괜찮은데, Flutter는 조금 불안불안하다.
push쪽에서도 계속 문제가 발생하고 있고, ios는 되는데 안드는 안되고 이런 부분이 꽤 있다.
플러터로 가능한데, 우리가 해결 방법을 못찾는거겠지..?


2) 사이드 프로젝트

사이드 프로젝트를 하게되었다!
원래 RN으로 서비스하고 있는 프로젝트인데, 작년에 출시된 이후로는 크게 수정이 없었고, 기존 개발 인원들이 프로젝트에 시간을 많이 쏟지 못하는 상황이라서 새로 개발 팀원을 구하게 되었다고 한다.
팀 내에서 flutter도 긍정적으로 얘기가 나왔고, 마침 내가 연락을 했을 때 괜찮을 것 같다고 판단을 해주셔서 아에 플러터로 새로 만들게 되었다.

일단 지금 있는 기능을 플러터로 만들고, 새로운 기능들을 추가하기로 했다.
회사에도 디자이너가 없는데, 기획자, 디자이너, 마케팅, 개발자가 모두 있다!
혼자 개발하다보니 자유도가 아주....높아서 마음껏 하고 싶은걸 하고 있다. 아니, 하고 싶었다.

일단 생각 못한 문제가 몇 가지 있었는데, 생각보다 일정이 빠듯하다는 것이다.
물론 사이드 프로젝트라 어느 정도 딜레이는 괜찮지만, 서비스가 지금도 신규 유입이 계속 있는 상황이라 개인적으로도 빨리 만들고 싶은 마음이 크다.
하면서 느끼는데 일단 스크린도 꽤 많은 편이고, 무엇보다 아직 내 역량이 많이 부족하다.

지금 회사 서비스야 초기부터 같이 했다고 해도 내가 들어갔을 때 이미 아키텍처는 어느정도 잡혀있었고, 환경세팅도 다 되어 있었다.
그런데 사이드 프로젝트는 완전히 내가 새로 만드는 거라서 구조 잡는 것도 한참 걸렸다.
graphQl도 처음써봐서 에러가 너무 많이 났고(지금도 타입 캐스팅 못해서 하드코딩이 너무 많다 ㅜㅜ), 아직 개발/운영 분리도 못했다(배포 전에는 해야지...)

특히 상태관리 패키지를 뭘 쓸지 한참 고민했다.
회사에서 riverpod을 사용하는데 개인적으로 bloc을 써보고 싶어서 해보다가 너무 오래걸려서 포기하고 riverpod으로 바꿨다.
사이드 시작하기전에 bloc도 조금 공부를 한 상태였는데, 프로젝트는 만들어본적이 없어서 오래걸리기도 했고, riverpod에서는 자연스럽게 할수있는 것들을 하기 어려웠다.

 

riverpod vs bloc

개인적으로 해결하지 못한 고민들은 다음과 같다.
- riverpod은 어떤 클래스나 provider로 만들면 ref만 있다면 어디서나 자유롭게 접근할 수 있는데 bloc은 정말 주입밖에 없는가..?
- bloc은 context로 접근을 해야해서 위젯에서 사용할 때는 편했는데, view model이나 그 아래 레이어에서 사용하는 클래스는 어떻게 접근을 해야하지??

final someRepositoryProvider = Provider((ref) {
  final someDataSource = ref.watch(someDataSourceProvider);
  return SomeRepository(someDataSource);
});

또, riverpod과 bloc은 코드량에서도 차이가 나는데, 간단한 state라면(예를 들어 bottom navigation index) riverpod이 코드량이 훨씬 적다.
(그런데 이 부분은 유지보수 측면에서는 다르게 평가할 수 있을 것 같다. 코드량이 더 많아도 관리는 더 쉬울 수 있으니까!)

riverpod을 쓰면서 비즈니스 로직과 ui가 잘 분리되지 않는다고 느꼈는데, 이번에 사이드 프로젝트하면서 만들기 나름인 것 같다는 생각을 했다.
로직이 잘 분리되지 않는다고 느낀 이유 중 하나는 위젯 안에 ref를 사용하는 부분이 많아지면서 어디까지가 로직인지 분명하지 않아 보인다는 것이었다.
그래서 이번에 사이드 플젝하면서 이 두 가지를 확실히 구분하려고 했다.

 

//ref.listen이나 callback 등은 모두 여기서 정의
class SomeScreen extends StatelessWidget {
  const SomeScreen({Key? key}) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    return const SomeView();
  }
}

//여기에는 ui만
class SomeView extends StatelessWidget {
  const SomeView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const Placeholder();
  }
}

 

또, riverpod이 업데이트되면서 추가된 기능들이 있는데, 이전보다 훨씬 사용하기 편해졌다.

특히 @riverpod 어노테이션이나 AsyncNotifier를 잘 쓰고 있다. -> 공식문서

 

Riverpod

 

docs-v2.riverpod.dev

//code generation을 통해 provider를 따로 만들지 않아도 된다.
@riverpod
class AsyncTodos extends _$AsyncTodos {
  Future<List<Todo>> _fetchTodo() async {
    final json = await http.get('api/todos');
    final todos = jsonDecode(json) as List<Map<String, dynamic>>;
    return todos.map(Todo.fromJson).toList();
  }

  //초기화는 여기서!
  @override
  FutureOr<List<Todo>> build() async {
    return _fetchTodo();
  }

  Future<void> addTodo(Todo todo) async {
    //여기 예제에는 없지만 여기서 ref로 다른 객체를 읽는 것도 가능하다.
    //final repository = ref.read(someRepositoryProvider);
    state = const AsyncValue.loading();
    //guard를 통과하지 못하면 무조건 AsyncValue.error()가 return된다!
    state = await AsyncValue.guard(() async {
      await http.post('api/todos', todo.toJson());
      return _fetchTodo();
    });
  }
}
class TodoListView extends ConsumerWidget {
  const TodoListView({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final asyncTodos = ref.watch(asyncTodosProvider);

// AsyncNotifier는 기본적으로 data, loading, error 상태를 지원한다.
    return asyncTodos.when(
      data: (todos) => ListView(
        children: [
          for (final todo in todos)
            CheckboxListTile(
              value: todo.completed,
              // When tapping on the todo, change its completed status
              onChanged: (value) =>
                  ref.read(asyncTodosProvider.notifier).toggle(todo.id),
              title: Text(todo.description),
            ),
        ],
      ),
      loading: () => const Center(
        child: CircularProgressIndicator(),
      ),
      error: (err, stack) => Text('Error: $err'),
    );
  }
}

처음에 graphQlService - datasource - repository - notifier 구조로 가다가 여기서 datasource를 빼기도 했고, @riverpod/AsyncNotifier 조합으로 코드량이 꽤 줄었다!(어제 너무 재밌게 리펙토링해서 아직 신난 상태)
물론 AsyncNotifier가 제공하는 loading/data/error외에 상태를 넣고 싶다면 그냥 새로 Notifier를 만드는게 낫겠지만 아직까지는 이걸로 충분한 것 같다.
원래는 loading에 데이터를 optional로 받게 만들어서 pagination같이 기존 데이터를 유지하면서 로딩 상태로 만들고 싶을 때 잘 썼는데, AsyncValue.loading()은 데이터를 못 받아서 이 부분은 좀 더 고민해봐야 할 것 같다.

어쨌든 이것저것 막 바꾸면서 재밌게 하고 있다.
그런데 퇴근 후에 하니까 아무래도 쓸 수 있는 절대적 시간이 부족하고, 일정은 마냥 미룰 수는 없어서 스트레스도 많이 받고 있다.
정말 재밌는데 스트레스도 많이 받는 이 아이러니😂
회사 코드는 맘대로 못하지만 이건 사이드니까 마음껏 하고싶은거 하는중!
개인적으로 테스트코드랑 fastlane을 해보고 싶다.


3) swift 공부하기

작년 말부터 swift 공부를 시작했었고, 인프런에서 앨런님 문법 강의를 듣고 있다(꽤 재밌게 들었다!!)
그런데 어쩌다 보니 사이드 프로젝트와 겹치면서 swift공부시간이 절대적으로 줄어들었다.
강의가 기한 제한이 있어서 막판에는 정말 빠듯하게 들었다😱
그래도 일단 문법 1회독은 완료했고, 사이드 플젝 급한 거 끝나면 ios에 본격적으로 시간을 더 투자해볼 생각이다.

 

2. 그래서 앞으로 뭘할건데?

사실 1분기 내내, 그리고 지금도 큰 고민은 앞으로 뭘 할거냐, 이다.
앞에도 살짝 언급을 했지만 flutter를 하면서 한번에 안드/ios를 만들어서 편하기도 하지만 그것 이상으로 챙겨야 할 것도 많다.
무엇보다 flutter로 앱개발을 시작하니 native지식이 너무  부족한 상태이고, 양쪽을 다 챙겨야한다는 것에 때때로 부담을 느낀다.
swift공부도 작년 말에 native를 공부해야겠다는 생각에 시작하게 되었는데, 앞으로 어떤걸 더 중점적으로 해야할지, 특히 커리어 측면에서 무얼 메인으로 가져가야할지 고민이 많다.

개인적으로는 서버나 웹 프론트도 해보고 싶은데(js/ts진영!) 이건 정말 개인적 흥미에 가까워서 나중을 기약하는게 맞는 거 같고, 정말 고민되는건 앱이다.

native는 안드로이드보다 ios가 지금은 더 관심이 있다.
그렇다면 다음 이직을 하게 된다면 flutter로 가야하나, ios로 가야하나🥲

ios로 가게되면 사실상 완전히 신입으로 가는거라 포폴도 만들어야 하고 준비해야할게 많다. 거기다 ios는 신입 채용공고도 많이 못봤다.
그렇게만 새로운 기술 스텍을 배우는데 가장 확실한 방법은 일을 하는 거라고 생각하기 때문에 ios 포지션으로 근무를 하게 된다면 ios 실력도 많이 늘 것이고, flutter를 완전히 놓지만 않는다면(사이드 플젝 등으로) 나중에 선택할 수 있는 옵션도 다양해질 것 같다.

반면에 flutter는 일단 지금 경력(아직 1년도 안되지만)을 계속 살릴 수 있고, 하이브리드 앱 특성상 스타트업에서는 분명히 수요가 있을 것 같다. 초기 프로토 타입을 만드는데는 플러터는 확실히 장점이 있다고 생각한다. 앞으로 플러터 시장도 더 커질 것 같고 고용도 더 늘어날 것 같다. 안드/ios 시니어 2명 뽑을 비용이라면 안드나 ios 경험있는 flutter 1명(+주니어)을 뽑지 않을까?
하지만 하이브리드이기 때문에 분명 불안정한 측면도 있다. 시장에서 기술스텍은 계속 바뀔 거고 내가 사용하던 기술이 없어져도 개발자로서의 경쟁력이 떨어지는 건 아니라고 생각하지만, 그래도 잘 이직할 수 있을지 걱정되는게 사실이다.

지금 회사가 도메인도 재밌고, 여러모로 나랑 잘 맞는다고 생각하지만 계속 여기 있을지는 알 수 없는거고, 어쨌든 계속 준비는 필요하다.
flutter로 계속한다고 해도 native 공부는 필요해서 일단 뭐가 됬든지 ios 공부는 계속 해야할 것 같다.

지금 하고 있는 사이드 프로젝트는 일단 5월말에는 배포를 목표로 하고 있고, 우선 순위가 높은 기능들을 우선 개발한다고 해도 6월이 지나면 어느 정도 정리가 될 것 같다. 이후에는 feature 단위로 간다고 하면 지금만큼 시간을 쏟지 않아도 될 것 같아서 그 때는 ios 공부에 더 시간을 많이 쓸 수 있을 것 같다.
일단 올해가 가기전에 ios 플젝 하나는 하는걸 목표로 해야겠다.

끝.

쓰다보니 정말 글이 길어졌다.
요새 회고글을 안써서 이렇게 할말이 많아진 것 같다.
그래도 쓰면서 스스로 정리된 부분도 많다.

그래도 앱보다는 웹이 더 전망이 좋지 않나, chatGPT를 보면서는 이제 개발자는 어떻게 되는 건가 등등 여기서 쓰지 못한 고민들도 많았는데, 걱정은 사서 할 필요가 없고 고민할 시간에 뭐라도 하는게 나을 것 같다.


코딩은 재밌지만 회사 일로 하는건 마냥 재밌지는 않은 것 같고, 그렇다고 사이드를 하니 놀 시간, 쉴 시간은 부족하다.
요새 너무너무 피곤 상태고 육체적/정신적으로 건강에 적신호가 올 것 같다는 생각도 진지하게 많이 했다.
하고 싶은건 너무 많고 하루는 너무 짧다😠
일 하는 시간을 줄이고 놀고 코딩하는 시간을 늘릴 수 있으면 얼마나 좋을까🥲