벨로그를 탐방하다가 좋은 글을 발견했다. 함께 일하고 싶은 사람이라는 글인데

최근 이직을 한 나로서는 읽고 느낀점이 많았다. 전 직장의 동료들은 돌이켜 생각해보면 모난 구석 하나 없고

정말 다들 좋은 사람들이었던것 같다. 현직장 사람들은 어떤지 모르겠지만 나는 좋은 동료가 되도록 노력해야 겠다.

 

https://velog.io/@city7310/%ED%95%A8%EA%BB%98-%EC%9D%BC%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%9D%80-%EC%82%AC%EB%9E%8C-1.-%EC%97%85%EB%AC%B4-%EC%8A%B5%EA%B4%80-w1mfhsf2

 

요약문인데 이것만 읽어도 좋을것 같다.

 

  1. 질문 막 하지 말고, 최대한 탐구하고 정리해서 가져가자.
  2. 물어볼 때까지 기다리지 말고, 웬만한 건 먼저 얘기하자.
  3. 옳은 일이 일어날 때까지 계속해서 대화할 의무가 있다고 생각하자.
  4. 말에 배려를 담자.
  5. 안 되는 이유를 찾을 시간에, 되게 만들기 위한 리소스를 요청하자.
  6. 문제 해결만큼 재발 방지도 중요하다.
  7. 딴지 걸거나 훈수 두는 식으로 피드백하지 말고, 근거, 사례, 대안을 구체적으로 제시하자.
  8. 실험해서 숫자를 뽑아낸 뒤, 이야기가 아니라 사실을 기반으로 의견을 내자.
  9. 동료의 평가가 가장 정확하다.
  10. 기술에 당연한 것은 없으니 항상 이유를 고민하자.
  11. 내 의견에 고집을 부리지 말고, 토론이 올바른 결론을 낼 수 있도록 돕자.

FLUTTER BLOC 패턴에 대해서 공부해 보면서 공식 dev 에 있는 예제를 따라 해보고 있었다.

그러던중 

The argument type 'Object' can't be assigned to the parameter type 'PostStatus'.

라는 에러를 봤다 아마 이런 류의 에러는 타입이 맞지 않아서 보통 나올것이다.

 

나의 경우에는

import 'package:equatable/equatable.dart';
import 'package:practice_bloc_infinitescroll/posts/models/post.dart';

enum PostStatus { initial, success, failure }

class PostState extends Equatable {
  final PostStatus status;
  final List<Post> posts;
  final bool hasReachedMax;

  const PostState({
    this.status = PostStatus.initial,
    this.posts = const <Post>[],
    this.hasReachedMax = false,
  });

  PostState copyWith({
    PostState? status,
    List<Post>? posts,
    bool? hasReachedMax,
  }) {
    return PostState(
      status: status ?? this.status,
      posts: posts ?? this.posts,
      hasReachedMax: hasReachedMax ?? this.hasReachedMax,
    );
  }

  @override
  String toString() {
    return 'PostState{status: $status, posts: $posts, hasReachedMax: $hasReachedMax}';
  }

  @override
  List<Object> get props => [status, posts, hasReachedMax];
}

에서 status: status ?? this.status, 라는 부분에서 에러가 나고 있었다. 코드를 보면 중간 부분에 있다.

에러가 난 부분을 아무리 고치려고 해도 안 고쳐졌는데 천천히 읽다 보니까 나의 오타를 발견했다.....

위에 copyWith 라는 메서드의 parameter를 받을때 PostStatus 라고 타입을 명시 해야 되는데 바보 같이 PostState로 했다...

너무 비슷하자나..... 그래서 아래와 같이 고쳤다.

 

import 'package:equatable/equatable.dart';
import 'package:practice_bloc_infinitescroll/posts/models/post.dart';

enum PostStatus { initial, success, failure }

class PostState extends Equatable {
  final PostStatus status;
  final List<Post> posts;
  final bool hasReachedMax;

  const PostState({
    this.status = PostStatus.initial,
    this.posts = const <Post>[],
    this.hasReachedMax = false,
  });

  PostState copyWith({
    PostStatus? status,
    List<Post>? posts,
    bool? hasReachedMax,
  }) {
    return PostState(
      status: status ?? this.status,
      posts: posts ?? this.posts,
      hasReachedMax: hasReachedMax ?? this.hasReachedMax,
    );
  }

  @override
  String toString() {
    return 'PostState{status: $status, posts: $posts, hasReachedMax: $hasReachedMax}';
  }

  @override
  List<Object> get props => [status, posts, hasReachedMax];
}

그랬더니 너무나도 쉽게 문제 해결!!!!

역시 에러 이유를 읽고 천천히 코딩을 하면 이런 에러는 안날듯...

그리고 너무 이름이 비슷해서 ㅠㅠ 네이밍에 조금 신중할 필요가 있다는 것을 다시 깨달았다.

매일 GITHUB 만 쓰다가 회사에서 GITLAB을 쓰네??

하지만 같은 git이니까 뭐 차이 없겠지 하고 아무렇지 않게 사용중이었다.

 

스크립트 하나를 공통으로 만들라는 업무를 받아서 git 그룹에 있는 레포에 하나의 새로운 프로젝트를 만들어서

연동도 하고 첫 푸시도 잘 됬다

첫 푸시 내용은 "추가: :tada: 첫 커밋" 이라고 푸시를 했더니 잘 됬다 그래서 어 뭐 큰 차이는 없구만 하고 사용중에.....

위와 같이 에러가 났다 여러번을 시도 했지만 일단 안되는걸로..... 

안되는 이유는 위와 같이

remote: GitLab: Commit message does not follow the pattern '(Revert*|Merge*|[feat|fix|refactor|docs|test|etc]: [^\s].*)'

커밋 메세지가 패턴에 안 맞는다는 건데 ㅠㅠ 이번에 내가 커밋한 메시지를 확인했다.

git log

위와 같이 치면 내가 커밋한 마지막 메시지랑 로그들을 볼 수 있다.

 

별 내용 없는뎁쇼???.... 작업중 ??? 이모지??? 그정도인뎁숑 뭐가 틀렸다는 거지???ㅠㅠ 

 

일단 안되니까 커밋을 되돌린다.

git reset HEAD

위의 명령어로 되돌린다. 만약 여러개의 커밋이 있었다고 가정하면 뒤에 ~2 같이 숫자를 붙이면 갯수 만큼 되돌릴수 있다.

Ex) git reset HEAD~4

 

그 후에 내부적으로 커밋에 대한 규정이 있나 봤더니..일단 어디에 있는지는 찾지 못했지만

다들 feat: 커밋내용 과 같이 커밋중이었고 나도

feat: 작업중 이라고 커밋후 푸시했더니 잘 되었다.... 

아마 내부 메세지 정책이 있는거 같다.

 

그리고 내부 규칙? 같은걸 찾아 보다가 commit 에 대한 규칙 8개를 발견했다. 이는 꼭 해야 되는건 아니고 권장 사항인거 같다.

https://climbplant39.tistory.com/36

 

Commit Message 규칙

Commit 메시지 규칙은 커밋 로그 가독성, 협업 리뷰 과정, 코드 유지 보수를 위해 진짜 꼭 필요하다. Commit Message 규칙 8개 제목 본문 한줄 띄어 분리 제목 50자 이내 제목에 마침표 금지 제목은 구문

climbplant39.tistory.com

위의 글은 재미로 읽어 보는것도 좋을것 같다.

 

참고

https://docs.gitlab.com/ee/user/project/repository/push_rules.html#validate-commit-messages

 

Push rules | GitLab

Documentation for GitLab Community Edition, GitLab Enterprise Edition, Omnibus GitLab, and GitLab Runner.

docs.gitlab.com

를 참고하니 뭔가 있긴한가보다....

사용자가 모바일 애플리케이션에서 애플리케이션을 실행할 때 떄때로 certificate_verift_failed 라는 오류가 무작위로 발생하기 시작합니다. 따라서 아래에 해결 방법을 설명하겠습니다.

 

내가 찾은 방법은 모든 인증서를 허용하는 것입니다.

main.dart 파일에서 다음 클래스를 추가하거나 가져옵니다.

class MyHttpOverrides extends HttpOverrides {

  @override
  HttpClient createHttpClient(SecurityContext? context) {
    return super.createHttpClient(context)..badCertificateCallback
    = (X509Certificate cert, String host, int port) => true;
  }

}

그 다음은 기본 함수에서 함수 정의 뒤에 다음 줄을 추가합니다.

    HttpOverrides.global = MyHttpOverrides();

 

dio 라이브러리를 사용하는 경우 아래와 같이 수행하면 됩니다.

Dio dio = new Dio();
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
    (HttpClient client) {
  client.badCertificateCallback =
      (X509Certificate cert, String host, int port) => true;
  return client;
};

 

혹은 아래와 같이 실행할 수 있습니다.

import 'package:http/io_client.dart';
import 'dart:io';
import 'package:http/http.dart';
import 'dart:async';
import 'dart:convert';

    Future getAccessToken(String url) async {
      try {
        final ioc = new HttpClient();
        ioc.badCertificateCallback =
            (X509Certificate cert, String host, int port) => true;
        final http = new IOClient(ioc);
        http.post('url', body: {"email": "xyz@xyz.com", "password": "1234"}).then(
            (response) {
          print("Reponse status : ${response.statusCode}");
          print("Response body : ${response.body}");
          var myresponse = jsonDecode(response.body);
          String token = myresponse["token"];
        });
      } catch (e) {
        print(e.toString());
      }
    }

 

가장 좋은 방법은 믿을수 있는 호스트로부터의 certificate 만 허용하는 것입니다.

그래서 만약 api host 가 api.my_app이라면 이 host만 허용합니다.

HttpClient client = new HttpClient();
client.badCertificateCallback = ((X509Certificate cert, String host, int port) {
 final isValidHost = host == "api.my_app";
 return isValidHost;
});

 

그래서 lib/_http/http.dart에서 Chopper로 직접 HttpClient를 전달할 수 없었습니다. ChopperClient는 ioclient.IOClient에 래핑된 생성자에서 HttpClient를 수신할 수 있습니다.

HttpClient webHttpClient = new HttpClient();
webHttpClient.badCertificateCallback = ((X509Certificate cert, String host, int port) => true);
dynamic ioClient = new ioclient.IOClient(webHttpClient);
final chopper = ChopperClient(
  baseUrl: "https://example.com",
  client: ioClient,
  services: [
    MfService.create()
  ],
  converter: JsonConverter(),
);
final mfService = MfService.create(chopper);

 

tls 1.3 request URL도 문제 없습니다.

import 'dart:io';

main() async {
  HttpClient client = new HttpClient();
  // tls 1.2 error
//  var request = await client.getUrl(Uri.parse('https://shop.io.mi-img.com/app/shop/img?id=shop_88f929c5731967cbc8339cfae1f5f0ec.jpeg')); 
  // tls 1.3 normal
  var request = await client.getUrl(Uri.parse('https://ae01.alicdn.com/kf/Ud7cd28ffdf6e475c8dc382380d5d1976o.jpg'));
  var response = await request.close();
  print(response.headers);
  client.close(force: true);
}

 

결론

KEEP FLUTTING!!!

One or more plugins require a higher Android SDK version.
...
android {
  compileSdkVersion 33
  ...
}

 

위와  같은 에러가 날 때가 있다. 그럴때는

project > android > app > build.gradle 에 가서

android {
    compileSdkVersion flutter.compileSdkVersion
    ndkVersion flutter.ndkVersion
    ...
    }

위 부분의 compildSdkVersion을 맞는 버전으로 바꿔주면 된다.

android {
    compileSdkVersion 33
    ndkVersion flutter.ndkVersion
    ...
    }

 

pub.dev는 라이크 순이나 사용 순으로 보여주기 때문에 내가원하는 기능의 패키지를 찾는 것은 어렵다 ㅠㅠ

그러다 찾은 사이트가 나에게 광명의 빛을!!

바로 FLUTTERGEM

이렇게 위와 같이 기능이나 어떤 특정한 기준으로 묶여서 내가 원하는 걸 찾을수 있다.!!! 완전 신세계!

게다가 UI도 이쁘다.

 

 

사이트 안으로 들어가면 이렇게 해당 관련의 패키지들이 쭉 나와 있고 지금은 캡쳐로 보이지만! 실제로는 애니메이션으로 그 기능들을 간략하게 보여주고 있다. 완전 강추다. 물론 pub.dev에 들어가면 다 있겠지만 기능별로 찾고 싶을때는

fluttergem을 이용하는게 좋아보인다.!

anroid studio의 terminal 로 git 명령어를 주로 쓰는데 git bash shell을 쓰니까 오류가 나온다.

명령어를 쓰고 지웠다가 다시 글을 쓰면 쓸때는 별 문제 없어 보이는데 push 했을때 문제가 나왔다.

난 위와 같은 글을 쓴적이 없는데 저렇게 나왔다. 한참을 그냥 저대로 쓰다가 쉽게 해결이 가능했다.

settings > terminal 에 shell path 에 위와 같이 shell 경로에 ""을 붙이고 -login -i 를 붙이면 된다.

"C:\Program Files\Git\bin\bash.exe" -login -i

flutter로 계산하다 보면  == 연산자와 is 연산자를 종종 사용하게 되는데 어떤때에 == 연산자를 사용하고 is 연산자를 사용하는지 알아보자.


== Operator

공식 사이트를 보면

The default behavior for all Objects is to return true if and only if this object and other are the same object.

Total: It must return a boolean for all arguments. It should never throw.

Reflexive: For all objects o, o == o must be true.

Symmetric: For all objects o1 and o2, o1 == o2 and o2 == o1 must either both be true, or both be false.

Transitive: For all objects o1, o2, and o3, if o1 == o2 and o2 == o3 are true, then o1 == o3 must be true.

라고 나와 있는데 결국 객체가 같은지 보는것이라고 한다.

 

is 

is 의 같은 경우는 객체를 검사하는것이 아닌 타입을 검사하는 것이다.

is 키워드 : 같은 타입이면 true를 반환하고 다른 타입이면 false를 반환.

is! 키워드 : 같은 타입이면 false를 반환하고 다른 타입이면 true를 반환.

 


간단한 예제 1

void main() {
  int a1= 1;
  int a2 = 2;
  int a3 =1 ;
  print(a1 == a2);
  print(a1 == a3);
  print(a1 == int);
}
false
true
false

 

 

 

간단한 예제 2

  int a1 = 1;
  double a2 = 2.2;
  print(a1 is int);
  print(a1 is double);
  print(a2 is int);
  print(a2 is double);
true
true
false
true

 

오류 1 

  int a1 = 1;
  double a2 = 2.2;
  print(a1 is a2);
Error: 'a2' isn't a type.
  print(a1 is a2);
              ^^
Error: Compilation failed.

a2는 타입이 아니기 때문에 is 키워드를 사용시 에러가 난다.

+ Recent posts