2022년 9월 7일 수요일

C# Async/Await Task 속도가 느릴 때 (TaskCompletionSource)

고전적인 개발 방법으로는 작업이 끝났는지 확인하기 위해서

작업 내용을 확인하는 루프를 만들어서 확인을 하는데


나는 이걸 mysql 풀링에 사용했었다.


그러니까 지금 사용 가능한 mysql 연결이 있는지를 task 에서

루프 돌면서 확인하는 방식으로 만들었던 것이다.


그런데 처음에 async/await task 방식이 문제라고 잘못 생각했던 것이

cpu 점유율을 너무 많이 먹었던 것이다.


ram이나 다른 리소스는 문제가 되지 않았다.

그저 cpu 점유율만 높았다. 그래서 이거 계속 써야 하나 싶었다.

그런데 써보니까 async 에서의 순차 실행이 참 편한 부분이 많았고

해결책을 찾아보니 내 코딩 스타일과 맞지 않았던 것이다.


루프 돌면서 쉬는 mysql 연결을 찾는 코드가 문제였는데

전체 확인하고나서 Task.Yield() 해서 한펌 쉬는 코드를 해놨는데

이게 유니티에서의 1프레임 단위가 아니었던 것이다.

결국 mysql 커넥션이 전부 사용중일때 많은 task 들이 yield를 하면서

루프를 도는데 이 텀이 너무 짧다보니 거의 무한루프(?) 돌듯이 계속 체크하면서

cpu를 다 먹었었다.


그래서 task 관련 공부를 더 했고 해결책을 찾았는데 그게

TaskCompletionSource였다.

값이 맞춰질때까지 대기하는 것이기 때문에 mysql을 다 쓴 후 반환하는 코드에서

mysql 연결 인덱스를 맞춰주니 yield를 사용할 필요가 없어서 cpu 사용율이

획기적으로 내려갔다.


사실 이건 내 코딩 스타일이 오래되서 그런거 같다. 하여간 문제는 해결이 되었고

이제 cpu 점유율 문제는 사라졌다.


2022년 4월 3일 일요일

C# CSV 파싱(여러줄 가능)

이전에는 데이터를 엑셀 데이터를 이용했는데 이건 좀 아닌거 같더라

그래서 CSV를 쓰려고 했는데 여러줄이 들어간 경우 때문에 안 쓰게 되었다.

이번에 현지화 관련 작업을 하면서 CSV를 쓰자고 생각이 들었고

CSV에서 어떤 방식으로 저장하는지를 연구해보았다. 일단 잘 동작한다. 

 
public static void ParsingCSV(string file_name,ref string[][] ret)
{
    ret = null;
    string all = ReadAllText(file_name);
    List<List<string>> lines = new List<List<string>>();
    List<string> ln = new List<string>();
    StringBuilder sb = new StringBuilder();
    bool is_string = false;
    int last = all.Length - 1;
    for(int i = 0; i < all.Length;++i)
    {
        Char c = all[i];
        if (is_string)
        {
            if (c == '"')
            {
                if (i < last && all[i + 1] == '"')
                { // " 2개가 연달아나오면 " 문자열을 써주면 된다.
                    sb.Append('"');
                    ++i;
                }
                else
                { // 문자열이 끝나는 상황
                    ln.Add(sb.ToString());
                    sb.Clear();
                    is_string = false;
                }
            }
            else sb.Append(c);
        }
        else
        {
            if (c == '"') is_string = true; // 문자열의 시작이다.
            else if (c == 0x0d)
            {
                ++i; // \r\n
                if (sb.Length > 0) ln.Add(sb.ToString());
                lines.Add(ln);
                sb.Clear();
                ln = new List<string>();
            }
            else if (c == ',')
            {
                if (sb.Length > 0)
                {
                    ln.Add(sb.ToString());
                    sb.Clear();
                }
                else ln.Add("");
            }
            else sb.Append(c);
        }
    }
    if (lines.Count <= 0) return;
    ret = new string[lines.Count][];
    for (int i = 0; i < ret.Length; ++i) ret[i] = lines[i].ToArray();
}
 "",",\r,\d, , 이 정도만 처리하면 되더라. 

 앞으로는 csv로 써보면서 문제 있으면 위 코드를 수정하게 될 것이다.

2022년 3월 12일 토요일

[윈도우 스토어] 워커홀릭

워커홀릭은 윈폼을 이용한 간단한 프로그램입니다.




구조

1. 상단 트리구조로 당장 업무에 필요한 내용을 정리합니다.

2. 하단 메모장에 필요한 내용을 정리합니다.


끝입니다.


시스템 트레이에 두고 관리할 수 있으며 언제든지 쉽고 빠르게 수정할 수 있습니다.

당장 가볍게 훅훅 들어오는 내용을 정리해 놓았다가 업무툴에 반영하기 좋습니다.

장기가 아니 당장 할 목록을 적었다가 지우면서 사용하면 좋습니다.


개인정보 취급 방침

이 앱은 설치형앱이고 아무런 인터넷 통신을 하지 않습니다.

어떠한 개인정보도 수집하지 않습니다.


2022년 3월 9일 수요일

IP로 국가 코드 얻기 KISA & DB BROWSER FOR SQLITE

 ip로 국가 확인 api


검색어로 구글 검색을 해보니 KISA에서 CSV를 배포하는 것을 알게 되었다.

일반적으로 GEOIP 검색해보면 유료 서비스가 있는데 돈 쓰는 것은 아깝고

PHP등에서는 예전 형식을 사용하는 것이 있는데 난 Dotnet을 사용하는데

데이터만 있으면 좋겠는데...  하고 아쉬워 했었다.


하여간 csv를 먼저 받도록 하자


kisa 국가별 ip


검색어로 검색을 하면

https://xn--3e0bx5euxnjje69i70af08bea817g.xn--3e0b707e/jsp/statboard/IPAS/ovrse/total/currentV4Addr.jsp

위 url로 들어가볼수 있다. (이상한 문자로 보이지만 주소창에 한글로 되어 있다.)


해당 사이트에서 csv를 받도록 한다.


내용은 아래와 같다




사실 여기서 필요한 정보는 국가코드,시작IP,끝IP 3가지다.

나머지열은 지워버린다. 그리고 1줄에 헤더 부분(한글) 도 지워버린다.

db browser for sqlite 를 켜고 데이터베이스를 만든다.

테이블은 안 만들어도 된다. (가져오기 하면 임시 테이블 만들어지니까 이거 수정하자)





파일을 지정하면 아래와 같이 나온다.


가져오기 하면 지 맘대로 테이블 만들어준다.


정보는 원하는대로 입력한다.


데이터가 제대로 입력된것을 볼 수 있다.


공격 들어오는 ip를 조회해보았다.



쿼리는 아래와 같다.

SELECT code from geoip where start <= '168.76.2.6' and end >= '168.76.2.6'

'168.76.2.6' <- 여기에 아이피 넣으면 되고 code 가 없을수도 있다.

이럴경우 특정 값으로 만들어 주고 나중에 다른 서비스를 이용해서 등록해주면

되지 않을까 싶다. 그리고 가능하면 주기적으로 확인해서 최신 데이터로 갈아주는것도

좋을 것이다.


%% 주의 %%

이거 문자열을 숫자형태로 변환해서 사용해야 합니다.

검색하면 나올건 sqlite에는 명령어가 없고 mysql 에서는 INET_ATON 명령어로

변환해서 사용해야 제대로 검색이 됩니다.

글을 수정하거나 새로 쓰기 귀찮아서 아래에 추가 합니다.

2022년 2월 27일 일요일

C# Litjson Extension

저는 C# 개발을 할때 json 라이브러리는 Litjson을 주로 사용합니다.


편하게 사용하기 위해서 정적 클래스 하나 만드러서 사용하다가 이번에는 익스텐션을 만들어 보았습니다.


확실히 편하게 사용할 수 있는 부분은 찾아보는 것이 좋은것 같습니다.


사용하는 litjson 라이브러는 0.17.0 버전입니다. 이전이나 이후도 별 상관은 없을것 같네요.

dotnet6로 만든 소스구요 null에 대한부분 ? 없애는 정도면 되지 않을까 싶네요.


사용법은

JsonData jd;

jd.GetInt();

jd.GetString();

아래 소스를 보시면 아시겠지만 어떻게든 값을 얻어옵니다.

타입 체크가 필요하면 하고 하면 될것이구요.

IsNumber의 경우 숫자 형태가 너무 많아서 추가했습니다.

필요한 것이 있으면 더 추가하면 될것이구요.

하여간 도움이 되면 좋겠습니다~


파일을 올릴수가 없네요.

소스입니다.

namespace LitJson
{
    internal static class LitjsonExtension
    {
        public static bool IsNumber(this JsonData jd)
        {
            switch (jd.GetJsonType())
            {
                case JsonType.Int:
                case JsonType.Long:
                case JsonType.Double: return true;
                default: return false;
            }
        }
        public static bool GetBool(this JsonData jd)
        {
            if (jd == null) return false;
            switch (jd.GetJsonType())
            {
                case JsonType.String: return Convert.ToBoolean((string)jd);
                case JsonType.Int: return Convert.ToBoolean((int)jd);
                case JsonType.Long: return Convert.ToBoolean((long)jd);
                case JsonType.Double: return Convert.ToBoolean((double)jd);
                case JsonType.Boolean: return (bool)jd;
                case JsonType.None:
                case JsonType.Object:
                case JsonType.Array:
                default: return false;
            }
        }
        public static int GetInt(this JsonData jd)
        {
            if (jd == null) return 0;
            switch (jd.GetJsonType())
            {
                case JsonType.String: return Convert.ToInt32((string)jd);
                case JsonType.Int: return (int)jd;
                case JsonType.Long: return Convert.ToInt32((long)jd);
                case JsonType.Double: return Convert.ToInt32((double)jd);
                case JsonType.Boolean: return Convert.ToInt32((bool)jd);
                case JsonType.None:
                case JsonType.Object:
                case JsonType.Array:
                default: return 0;
            }
        }
        public static long GetLong(this JsonData jd)
        {
            if (jd == null) return 0;
            switch (jd.GetJsonType())
            {
                case JsonType.String: return Convert.ToInt64((string)jd);
                case JsonType.Int: return Convert.ToInt64((int)jd);
                case JsonType.Long: return (long)jd;
                case JsonType.Double: return Convert.ToInt64((double)jd);
                case JsonType.Boolean: return Convert.ToInt64((bool)jd);
                case JsonType.None:
                case JsonType.Object:
                case JsonType.Array:
                default: return 0;
            }
        }
        public static double GetDouble(this JsonData jd)
        {
            if (jd == null) return 0;
            switch (jd.GetJsonType())
            {
                case JsonType.String: return Convert.ToDouble((string)jd);
                case JsonType.Int: return Convert.ToDouble((int)jd);
                case JsonType.Long: return Convert.ToDouble((long)jd);
                case JsonType.Double: return (double)jd;
                case JsonType.Boolean: return Convert.ToDouble((bool)jd);
                case JsonType.None:
                case JsonType.Object:
                case JsonType.Array:
                default: return 0;
            }
        }
        public static string? GetString(this JsonData jd)
        {
            if (jd == null) return null;
            switch (jd.GetJsonType())
            {
                case JsonType.Object:
                case JsonType.Array: return jd.ToJson();
                case JsonType.String: return (string)jd;
                case JsonType.Int: return Convert.ToString((int)jd);
                case JsonType.Long: return Convert.ToString((long)jd);
                case JsonType.Double: return Convert.ToString((double)jd);
                case JsonType.Boolean: return Convert.ToString((bool)jd);
                case JsonType.None:
                default: return null;
            }
        }
    }
}

2022년 1월 26일 수요일

[Cocos Creator] Scene, Prefab 머지 문제 방지하기

기존에 남긴 글을 보면

https://gogogodwish.blogspot.com/2022/01/cocos-creator-scene-prefab.html


svn이 바이너리는 머지를 하지 않는데 txt 형식의 파일은 머지를 하려고 한다. 

유니티에서는 문제가 없던 것이 코코스에서는 문제가 될 때가 있는데 프리팹, 씬 등

머지 하면 안 되는 파일들이 머지가 되면서 생기는 문제들이다.

문제 생기면 지우고 받고 또 문제 생기고를 반복하다가 혹시나 하는 생각이 들었다.

역시나 방법은 있었다. 머지를 하지 못하게 하면 되는 것이다.


아래는 TortoiseSVN을 이용해서 코코스에서 문제가 생기지 않게 설정하는 부분이다.




svn 설정을 바꿔주는데 기본값이

*.o *.lo *.la *.al .libs *.so *.so.[0-9]* *.a *.pyc *.pyo __pycache__ *.rej *~ #*# .#* .*.swp .DS_Store [Tt]humbs.db

이었는데 난 아래와 같이 수정했다.

*.o *.lo *.la *.al .libs *.so *.so.[0-9]* *.a *.pyc *.pyo __pycache__ *.rej *~ #*# .#* .*.swp .DS_Store [Tt]humbs.db *.fire *.prefab *.meta *.anim *.mtl *.plist *.tps *.txt *.json

뒤에 txt,json은 스파인에서 나오는 형식이 저렇게 나온다고 한다.


실제로 추가되는 내용은

*.fire *.prefab *.meta *.anim *.mtl *.plist *.tps *.txt *.json


svn 설정은 전역이기 때문에 본인에게 맞는 설정을 적용하면 될 것 같다.

2022년 1월 24일 월요일

[Cocos Creator] 포럼에 글을 쓸 수는 없는가?

현재는 해결 된 상태이며 해결한 방법은 새로 가입했더니 된다.
기존에 가입된 계정이 문제였어서 등업 글 남길 때 계정 문제 있다고 하니까 새 계정 지우고
기존 계정의 글 쓰기를 가능하게 해주더라
하여간 지금은 해결이 된 상태다.





답답한 일이다..

기본 권한을 얻었고 글도 쓸 수 있을 것 처럼 노티는 왔는데

글을 남길수가 없다.

뭘 어떻게 해야 하는지 모르겠다.

글을 남겨야 등업이 된다고 가이드라인에 있는데 글을 못 남기게 해놨다.

뭘 어떻게 하라는거냐? 할 수 있는건 좋아요 남기기? 토픽 쉐어링 정도?

관심도 없는 토틱에 하트 남기고 싶지도 않고..

글을 쓰고 싶은데 막아놓으니 뭘 할 수가 없다.

자기들 관리하기 좋게 글 쓰기 권한을 통제 하는 것인지.. 안타깝다..


2022년 1월 22일 토요일

[Unity] MultiTextGradation

[에셋 스토어 바로가기]




단순한 스크립트 에셋입니다.
UGUI에 기본적으로 그라데이션 기능이 없는 것으로 알고 있습니다.
익스텐션 붙이면 되긴 한데 지금까지 제가 찾은것은 각 4개의 모서리 그라데이션 및
2단계 혹은 3단계 그라데이션이었습니다.

















위와 같습니다.

원하는 단계만큼 그라에디션을 지정할 수 있습니다.

원래 가격을 0.99$로 책정하고 싶었는데 아쉽게도 최저가가 4.99$입니다.

이후에 할인을 할 수 있을지는 모르겠지만 뭐 당장은 어쩔 수 없을듯 싶네요.


원래 회사에서 NGUI용으로 만들었던 것을 UGUI용으로 다시 만든 것입니다.

NGUI용도 있긴한데 NGUI는 버전에 따라 구조가 달러서 작업을 몇 번 했던 것으로 기억합니다.

NGUI는 코어단까지 건드려야 합니다. 뭐 필요한 사람이 있으면 올릴수도 있지만 당장은 회의적입니다.


[에셋 스토어 바로가기]

[Cocos Creator] 편집기 실행시 Restart Aboart 나오고 안 열릴 때

현재 사용하는 Cocos Creator 버전은 2.4.5고 2.4.7도 동일 했던 것으로 보임


이번 글은 겪었던 경험을 기록해 놓으려는 것으로 혹시나 동일한 문제를 겪으면 도움이 될 수도 있지만 뭐 대단한 내용은 아님


내가 겪은 이 경우도 마찬가지로 왜 문제인지 알수가 없었음


뭐 언제나 그랬듯이 내가 뭘 건드렸나를 찾아보게 됨


Cocos Creator 빌드하면 iOS에선가 아마 ogg가 재생이 안되는 문제가 있었음


그래서 mp3로 변경을 해줘야 했는데 뭐 그 문제 아니라도 유니티 프로젝트를 코코스로 바꾸는 작업을 하다보니 만사 귀찮으니 폴더 그대로 복사를 하는 경우도 있었음


그러고 문제가 생겼고 그래서 여러 삽질의 끝에 해당 리소스 확인을 하게 됨


그냥 보명 아무 문제가 없어보임


그런데 meta파일을 까보니 (음악 파일이 문제는 아닐 테니) 뭔가 원래 Cocos Creator와 구조가 다른 것을 알게 되었음


그래서 생각을 해본 유니티 meta파일을 그대로 복사한거였음


결국 유니티 meta파일을 파싱하다가 오류가 뜬 거였음


해당 meta 파일 다 지우니 문제가 해결 됨


하여간 뭐 대단한 내용은 아니고 수 많은 오류중에 하나일 것이고 로그성으로 남겨놓음

[Cocos Creator] Scene과 Prefab의 구조

현재 사용하는 Cocos Creator 버전은 2.4.5고 2.4.7도 동일 했던 것으로 보임


코코스를 이해하려면 씬과 프리팹의 구조를 이해하는 것이 좋을 것으로 보임


a라는 씬(fire)가 있고 b,c,d라는 프리팹이 있다고 보자


a->b->c->d


자 a라는 씬에 b가 있다. 저장을 한다


a의 b의 내용과 실제 b의 내용은 다름


유니티도 다르지 않나???


그렇지 않음. 왜 그런가?

Cocos Creator에서는 해당 프리팹의 내용이 그대로 씬에 저장이 됨.


그게 뭔데?

그니까 b라는 프리팹에 내용이 1,2,3이라면 a 씬에 b프리팹으로 되어 있는 부분에 4,5,6이라도 된다는 거임

이게 무슨 차이가 있냐면 유니티에서는 프리팹을 씬에 넣을때 프리팹의 구조를 바꿀수는 없음.구조가 그대로인데 그 안의 내용은 바꿀 수 있찌만 구조를 바꾸면 프리팹을 깰거냐고 물어보는 것을 알수 있음


그래서 이런 부분이 Cocos Creator가 좋은 부분도 있을 수 있다 라고 생각을 할 수도 있지만 보통의 경우 지옥도가 열림, 왜? 우리는 보통 협업을 하니까


예를 들어서

1. 디자이너가 프리팹을 배포함

2. 개발자가 씬에 프리팹을 넣음

3. 디자이너가 프리팹의 구조를 수정하고 커밋

4. 개발자가 업데이트 받고 "수정 안 되었는데요?" 물어봄


단순하게 씬에 프리팹 내용이 그대로 들어가 있고 프리팹이 변한것이 반영되지 않아서임


이건 프리팹도 마찬가지라서 프리팹 안에 프리팹도 같은 구조임


그냥 이 프리팹에 다른 프리팹이 포함되어 있음.

그냥 어떤 노드에 다른 프리팹이었다는 사실을 알려주는 것임


그래서 프리팹 옵션에 Go Back(원래 프리팹 내용으로 바꿈) Save가 있는 것임


근데 이게 유니티의 구조와도 다르지만 뭔 수정이 생길때마다 Go Back을 해줘야 하는 상황이벌어 지기 때문에 상당히 피곤하다는 것을 알 수 있음


우리도 이런 문제에 엄청 피곤했고 이후에는 그냥 프리팹 연결하는 구조로 변경했음


--------------------------------


svn 설정으로 문제를 해결했습니다. [바로가기]

[Cocos Creator] 편집기가 안 열릴 때(하나의 경우)

현재 사용하는 Cocos Creator 버전은 2.4.5고 2.4.7도 동일 했던 것으로 보임


이건 스크립트 관련 문제인데 아마 대부분의 개발자가 Visual Studio Code로 작업을 할 것으로 생각함.


단순하게 Type Script 문법오류 그니까 그냥 잘못 짰을 경우임


내가 겪어본 경우임


a= number = 0;

( a : number = 0: 으로 바꿔야함)


Cocos Creator 시작한지 얼마 안되고 Type Script잘 모를 때 있었던 문제로 위와같이 문법 오류가 있을때 편집기가 문제가 생기는 경우임


그냥 스크립트에 문제가 있다고 오류 뱉으면 되는데 아무런 노티도 없고 Visual Studio Code에서도 스크립트 열어봐도 오류 표시가 안 되서 어디가 문제인지 알기가 너무 어려움


이런 부분을 찾으려면 결국 이후에 수정한 부분이 무엇인지를 찾아야함


그래서 전체적으로보다보니 잘못 짠 부분이 보였고 수정하니 됨


문제는 이런 부분이 꽤 많다는 것임 (vs code에서 오류로 표시가 안 됨)


하여간 그래서 편집기가 안 켜질 때 스크립트도 의심을 해봐야 한다임


혹시나 나중에 나도 까먹을까봐 남겨 놓음






[Cocos Creator] Time Line Panel이 안 닫히는 경우

현재 사용하는 Cocos Creator 버전은 2.4.5고 2.4.7도 동일 했던 것으로 보임


Cocos Creator에서 애니메이션 작업을 할 때 문제가 많은데 그중 대표적인거 2개가


1. 애니메이션 작업 도중 Node의 위치를 옮기는 경우

2. 애니메이션 하는 최 상위 Node에 포함된 하위 Node들 중에 Particle3D가 포함된 경우 맛이 가는 경우


이 문제를 해결하고 하고 싶어 편집기 소스를 고치고 싶었으나 공개된 것은 엔진 소스 뿐이어서

고칠수가 없었음 (편집기 소스는 자기들이 관리 하는듯)


결국 편집기를 고칠수가 없으면 그냥 가는 수 밖에 없는데 아직까지 해결되진 않은것으로 보임.


원인으로 보이는 것은 그냥 편집기 만드신 분들이 버그가 있지만 고치고 있지 않은 것으로 보임


위에 Node 위치 옮기는 경우 맛가는건 뭐 그냥 눈에 보이니까 편집기 문제이고 Particle3D 문제는 아래 이유로 편집기 문제로 보임


판단 이유

1. 애니메이션 파일을 까보면 "a/b/c" 이런식으로 문자열로 node가 연결되어 있어서 node 연결이 uuid등 특별한 방법으로 연결되어 있지 않아서 바인딩이 단순함

2. 구조가 다른 프리팹에서는 문제가 없는 경우가 있음

3. 프리팹에서 Particle3D를 제거하고 하면 됨

4. 위에 Particle3D가 anim 파일에 있는게 아니고 프리팹에 있는 것임

5. 결국 anim 파일 문제가 아니라 프리팹등 node들의 문제라는 것을 알 수 있음.,

6. Particle3D는 재미있게도 되는 것도 있고 안 되는 것도 있음


Particle3D 프리팹을 까보면 문자열로 되어 있는 Particle3D 정보가 400중? 생각보다 많은 정보가 있는 것으로 보이는데 애니메이션을 닫거나 저장할때 변경된 부분? 뭐 이런 내용을 스캔하다가 Particle3D 정보를 처리하다가 기능이 맛이 가는 것으로 보임


node.js 특성상 함수 연결 구조를 많이 쓸텐데..


a->b->c-> 요런식으로 구현이 되어 있다면 a->b(스캔) 맛감 -X->c


이런식으로 세이브하고 타임라인 페널 꺼주는 처리를 해야 하는데 안되는 경우

혹은 세이브는 되 고 페널 안 꺼지는 경우 이렇게 보임


정리하자면 해당 이슈는 편집기 문제고 수정이 불가능하다. 그냥 조심해서 사용하는 방법 밖에 없다 입니다.

[Cocos Creator ] json 관련 오류(uuid)가 나는 경우

현재 사용하는 Cocos Creator 버전은 2.4.5고 2.4.7도 동일 했던 것으로 보임


???-???-???-???.json  앞에 ??는 꽤 긴 숫자 혹은 문자들로 이루어져 있다.

ex) 프로젝트 폴더 /library/imports//14/14413966-a78d-4a80-89f8-ad0eda1023d5.json


작업을 하다보면 위와 같은 오류가 나는 경우가 있음


이 오류는 언제 나는가 하면 스프라이트,머터리얼,버튼,... 하여간 이미지나 리소스 링크가 깨졌을 때 나오는 오류입니다.


만약에 a.png가 있고 스프라이트에 a.png를 넣고 씬이나 프리팹에 배치를 했는데

이후 a.png를 지우는 경우 발생합니다.


리소스가 없어서 실행이 안된다 이런 의미 입니다.


그냥 missing 나고 실행 되면 좋은데 Cocos Creator는 다릅니다.  안됩니다.


이런 어이 없는 경우가 Cocos Creator에는 많은데 이 오류를 안 나게 하려면 문제가 있는 링크를 끊어 주면 됩니다.


가장 쉽게 어느 곳에서 사용하는지 알고 싶다면 폴더 단위로 검색 가능한 편집기로 확인하면 됩니다.


저는 visual studio code로 하는 경우가 많습니다.


일단 asset 폴더를 폴더 열기로 열어줍니다.

???.json에 ??? 부분을 전체 파일 검색으로 찾아 줍니다.


그럼 포함된 파일들이 나옵니다. 그럼 어디에 연결되어 있는지 나오게 됩니다.


해당 파일들에서 연결된 부분을 끊어주면 됩니다.

C# Async/Await Task 속도가 느릴 때 (TaskCompletionSource)

고전적인 개발 방법으로는 작업이 끝났는지 확인하기 위해서 작업 내용을 확인하는 루프를 만들어서 확인을 하는데 나는 이걸 mysql 풀링에 사용했었다. 그러니까 지금 사용 가능한 mysql 연결이 있는지를 task 에서 루프 돌면서 확인하는 방식으로 만...