flutter No file or variants found for asset  에러

플러터에서 이미지 로딩이 안 될 경우

 

flutter:
  assets:
    - assets/images/

 

 

pubspec.yaml 파일에 assets 폴더를 인식할 수 있도록 작성.

그 때 모든 이미지 파일을 나열해서 작성하지 않고 그냥 이미지 폴더까지 등록해도 인식 가능

 

위와 같이 수정 후,

프로젝트 디렉토리에서 flutter clean 해준다.

 

만약 ios도 함께 개발중이라면 project directory 에서 flutter clean 완료된 후 flutter build ios도 실행

% flutter clean 
% flutter build ios

 

JS window.open() 명령어로 되어있는 웹을 flutter webview에서 실행시키기 위해 얼마나 오랜 기간을 삽질해왔는지 ㅠㅠㅠ

 

!!!!!!!! 드디어 해결책을 찾았다!!!! 

그래서 고생할 지도 모를 지구 어딘가의 flutter 개발자를 위해 글을 남긴다. 

 

새 창을 띄우기 위해서는 flutter webview 라이브러리가 아닌 InAppWebView를 사용해야한다.

그런데 마침 이번에 6.0으로 업데이트를 했다길래 냉큼 새 버전으로 탑승

 

https://inappwebview.dev/docs/intro

 

Getting Started | InAppWebView

Installation

inappwebview.dev:443

 

 

설치방법 생략

 

그리고 대망의 window.open() flutter app 에서 실행하기!!!!!!!!!

라이브러리 기여자들이 굉장히 예제를 성실하게 남겨주었다.

 

예제 참조:

https://github.com/pichillilorenzo/flutter_inappwebview_examples/blob/main/popup_window/lib/main.dart

 

flutter_inappwebview_examples/popup_window/lib/main.dart at main · pichillilorenzo/flutter_inappwebview_examples

A collection of flutter_inappwebview project examples - pichillilorenzo/flutter_inappwebview_examples

github.com

 

이것만있으면 뚝딱이다.

 

하지만 사람의 욕심은 끝이 없다. 아니 새 창을 띄웠으면 닫아야죠... 뒤로가기 버튼을 아무리 눌러도 안되는데 이거 머임ㅠ

안드로이드 뒤로가기 버튼을 백날 누르고 goBack() 함수를 불러도 먹히지 않았다.

그렇게 검색을 해서 찾아보면 willPopScope가 나온다.

 

However, But, Although . . .

willPopScope is deprecated. 

 

참고자료 : 

 

https://api.flutter.dev/flutter/widgets/WillPopScope-class.html

 

WillPopScope class - widgets library - Dart API

Registers a callback to veto attempts by the user to dismiss the enclosing ModalRoute. See also: Inheritance Annotations @Deprecated('Use PopScope instead. ' 'This feature was deprecated after v3.12.0-1.0.pre.') Constructors WillPopScope({Key? key, require

api.flutter.dev

 

그래서 친절하게 migration guide도 준비되어있다.

https://docs.flutter.dev/release/breaking-changes/android-predictive-back#migration-guide

 

Android predictive back

The ability to control back navigation at the time that a back gesture is received has been replaced with an ahead-of-time navigation API in order to support...

docs.flutter.dev

 

 

 

 

 

 

그래서 위의 레퍼런스를 참조해서 해결한 전체 코드:

 

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

//InAppWebViewController Singleton
class WebControllerSingleton {
  WebControllerSingleton._privateConstructor();
  static final WebControllerSingleton _instance = WebControllerSingleton._privateConstructor();
  factory WebControllerSingleton() {
    return _instance;
  }

  InAppWebViewController? _webController;
  InAppWebViewController? get webController => _webController;
  set webController(InAppWebViewController? controller) {
    _webController = controller;
  }
}

//main webView Screen
class InAppWebViewScreen extends StatefulWidget {
  const InAppWebViewScreen({Key? key}):super(key:key);

  @override
  State<InAppWebViewScreen> createState() => _InAppWebViewScreenState();
}

class _InAppWebViewScreenState extends State<InAppWebViewScreen> {
  final GlobalKey webViewKey = GlobalKey();

  final urlController = TextEditingController();
  final String loginUrl = "https://www.naver.com";
  String url = "";

  PullToRefreshController? pullToRefreshController;
  double progress = 0;

  InAppWebViewSettings settings = InAppWebViewSettings(
    isInspectable: kDebugMode,
    javaScriptEnabled: true,
    javaScriptCanOpenWindowsAutomatically: true,
    iframeAllowFullscreen: true,
    useOnDownloadStart: true,
    useOnLoadResource: true,
    clearCache: true,
    allowFileAccessFromFileURLs: true,
    allowUniversalAccessFromFileURLs: true,
  );

  @override
  void initState() {
    super.initState();

    pullToRefreshController = kIsWeb
        ? null
        : PullToRefreshController(
      settings: PullToRefreshSettings(
        color: Colors.black,
      ),
      onRefresh: () async {
        if (defaultTargetPlatform == TargetPlatform.android) {
          WebControllerSingleton().webController?.reload();
        } else if (defaultTargetPlatform == TargetPlatform.iOS) {
          WebControllerSingleton().webController?.loadUrl(
            urlRequest:
            URLRequest(
                url: await WebControllerSingleton().webController?.getUrl()),
          );
        }
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvoked: (didPop) async {
        print("------ try go back");
        await WebControllerSingleton().webController?.goBack();
      },
      child: Scaffold(
        body: Column(
          children: <Widget>[
            Expanded(
              child: InAppWebView(
                key: webViewKey,
                initialUrlRequest: URLRequest(url: WebUri(loginUrl)),
                onWebViewCreated: (controller) {
                //init controller
                  WebControllerSingleton().webController = controller;
                },
                initialSettings: settings,
                pullToRefreshController: pullToRefreshController,
                onCreateWindow: (controller, createWindowAction) async {
                  showDialog(
                    context: context,
                    builder: (context) {
                      return WindowPopup(createWindowAction: createWindowAction);
                    },
                  );
                  return true;
                },
              ),
            ),
          ],
        ),
      ),
    );
  }

}

//popup window class
class WindowPopup extends StatefulWidget {
  final CreateWindowAction createWindowAction;

  const WindowPopup({Key? key, required this.createWindowAction})
      : super(key: key);

  @override
  State<WindowPopup> createState() => _WindowPopupState();
}

class _WindowPopupState extends State<WindowPopup> {
  String title = '';

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      content: SizedBox(
        width: double.maxFinite,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Row(mainAxisSize: MainAxisSize.max, children: [
              Expanded(
                child:
                Text(title, maxLines: 1, overflow: TextOverflow.ellipsis),
              ),
              IconButton(
                  onPressed: () {
                    Navigator.pop(context);
                  },
                  icon: const Icon(Icons.close))
            ]),
            Expanded(
              child: InAppWebView(
                gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
                  Factory<OneSequenceGestureRecognizer>(
                        () => EagerGestureRecognizer(),
                  ),
                },
                windowId: widget.createWindowAction.windowId,
                onTitleChanged: (controller, title) {
                  setState(() {
                    this.title = title ?? '';
                  });
                },
                onCloseWindow: (controller) {
                  Navigator.pop(context);
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

 

 

나는 webViewController를 제어하기 위해 Singleton으로 만들어버렸다. 사실 onCreateWindow에서 새로 호출하는 AlertDialog를 Scaffold로 띄워보려고 시도했던 흔적이기도함.. 안드에서는 전체화면으로 잘 나오는데 ios에서는 정말 팝업으로 작게 나타나서 해결 시도중입니다. 해결책 아시는분 제발 글 써주세요.

 

 

예제로 적은 링크는 네이버. 대한민국 개발자라면 라인 지켜. 라인 망하면 다 망하는거야. 라인 보고있나? 저도 같이 일하게 해주세요. 저 영어도 할 수 있어요.

 

 

취업준비를 위해 오늘도 포트폴리오를 다듬다가 오프보딩에 관련한 글을 읽었다.

 

내가 이전회사에서 일을 한 시간은 1년 2개월이다.

 

짧다고 느낄 수 있는 시간이었지만 그 시간은 내게는 사실, 굉장히 길었다.

 

 

이전 회사에서 내가 처음 다룬 언어는 한번도 다뤄본 적 없었던 PHP였다.

그리고 다음날부터 혼자 프로젝트에 내던져졌는데, PHP 책 한권을 읽고 구글을 찾아가며 주어진 업무를 해냈다.

 

그 프로젝트는 클라이언트가 단순한 요청을 했던거라 일주일만에 완성할 수 있었지만 생각해보면 취업하고 바로 다음날부터 그냥 실무 최전선에 던져졌었다.

 

그리고 일주일 뒤에 나는 백엔드팀에서 담당하고있던 또 다른 웹 프로젝트의 한 섹션을 맡게되었다.

 

그 다음부터는 그냥 실전이었다.

 

나는 자바만 공부해서 왔는데 어쩌다가 이렇게 되었지?

 

생각할 시간조차 없었다. 당시 백엔드팀은 나 포함 셋 뿐이었다.

그리고 당장 한 달 뒤에 클라이언트와 발표 미팅을 해야했기에 할 수 있는 일을 해내는 데에 집중했다.

 

SQL문 작성과 PHP, JavaScript로 웹 프로젝트를 두 달정도 하고나니 업무에 익숙해지기 시작했다.

(그와중에 레거시 프로젝트를 유지보수하는 업무도 함께 담당했다)

 

그러다가 내 최고 업적을 만나게 되었다.

 

나는 들어온지 3개월 된 개발자인데 내 밑으로 신입 개발자 세명이 붙어서 함께 새로운 프로젝트에 매달렸다.

JPA를 활용해서 개발을 2개월 넘게 진행했는데 중간에 다 뒤엎고 MyBatis로 변경해서 다시 프로젝트를 진행하기도 했었다.

회사에서 10시간은 기본으로 일했고 12시간, 밤샘근무를 하며 회사 붙박이처럼 일했다.

분명 퇴근을했는데 출근시간까지 4시간 남아있고... 그랬었다.

 

그러면서 중간에 한 명은 퇴사했고 남은 셋이서 프로젝트를 완성시키기 위해 갖은 애를 다 썼다.

 

그러다보니 고객사 사람들과 미팅도 하게되고 일정과 관련한 개발기능 스케줄을 공유하기 위한 문서도 작성하게 되었다.

고객사에서 새로운 기능을 요청하면 개발이 가능할지 구현 방안에 대한 검색도 하게되었고 테스트 코드 작성과 개발의 구체적인 방향을 결정하게 되었다.

 

그렇게 나는 1년만에 백엔드 파트장이 되었다.

 

그냥 어쩌다보니라는 말밖에 나오지 않았다. 어떤 팀원은 미팅을 싫어했고 또 다른 팀원은 내게 자신의 의견을 전달하고 가장 중요한 타이밍에는 침묵했다. 그러다보니까 그냥 내가 다른 개발자의 대변인이 되었고 의견을 조율하고 스케줄을 짜고 프로젝트의 앞날을 고민하고 있었다.

 

그렇게 고생했던 프로젝트가 배포되자 실서버를 운영하며 고객사는 유지보수 기간에 편의성에 기반한 개발요청을 해오기 시작했다.

 

그 때 이 프로젝트를 함께 했던 팀원들이 퇴사를 하기 시작했다.

 

고작 셋뿐인 담당자였기에 둘이 퇴사하자 나만 남았다.

 

당시 채 1년을 채우지 못했지만 회사에서 살다시피 일했던 나여서 회사가 새로 뽑는 신입 백엔드 개발자들의 교육도 맡았다.

 

퇴사가 간절했지만 나는 차마 내가 그 고생을 하며 완성한 프로젝트를 그냥 놓고 떠날 수가 없었다.

심지어 그 프로젝트를 담당한 사람중 회사에 남은 사람은 나밖에 없었다.

 

 

그렇게 오프보딩 준비를 시작했다.

 

레거시 프로젝트를 하면서 날림으로 작성된 인수인계 문서를 보며 머리를 뜯던 과거를 생각하면 도저히 클릭부터 가르친 후임 개발자들에게 그런식으로 일을 주고가기 싫었다.

 

퇴사까지 한 달의 여유기간을 두고 인수인계 문서를 꼼꼼하게 작성했다.

서버에러 보는 방법, 서버에 배포할때 유의사항, 보안처리한 코드, 고객사에서 요청해서 만들수밖에 없었던 특이한 개발 요소, 기한 여유가 있어서 미뤄둔 업무 가이드...

 

심지어 사내 타 부서들과 협업하기 위한 요청 가이드문서까지 작성해놓고 후임자에게 퇴사 당일까지 하나하나 가르쳤다.

 

다행히(?) 퇴사 후 업무 관련 연락은 온 적이 없다.

 

오프보딩. 재밌는 말이다.

 

함께 타고있었던 배를 떠날 때 그 배에 머물 사람들이 앞길을 잘 찾아가길 바라며 나는 최선을 다 했다.

최선을 다 한 사람에게 후회는 없다.

 

 

 

 

만약 SQLite를 사용, 수정하는 와중 xcode의 가상 시뮬레이터가 fatal error를 띄우면서 경로가 잘못되었다고 나타났을 때

 

Core Data에서 변경된 데이터를 찾을 수 없어서 오류가 났다.

 

1. xcode에서 실행하던걸 멈춘다

2. 가상 시뮬레이터에서 빌드한 앱을 삭제한다.

3. 다시 실행한다.

 

위의 절차로 해결 가능

 

이 글은 다음 강의의 섹션 16을 수강 후 작성했습니다.

 

https://www.udemy.com/share/101WsW3@owgko3jlDak3QqRDGGVFONQqLCVZDrzwrvRo3zj13qk3X472hZkph3cjFTKpAIaoDQ==/

 

 


 

나는 비전공자라 터미널을 쓰는 걸 좋아한다.

무슨 상관이 있냐하면...

개발자같고 멋있기 때문이다.

 

 

이번 강의는 터미널 사용에 관련한 강의였다.

 

실무에서는 생각보다 터미널을 꽤 자주 써야한다.

그리고 난 백엔드 개발자였고 DB랑 서버 들어가서 로그 읽는 건 거의 매일했었다. 

이 강의에서는 mkdir이나 cd와 같은 명령어가 GUI환경에서의 어떤 것과 같은 일을 수행하는지를 차근차근 가르쳐준다.

 

갓 안젤라쌤, 만약 내가 개발을 처음 배우는 입장이었다면 실무에서 꼭 필요했을 부분을 채워주는 수업이었다.

 

 

 

 

이 글은 다음 강의의 섹션 15를 수강 후 작성했습니다.

 

https://www.udemy.com/share/101WsW3@owgko3jlDak3QqRDGGVFONQqLCVZDrzwrvRo3zj13qk3X472hZkph3cjFTKpAIaoDQ==/

 

 


 

 

섹션 15는 무려 5시간이 넘는 길이의 강의를 자랑한다. 

 

 

 

 

하지만 이번 모듈의 목표는 무려

 

채팅앱 5시간만에 완성하기!!

 

채팅앱 만드는 강의가 5시간이면 이건 엄청난 효율이 아닐까?

 

 

아무튼 끝이 창대한 모든 시작은 미비하다.

 

처음에는 앱에 애니메이션을 넣는 방법을 알려준다.

그리고 Cocoapod을 다운로드 받아서 프로젝트에 적용하고 cocoapod을 통해서 애니메이션을 적용하는 방법을 배웠다.

그렇게 cocoapod Dependency를 어떻게 적용하는지까지 학습을 하게되면

다음은 Firebase의 차례이다.

 

파베는 안드로이드로 채팅앱을 만들때 사용해봤는데 그 당시에는 그저 상사가 시키는대로하는 아바타였다.

그래서 뭘 알고 했던건 아니었는데 갓 안젤라쌤 덕분에 바로 이해하게 되었다.

 

이 강의에서는 자꾸... 공식 문서를 읽으라고 시키는데 그 덕분에 정석으로 어떻게 파이어베이스가 나의 앱에 적용되는지 상세하게 알 수 있다.

 

 

 

 

이번에 사용한 예제 앱은 'FlashChat'.

 

강의에서 제공하는 github에서 프로젝트를 받으면 이미 화면 4개가 만들어져있다.

학습이 진행되며 학생들은 Firebase Authorization를 공부하며 유저생성하는 방법을 배운다.

 

한창 백엔드 공부할때는 MySQL다운로드받고 터미널에서 DB user생성하고 쌩난리를치면서 프로젝트에 DB연결하고 그랬는데 앱 공부를 하니까 모두 생략하고 바로 Firebase Auth에 때려넣는 쾌감....!! 

 

그렇게 바로 DB해결하고 유저생성까지 2시간 학습이면 뚝딱이다.

 

진도빼는 속도가 아주 엄청나다.

 

 

그 다음은 채팅이다.

 

우선 채팅에서 사용하는 화면부터 만드는 작업을 배운다.

 

채팅에서 사용하는 View는 TableView로 안드로이드로 따지자면 RecyclerView가 되겠다.

정말 비슷하게도 여기에서 사용하는 CellView가 필요한데 이것도 그냥 학습순서를 계곡 물 흘러가든 몸을 맡기면 금방 배운다.

 

 

 

이제 채팅에 필요한 도구는 준비되었으니 채팅을 치면 Firestore에 저장하는 방법을 배운다.

 

Collection과 Document생성은 강의를 들으면 계속 공식문서를 읽게 시키거나 직접 읽어주신다.

그렇게 구글 문서에 적힌 Firestore의 활용 방법과 사용법을 꼭꼭 씹어먹으면 어느새 앱에서 채팅을 치면 내가 만든 파베에 데이터가 올라가고있다.

 

그리고 심지어 위에서 Auth로 유저생성 기능까지 만들어둬서 다른 사람과 대화하는 View컨트롤까지 해놓으면 진짜 순식간에 채팅앱 완성!

 

물론 특정 유저를 선택하는 중간단계가 없긴 하지만 Firebase를 활용한 채팅구현방법은 충분히 학습할 수 있다.

 

그리고 마지막으로 야무지게 키보드가 화면을 가려서 불편한 UX를 수정하는 방법까지 배웠다.

고마워요 세계의 지식인!

 

https://github.com/hackiftekhar/IQKeyboardManager

 

GitHub - hackiftekhar/IQKeyboardManager: Codeless drop-in universal library allows to prevent issues of keyboard sliding up and

Codeless drop-in universal library allows to prevent issues of keyboard sliding up and cover UITextField/UITextView. Neither need to write any code nor any setup required and much more. - hackiftek...

github.com

 

 

+ 그런데 애플은 이걸 따로 받아야해? 안드로이드는 그냥 주던데 애플 머함

'iOS' 카테고리의 다른 글

[iOS공부] 섹션 16: The Command Line and Terminal  (0) 2024.02.17
[iOS] Udemy Course: iOS & Swift  (1) 2024.02.12

 

개발하다 가장 화나는 순간이 언제인 지 아시나요?

 

남이 개발한 스파게티 소스 읽기?

촉박한 일정에 맞춰서 개발하기? 

 

물론 짜증나지만 아닙니다.

 

정답은

 

아주 쉬운 에러가 해결이 안될때

 

 

암튼 분명 cocoapod을 다운로드받고 설치 완료떴는데도 거지같은 맥이 pod 명령어 못알아 처먹을때 해결방법

 

 

https://stackoverflow.com/questions/73566730/how-to-resolve-error-command-not-found-pod-despite-cocoapods-successful-insta

 

How to resolve error "command not found: pod" despite cocoapods successful install?

I have run sudo gem install cocoapods. Lots of gems installed and no error shown. But despite that, when I run pod setup, I keep getting error "command not found: pod". I tried rerun the

stackoverflow.com

 

 

바쁜 당신을 위해 (될지 안될지 모르는) 3줄요약 

왜 될지 안될지 모르냐면 저는 해결을 위해 루비를 설치하고 지우고 brew를 통해서 다시 설치했기 때문 

암튼

 

 

1. brew 설치를 해보세요

2. 다음 코드를 적어보세요

brew link cocoapods

3. 위의 명령어도 안되면 이걸 적어보세요

brew link --overwrite cocoapods

 

그래도 안되면 파이팅!

 

최근 ios 개발 공부를 하고있다.

 

오른손을 한 일을 왼손이 모르게 하라는 속담이 있지만

 

내가 공부하는건 나 혼자 하고있어서 이러다가 진짜 아무도 내가 ios공부한걸 모를 것 같아 블로그에 매일 공부 기록을 남기려고한다.

 

플랫폼은 Udemy, 강사는 Dr. Angela Yu

리뷰도 많고 평점도 높고 맛보기 강의를 들었을때 괜찮아보여서 세일중에 질렀다.

 

https://www.udemy.com/course/ios-13-app-development-bootcamp/

 

 

 

강의는 내내 영어로 진행된다.

 

하지만 한국어 자막이 잘 되어있어서 문제없다.

 

그리고 만약 영어에 언어장벽을 크게 느끼지 않는 사람이라면 그냥 봐도 무방하다.

 

나는 자막없이 그냥 듣는게 더 편해서 영어로만 공부중인데, 코딩 관련 영단어를 익힐 수 있어서 더 좋다.

 

 

현재 섹션 14까지 완료한 상태인데 (총 36섹션이다) 지금까지 수강한 코딩 강의중 단연 1등! 최고이며 

 

코딩을 잘 모르지만 아이폰 개발을 해보고 싶은 사람에게 무조건 추천하고 싶은 강의다.

 

이유 1: 강의를 따라하는 게 재밌다!

- 처음 코딩을 하게되면 내가 뭘 하는지 눈에 잘 안들어와서 반응이 바로 오는 작업을 하는 게 더 흥미롭다. 그런데 처음에는 iOS앱의 view를 직접 만들고 수정하며  재미를 느끼게 해준다. 재미는 공부를 할 때 아주 중요한 요인인데, 초반에 하는 섹션중에 실로폰 앱만들기가 있다.

앱에서 view를 누를때마다 음이 나오는 코드를 작성하게 만들어서 그럴듯한 작업물을 만들 수 있게 유도하는데 그 과정이 쉽고, import와 라이브러리같은 중요한 개념들을 자세히 설명해준다.

 

이유 2: 실습 위주의 강의

- 코딩을 그냥 시키는대로 따라치기만하면 실력이 절.대. 늘지 않는다. 하지만 안젤라는 계속해서 학생들에게 직업 시도하게 하는 시간을 주고 목표를 설정해서 직접 해보도록 유도한다. 그리고 git에 올라온 프로젝트를 클론 받아서 수업이 진행되기 때문에 리소스를 찾거나 다운로드 받아 적용해야하는 것과 같은 것들에 시간을 소비하지 않아도 된다! 그리고 git 사용법도 알려줘서 더욱 추천

 

이유 3: 실무위주의 세심한 팁

- 사실 이렇게 글을 쓰게 된 이유중 가장 큰 이유는 이 부분이다. 안젤라는 강의를 진행하면서 굉장히 자연스럽게 개발자의 필수 요소들을 모두 알려준다. stackOverFlow에서 검색을 하는 방법과 코딩이 막혔을때 해결하는 방법, 팁, 그리고 MVC패턴까지 굉장히 자연스럽게 알려준다. 나는 백엔드 개발을 하면서 땅에 헤딩하며 이렇게 하는 게 맞는지 한 구석에 의문을 가진채로 일해왔다. 그런데 이렇게 iOS강의를 통해 여러번의 실습을 하며 강사가 개발 방법을 자연스럽게 녹여서 알려주는 게 좋아서 이렇게 추천 글까지 남기게 되었다.

 

 

한국에도 다양한 IT교육 플랫폼이 있다는 것을 알고있다.

 

하지만 Udemy는 세계에서 실력있는 강사들이 모여있는 플랫폼이다.

그리고 무엇보다 가장 중요한건, 경제적으로 부담이 덜하다.

 

물론 아직 강의 하나만 수강하는 입장에서 섣부른 추천일 수 있겠지만, iOS를 공부하고 싶다면 이 강의를 추천한다!

 

최근 개발자 풀이 늘어나면서 git을 사용하는 사람들도 증가하고 있다.

 

하지만 그 유명하고 편하고 좋다는 git! 

어떻게 사용해야 더 잘 사용할 수 있을까?

 

현업에서 git을  사용하면서 많은 개발자들이 고민, 또 고민했던 문제이다.

 

이제 git branch 전략을 통해 (나보다)똑똑한 사람들은 어떻게 깃을 사용하는지 알아보자.

 

 

깃 브랜치 전략이란?

 

 

깃을 사용하다보면 branch라는 개념을 알 수 있다. 나무의 가지를 뜻하는 영어이기도 하고, 프랜차이즈의 분점을 지칭하기도 하는 branch는 메인으로 사용하는 마스터 외의 브랜치를 의미한다.

 

깃 브랜치 전략은 바로 그 브랜치들을 어떻게 활용하는지 그 관리하는 방법 혹은 지침이라고 할 수 있다.

코드의 컨벤션이 존재하듯 깃도 어떻게 브랜치들을 사용할지 개발자 선배님들이 정의해놓은 활용 방법이다.

 

 

깃 브랜치 전략의 종류

 

깃 브랜치 전략은 많이 있지만 주로 사용되는 전략들을 살펴보자.

 

1. Git Flow 

2. GitHub Flow 

3. GitLab Flow

 

 

 

Git Flow

Git Flow 전략은 master, develop, feature, release, hotfix 등 다양한 브랜치 유형을 사용하여 복잡한 프로젝트를 관리할 수 있는 구조이다. 장기 프로젝트에 적합하고 여러 사람들이 협업을 진행할 때 효과가 좋다. 각 브랜치마다 역할을 명확하게 나눠서 각자의 branch에서 업무를 진행하고 그 용도에 맞는 branch에 merge를 진행한 뒤 이전 개발하던 branch를 삭제하므로 꼬일 위험도 줄어든다.

 

 

GitHub Flow

GitHub Flow 전략은 main 브랜치를 주로 사용한다. 그러다가 각 작업이나 기능 개발을 위한 브랜치를 생성하여 작업을 진행한 후 main branch에 병합한다. 이후 작업했던 branch는 삭제한다.

단순한 구조로 되어있고 CI/CD와 관련있는 프로젝트에 적합한 전략이다.

 

 

 

GitLab Flow

GitLab Flow 전략은 GitFlow와 GitHub Flow를 섞은 전략으로 생각하면 이해하기 쉽다. GitLab은 웹 기반의 Git 리포지토리 관리 시스템으로 다양한 서비스를 제공하고 있다. GitLab Flow는 GitLab 환경에서 사용되는 전략으로 유연한 작업 흐름을 제공한다. production 브랜치가 있다는 것이 특징으로, production 브랜치는 배포를 위한 브랜치이다. 

담당자들은 feature branch에서 개발을 진행하고 완료되었을 경우, 의논을 통해 병합을 하는 방식으로 진행한다.

 

 

 

브랜치 전략은 프로젝트와 각 조직에 따라 변경될 수 있다. 따라서 어떤 브랜치 전략이 지금 진행하고 있는 프로젝트에 적합한지는 구성원들이 함께 노력해나가면서 만들고 변경해나가야 한다고 생각한다.

 

 

참고 사이트 

 

https://docs.github.com/en/get-started/quickstart/github-flow

 

GitHub flow - GitHub Docs

GitHub flow is a lightweight, branch-based workflow. The GitHub flow is useful for everyone, not just developers. For example, here at GitHub, we use GitHub flow for our site policy, documentation, and roadmap. To follow GitHub flow, you will need a GitHub

docs.github.com

 

https://about.gitlab.com/topics/version-control/what-is-gitlab-flow/

 

What is GitLab Flow?

Code reviews ensure developers ship the highest quality code through systematic assessments designed to identify bugs.

about.gitlab.com

 

https://techblog.woowahan.com/2553/

 

우린 Git-flow를 사용하고 있어요 | 우아한형제들 기술블로그

{{item.name}} 안녕하세요. 우아한형제들 배민프론트개발팀에서 안드로이드 앱 개발을 하고 있는 나동호입니다. 오늘은 저희 안드로이드 파트에서 사용하고 있는 Git 브랜치 전략을 소개하려고 합

techblog.woowahan.com

 

'깃허브' 카테고리의 다른 글

[github] 깃으로 하는 협업: 코멘트 남기기  (0) 2022.08.02

 

클린코드, 그게 대체 뭐지?

 

말로는 참 많이 들어봤다. 클린코드.

중요한 것도 알고있다.

 

하지만 어떻게 해야하는지 전혀 감도 안 잡히고 대충 개념은 알겠는데 그래서 어떻게 하라고?

이런 상태로 있다가 알게된 곳이 있다. NEXTSTEP.

 

https://edu.nextstep.camp/

 

NEXTSTEP

 

edu.nextstep.camp

 

 

단위테스트와 클린코드 작성을 한번에 배울 수 있는 강의가 있다고 해서 바로 신청했다.

마침 가격도 나쁘지 않아 신청했는데 왠걸...

 

안드로이드와 간신히 웹개발 프론트삼총사 CSS, JS, HTTP를 공부하던 내게 신세계가 펼쳐졌다.

 

자바 플레이그라운드 with TDD, 클린코드

 

 

현재 모각코에서 만난 스터디원과 노션을 통해 일정을 관리하고 코드리뷰를 병행중에 있다.

junit을 처음 써봤는데 알면 알수록 정말 재밌다!!

 

아직 클린코드라고 하기에는 부족한 실력이지만 지향점이 어디인지, 어떻게 나아가야하는지 감을 잡아가기 좋은 강의라 적어본다. 

모두를 위한 파이썬 <PY4E 2022>

 

모두를 위한 파이썬 <PY4E 2022>

부스트코스 무료 강의

www.boostcourse.org

 

6주간의 여정이 드디어 끝났다!!

 

부스터로 참가했지만 리드부스터가 되어 이렇게 끝까지 완주를 할 수 있어서 정말 뿌듯하다.

 

짧다면 짧은, 길다면 긴 시간을 함께 해준 우리 팀원들과 코치님, 그리고 운영진에게 감사한 마음뿐이다.

 

 

어떤 경험을 했는가?
  1. 리더로서 스터디를 이끌어봤다.
  2. 새로운 언어를 다른 사람들과 함께 공부해봤다.
  3. 코드리뷰를 진행, 경험해봤다.
  4. 깃허브로 협업을 했다.
  5. 파이썬의 기초를 익힐 수 있었다.

 

 

경험을 통해 배운 점

 

1. 리더로서의 경험

 

나는 보통 팔로워에 가까웠기에 이렇게 적극적으로 리더 활동을 해본 경험은 많지 않았다.

하지만 이 경험을 통해 나는 팔로워와 리더 모두 제대로 수행해 낼 수 있는 사람이란 걸 깨닫게 되었다.

사람들에게 도움을 주는 행동은 내게 동기부여를 하게 해주었고 리더라는 타이틀이 그 시너지를 낼 수 있게 도와주었다.

 

그래서 더욱 리더로서 열심히 활동을 할 수 있었고 팀원들에게 배울 수 있음에 감사하며 더욱 적극적으로 행동할 수 있었다. 이 경험으로 나는 내가 팔로워 뿐만 아닌 리더로 활동하는 역할도 해낼 수 있다는 자신감과 확신을 얻게되었다.

 

 

 

2. 새로운 언어를 함께 공부한 경험

 

대부분의 경우, 새로운 언어를 공부한다면 대부분 강의를 통해 스스로 학습한다.

하지만 운 좋게도 나는 많은 사람들과 함께 같은 언어를 슬랙을 통해 소통하며 배울 수 있는 기회를 얻었다.

이를 통해 다양한 배경시직이 있는 사람들과 소통하며 새 언어를 배우는데 어떻게 접근을 하는지 알아볼 수 있었다.

 

새 언어를 습득할 때 가장 중요한 건 '구체적인 기능을 구현'해보는 것이다. 그것도 사람들과 함께 한다면 더욱 효율적이다!

해당 기능을 구현하기위해 나는 리더로서 적극적으로 검색을 하며 기존 강의에서 알게된 지식보다 더 많은 것을 알게되었고, 다른 사람들의 그 기능을 구현하기 위해 어떻게 접근했는지 피드백을 통해 배울 수 있었다.

 

앞으로 내가 언어를 공부하게 된다면 기초 지식을 학습함과 더불어 같은 언어를 공부하는 사람을 모집하고, 함께 예제를 풀며 서로의 코드를 통해 발전해가는 것이 가장 이상적인 학습방법임을 알게되었다.

 

 

 

3.  코드리뷰

 

코드리뷰에 대해 많이 알아볼 수 있었다.

코드리뷰는 내가 리더가 되었을때 꼭 해야겠다고 마음먹은 팀활동이며 가장 신경쓴 부분이었다.

그렇기에 코드리뷰에 대해 다른 사람들의 경험담을 긴 시간 찾아보며 읽었고 다른 사람들에게 코드리뷰의 방향성과 진행 방안에 대해 자문도 구해보았다.

 

결과적으로 코드리뷰는 매 회를 거듭할수록 발전했다! 

학습은 결과도 중요하지만 '학습하는 법을 학습'하는 것이 중요하다고 생각한다.

우리 팀은 전부 코드리뷰를 처음해봤다. 처음에는 엉망이었는데 이후 개선 방안을 꾸준히 업데이트하며 우리 팀의 코드리뷰 시간은 시간이 지날 수록 더욱 서로에게 도움이 되는 시간이 되었다.

 

솔직히 부스트코스를 통해 내가 배웠던 것들 중 가장 값진 경험은 바로 코드리뷰 진행 경험이라 생각한다.

언제 또 이렇게 코드리뷰를 통해 내가 발전하고 있음을 느낄 수 있을까? 

 

서로를 존중하는 코드리뷰 - 피드백을 통한 발전 - 도움을 주고받음으로 인한 성취감 - 과업의 적극적 수행

 

위와 같은 절차를 경험할 수 있었다는 점에서 나는 정말 운이 좋았고 함께 개발하는 것이 얼마나 즐거운 일인지 알 수 있었다.

 

 

 

4. 깃허브를 통한 협업

 

우리팀의 과제 제출은 깃허브를 통해 이루어졌다.

a. 주차별 과제를 개별적으로 풀이한 다음, 깃허브에 업로드한다.

b. 시간을 정해 줌으로 코드리뷰를 진행한다.

c. 수정한 파일을 취합해 fin파일을 업로드한다.

d. 화요일에 해당 링크를 제출한다.

 

처음 깃허브는 내 개인 레포지토리에 올리도록 되어있었다. 하지만 공통의 과제 제출 파일들인데 개인 레포지토리로 업데이트 되는 것을 수정하기 위해 알아보다가 단체 레포지토리(Organization Repository)의 존재를 알게되었다.

 

나는 처음으로 깃허브 저장소를 단체 레포지토리로 바꿔 보았고, 우리의 팀 과제물 제출 저장소가 만들어졌다. 그 외에도 깃허브 사용법을 학습할 수 있는 기회를 가질 수 있었다.

 

 

 

5. 파이썬의 기초 학습

 

당연히 내가 참여한 부스트코스는 '모두를 위한 파이썬' 이므로 파이썬에 대해 배우게 되었다.

자바와 http, js, css 언어만 다뤄본 내게 파이썬은... 정말... 신세계였다.

 

없는 게 없고 안되는 게 없는데 심지어 짧고 쉽다!

 

게다가 딕셔너리는 정말 재밌는 타입이다. 자바만 다뤄봤던 내게 딕셔너리는 알면 알수록 신기한 타입이라 팀 과제를 수행할때 자주 활용해서 써봤다.

팀 과제를 수행하기 위해 강의 내용 외의 다양한 내장함수를 활용해 볼 수 있었는데, 그 경험을 통해 파이썬에 대해 더욱 많이 알 수 있었다.

 

 

 

코칭스터디를 마치며

 

과거의 내가 코칭스터디에 등록한 걸 매우 칭찬하고 싶다. 

나는 이 스터디를 진행하며 다양한 경험을 할 수 있었고 코딩을 어떻게 해야 즐겁게 할 수 있는지와 같은 방법도 알게되었다. 지난 6주간의 여정을 함께 해준 팀원들에게 정말 감사하다는 말을 전하고 싶다.

 

 

그리고 매번 섬세한 피드백을 주셨던 턴태코치님! 수고하셨어요! 

+ Recent posts