TIL - 2024. 07.
2024. 07. 14¶
C# 2차원 배열¶
https://stackoverflow.com/questions/12567329/multidimensional-array-vs
C#에서 2차원 배열 선언하는 방법 및 활용하는 방법.
double[][] x
처럼 선언하면 x안에 들어있는 각 배열의 크기가 달라도 상관 없음double[,]
처럼 선언하면 정해진 크기대로 만들어지는듯.
14174번: Block Game (acmicpc.net) 문제를 풀때 활용했다.
mkdocs에서 링크 클릭할때 새로운 창에서 뜨도록¶
[markdown] open a link with a new tab · squidfunk/mkdocs-material · Discussion #3660 (github.com)
위의 디스커션에 나온 내용에 따르면 아래처럼 작성하면 되는듯하다.
[name](link) <- 기존
[name](link){:target="_blank"} <- 새 탭에서 링크 열기
디스커션 계속 읽다 보면 누군가가 자동으로 링크 걸린 것을 새 탭으로 열게 해주는 플러그인도 만들어놓았고 insiders에 관련 기능이 구현되어 있다는 이야기도 있지만, 이 페이지에 있는 이전 페이지
같은 버튼들이 링크처럼 작성되어 있어서 영향을 받을 수도 있어보인다. {:target="_blank"}
를 사용하는 것으로 만족하기로 했다.
2024. 07. 15¶
.gitkeep 파일¶
예전에 어디선가 보고 잊고 있다가 이런 저런 repo들 돌아다니다가 다시 발견. 로그 파일 저장 위치 같이 처음에는 비어있지만 폴더가 존재해야 나중에 그 위치에 파일이 문제 없이 쌓이는 경우에 빈 폴더에 해당 비어있는 .gitkeep이라는 이름의 파일을 넣어놓는 식으로 활용한다. git은 비어있는 폴더는 무시하고 넘어가기 때문에 이렇게 해야 폴더가 남아있음.
사실 꼭 저 이름이 아니어도 같은 방식으로 작동하긴 할테지만 많이 쓰이는 컨벤션이니 기억해두고 다음에는 꼭 써먹자.
celery vs huey¶
is this to replace Celery · Issue #64 · coleifer/huey (github.com)
celery보다 가벼운 huey. huey 만든 분이 직접 장단점 적음. 2주 전 업데이트.
I'd write celery, more like smellery.
Seriously though I don't know what all has changed in celery over the years (or the other popular projects in this space). huey's gotten better at a few things since I wrote that, though, so I can write about that. Over the years, Huey's added:
- different worker types, so it can handle a variety of workloads
- priorities
- locking
- pipelines/chaining tasks
- signalling / much more powerful hooks for extending and introspecting huey
- controllable shutdown behavior - graceful or hard
- additional storage backends for different types of deployments
Things huey is not great for:
- at-least-once tasks (we are at-most-once as it is simpler)
- complex pipelines / airflow-type stuff
- monitoring tooling / etc is not on the level of celery ecosystem
huey still remains stupid simple to get going with and can go rather far. I think the users who like huey like it quite well, and that's what I'm going for here.
긴 코드블록 wrap하기¶
위의 코드블록에 따로 처리를 하지 않으면 옆으로 스크롤을 해야 하는 문제가 생긴다.
https://stackoverflow.com/a/56469907
여기에 있는 내용을 따라서 아래의 내용을 css파일에 추가해서 wrap이 되도록 했다.
code {
white-space: pre-wrap !important;
}
2024. 07. 16¶
mkdocs에서 sitemap.xml이 제대로 생성되지 않음¶
- haklee.com/sitemap.xml주소로 들어갔을때 나오는 sitemap 정보에 제대로 된 주소가 들어있지 않고
None
이 등장했다. mkdocs sitemap broken
키워드로 검색해보니 다음과 같은 링크가 나왔다.- 문제 해결 방법은
mkdocs.yml
에site_url
속성을 만들어주면 되는 것이었다. 다행히도 매우 간단한 해결 방법.
jetbrains에서 파이썬 유저들을 대상으로 진행한 2022년 서베이¶
Python Developers Survey 2022 Results (jetbrains.com)
흥미로운 내용들이 많다. 나는 flask vs django vs fastapi
키워드로 검색하다가 찾았는데, 서베이 내용에 점유율이 39% : 39% : 25%로 나왔다. 참고로 복수 선택이 가능해서 합이 100%가 넘을 수 있음. 의외로 사람들이 docker를 안 쓴다. How do you develop for the cloud?
질문에 대한 답에 In Docker containers
가 40% 정도 된다.
2024. 07. 17¶
yaml에 설정 복붙 기능¶
How to build differently configured celery workers using docker-compose? - Stack Overflow
큐를 다르게 설정한 celery worker들을 여럿 올릴때 기본 설정들을 중복해서 쓰는 것을 막기 위한 방법. 위 글에서는 이런 식으로 썼다.
version: "3"
services:
worker-a: &default
image: alpine
command: env
environment:
WORKER_TYPE: a_setting
# ... more definitions
worker-b:
<<: *default
environment:
WORKER_TYPE: b_setting
django의 project와 app 차이¶
Writing your first Django app, part 1 | Django documentation | Django (djangoproject.com)
- An app is a web application that does something
- A project is a collection of configuration and apps for a particular website
- A project can contain multiple apps. An app can be in multiple projects.
튜토리얼을 따라가다 보면 manage.py는 프로젝트를 생성할때 만들어지는데 $ python manage.py startapp polls
같은 방식으로 app을 생성함. 그렇다면 한 app이 여러 프로젝트에 속하게 하기 위해서는 직접 세팅해주어야 하는 값들이 있을 거라는 말인가...? 한 app이 여러 프로젝트에 속하는 상황의 예시를 나중에 찾게 된다면 다시 생각해보면 되겠다.
2024. 07. 18¶
개인 github을 nuget package server로 사용하기¶
Using Github as Private Nuget Package Server and Share Your Packages - CodeProject
위 링크 내용을 나중에 실습해볼것.
celery 실전용 팁들¶
10 Essential Lessons for Running Celery Workloads in Production | by Hank Ehly | Medium
유용한 팁들이 많았다. 그 중에서도 다음의 항목들이 지금 활용하기에 좋았다.
6. Use flower (the monitoring tool)
- 여기에서는 오토스케일이 적용된 환경에서 떠있던 워커들이 죽는 것까지 고려해서
FLOWER_PURGE_OFFLINE_WORKERS: 60
옵션 주는 걸 설명함.
- 여기에서는 오토스케일이 적용된 환경에서 떠있던 워커들이 죽는 것까지 고려해서
7. Broker (Redis, RabbitMQ, SQS) characteristics and points to keep in mind
- 여기에서는 브로커를 어떤 걸 사용하면 어떤 점이 좋은지/문제가 있을 수 있는지 잘 설명.
2024. 07. 19¶
docker compose를 쓸때 flower 컨테이너를 내렸다가 다시 올려도 정보 유지하게 하는 방법¶
Persistence not working with docker compose ? · Issue #1145 · mher/flower (github.com)
위의 이슈 끝에 유저 rajkumarvenkatasamy
가 남겨놓은 내용을 따라하면 잘 작동한다. 대신 아래와 같은 한계가 있긴 하지만, 그래도 태스크들에 대한 로깅이 가능하다는 점에서 쓸만해보인다.
- Data is being retained across container restarts
- The main status page shows reset statistics.
- You have to click through to the "active" , "processed", or "failed" tabs to see the previous tasks.
semver의 backward compatible의 정의는 어떻게 되나요?¶
Definition of backwards compatibility · Issue #256 · semver/semver (github.com)
유의적 버전에서 버전 번호를 올리는 상황을 정의할때 '이전 버전과 호환이 되는지'가 중요한 기준이 되는 것에 비해 호환이 어떻게 정의되는지를 자세히 다루지 않은 것에서 비롯된 이슈. 흥미로운 이야기를 하는 것 같은데 아직 자세히 읽어보지 않았다. 나중에 읽고 정리해보면 좋을듯하다.
2024. 07. 20¶
C#에서 배열의 마지막 아이템 얻는 방법¶
c# - Finding the last index of an array - Stack Overflow
여기에서 아래의 방법이 굉장히 인상깊었음.
int[] array = { 1, 3, 5 };
var lastItem = array[^1]; // 5
2024. 07. 21¶
postgresql에서 insert/update/delete한 행의 정보 가져오기¶
PostgreSQL: Documentation: 16: 6.4. Returning Data from Modified Rows
다음과 같이 정보를 가져오는 것이 가능하다.
UPDATE products SET price = price * 1.10
WHERE price <= 99.99
RETURNING name, price AS new_price;
이를 kysely를 쓰면 다음과 같이 사용할 수 있다.
let insertResult = await db
.insertInto('MySchema.MyTable')
.values({...}) // 내용물을 뭔가 넣었다고 하자.
.returning('uuid') // 이때 uuid가 자동으로 생성되는 칼럼이 있어서 해당 내용을 가져오려 한다.
.execute();
const uuid = insertResult[0].uuid; // uuid값을 받아오는 데에 성공.
turmite¶
Turmite - Wikipedia
현재의 상태와 방향을 가진, 무한한 2차원의 그리드로 된 셀로 이루어진 테이프로 작동하는 튜링머신. 무슨 말인지 하나씩 뜯어보면
- 원래 튜링머신에서 하나의 셀은 하나의 기호를 들고 있을 수 있다. 예를 들어, 셀이 'A'라는 기호를 들고 있을 수 있다.
- 튜링 머신은 상태를 가진다. 예를 들어, 현재의 상태가 '1'이라고 할 수 있다.
- 튜링머신은 주어진 규칙에 따라 작동한다. 예를 들어, "현재 상태가 x이고 셀에 y가 적혀있을때 상태를 x'으로 바꾸고 다음 셀에 y'을 적는다." 같은 작업을 수행할 수 있다.
- turmite에서는 이 셀이 들고 있는 것이 하나의 기호가 아니라 무한한 2차원 그리드라고 보면 된다.
- 방향을 가지고 있다는 말은, 2차원의 그리드를 읽을때 방향이 중요하다는 것.
- 즉, 주어진 그리드를 회전시키면 다른 정보가 된다.
- 예를 들어, 규칙에 "현재 상태가 (x, y)일때 (x, y)에 해당하는 그리드에 점을 찍고 상태를 북쪽으로 한 칸 이동한다"라고 되어있다 하자.
- 원래의 셀에서 북쪽으로 한 칸 가는 것과, 셀의 그리드를 시계방향으로 90도 회전시킨 다음 북쪽으로 한 칸 가는 것이 서로 다른 결과가 나오므로 방향이라는 정보가 중요함.
langton's ant같은 것이 이런 turmite에 속한다. 그 외에도 흥미로운 패턴들이 많이 있는 것을 볼 수 있는데, 나중에 좀 더 살펴볼 예정.
C#에서 특정 문자열 n번 반복하기¶
아래와 같은 방식으로 n번 반복되는 문자열을 띄어쓰기로 구분해서 붙일 수 있다.
string.Join(" ",Enumerable.Repeat(i,n))
2024. 07. 22¶
grafana provisioning¶
Provision dashboards and data sources | Grafana Labs
grafana를 docker로 올릴때 아무 세팅이 없는 빈 docker image로 올릴 텐데, 이때 각종 datasource, dashboard, alert 같이 유저가 직접 세팅한 값을 같이 올리고 싶을 수 있다. 이때 활용하는 것이 바로 provisioning.
특정한 폴더 구조에 맞게 config용 yml파일을 만들어서 넣어두면 grafana를 처음 올릴때 이를 반영해서 세팅해준다.
django ninja의 schema¶
Request Body - Django Ninja (django-ninja.dev)
이 링크의 제일 아래까지 내려가보면 다음과 같은 내용이 적혀있다.
- If the parameter is declared to be of the type of Schema (or Pydantic
BaseModel
), it will be interpreted as a request body.
즉, django ninja 뒷단에서는 pydantic이 자동으로 타입 유효성 검사를 해주고 있다고 생각하면 된다. 문제는 이를 해제할 수 있는 방법이 검색해도 잘 나오지 않는다는 것. 빠르게 프로토타이핑 하고 싶더라도 body를 정확하게 명시해주어야 하는 것은 조금 아쉽다.
celery worker를 멈추는 방법¶
Workers Guide — Celery 5.4.0 documentation (celeryq.dev)
Note
The terminate option is a last resort for administrators when a task is stuck. It’s not for terminating the task, it’s for terminating the process that’s executing the task, and that process may have already started processing another task at the point when the signal is sent, so for this reason you must never call this programmatically.
Helper functions that revokes celery tasks by name and ID (github.com)
하지만 그럼에도 불구하고 revoke를 사용하고 싶다면 위의 코드를 참고하자. 이전 버전 기준으로 작성되어 있지만, 코멘트를 보면 v5에 맞게 수정해서 사용 가능한듯.
For celery v5 it should be enough to change the imports with this:
from backend.celery import celery_app
revoke = celery_app.control.revoke
inspect = celery_app.control.inspect
2024. 07. 23¶
C# 변수 swap¶
c# - Swap two variables without using a temporary variable - Stack Overflow
두 변수를 swap하는 것이 가능하다.
int a = 10;
int b = 2;
(a, b) = (b, a);
django ninja에서 docs 페이지 안 만드는 방법¶
API Docs - Django Ninja (django-ninja.dev)
django ninja에서 docs 페이지를 안 노출시키고 싶으면 아래와 같이 설정해주면 된다.
api = NinjaAPI((docs_url = None));
django model과 기존 테이블 연결하기¶
How to integrate Django with a legacy database | Django documentation | Django (djangoproject.com)
django랑 기존 테이블이랑 연결.
class Person(models.Model):
id = models.IntegerField(primary_key=True)
first_name = models.CharField(max_length=70)
class Meta:
managed = False
db_table = "CENSUS_PERSONS"
2024. 07. 24¶
celery 라우팅¶
celery에 태스크 큐를 만들고 태스크들을 큐들로 라우팅하는 방법이 몇 가지가 있다.
Routing Tasks — Celery 5.4.0 documentation (celeryq.dev)
하나는 위의 페이지에 Manual routing
항목에 소개된 것처럼, apply_async()
함수에 queue
인자로 넣어서 보내는 것. 이 경우 task에 라우팅 정보가 들어간다고 볼 수 있다.
>>> from feeds.tasks import import_feed
>>> import_feed.apply_async(args=['http://cnn.com/rss'],
... queue='feed_tasks',
... routing_key='feed.import')
그런데 이렇게 개발할 경우 태스크가 많아지면 어떤 태스크가 어디로 라우팅 되는지 관리하기 어렵기도 하고, 태스크가 스스로 어느 큐로 가야 하는지 아는 것이 좋은 구조가 맞는지 생각해볼 여지가 있다.
이럴때 볼만한 것이 위의 링크에 있는 Routing
항목. route 관련 정보를 관리하는 객체들을 만들어서 이들을 한 군데 모아놓고 routing할때 활용하는 것이 주된 아이디어. routing 정보 객체는 태스크 이름을 키로 큐 정보를 들고 있는 dict로 관리해도 되고, 함수로 구현해도 된다.
def route_task(name, args, kwargs, options, task=None, **kw):
if name == 'myapp.tasks.compress_video':
return {'exchange': 'video',
'exchange_type': 'topic',
'routing_key': 'video.compress'}
# 혹은
task_routes = {
'myapp.tasks.compress_video': {
'queue': 'video',
'routing_key': 'video.compress',
},
}
자세한 내용은 문서화된 내용 참조.
2024. 07. 25¶
docker compose와 k8s 차이점¶
docker-compose will die : r/kubernetes (reddit.com)
...
For docker-compose You just need to understand some basic concepts to run multiple containers and have them communicate with each other.
For Kubernetes, At least in my case:
- I first needed to understand what to use: k8s, minikube, k3s, k3d, kind, Microk8s, Firekube etc (when you understand how kubernetes works and what it does things are not complex, but when you just want to run some containers and do not know anything about Kubernetes this can be a pain).
- I had to understand what a selector is and how it works, differences between Pods vs Replica Sets vs Stateful Sets vs Deployments, NodePorts vs ClusterIp vs LoadBalancer vs Headless (again fairly basic concepts when you have a good understanding of kubernetes, but can be a pain when you have 0 kubernetes experience and you just want to run some containers that can communicate with eachother.
- wait why doesn't kubernetes see my local image. Oh I have to create a registry? How does a registry work, what options do I have ?
- I see there is this thing called Helm I need in order to install "some containers". Oh I need to learn Go template language.
- I've used helm to install this database that I am using, but it has multiple instances running I want just one because my PC cannot handle the extra weight. Hmmm I see I installed an operator. What is an operator, how do I use it, how do I modify it.
...
즉, 이후에 k8s를 써야 하는 상황에서는 이걸로밖에 해결할 수 없는 문제들이 있을 것이고, 로컬에서도 k8s로 올려봐서 실제 배포 상황이랑 비슷한 환경에서 테스트를 진행하는 것이 좋겠지만, 그냥 서로 통신하는 컨테이너 몇 개만 올라가도 충분히 테스트가 가능한 상황에서는 k8s는 너무 무겁다.
NextJS에서 useEffect 안에 있는 내용물이 두 번 실행되는 것을 막는 방법¶
해결 방법은 다음과 같다.
// next.config.js
module.exports = {
reactStrictMode: false,
};
javascript - Why useEffect running twice and how to handle it well in React? - Stack Overflow
두 번 실행되는 이유는 이런 것을 막기 위함이었다.
This illustrates that if remounting breaks the logic of your application, this usually uncovers existing bugs. From the user’s perspective, visiting a page shouldn’t be different from visiting it, clicking a link, and then pressing Back. React verifies that your components don’t break this principle by remounting them once in development.
그러니까, 보통 페이지에 가서 다른 링크로 갔다가 다시 원래 페이지로 갔을때 useEffect가 두 번 발동되는데, 이런 상황에서 발생하는 버그를 개발 상황에서 useEffect를 두 번 발동시키면서 잡아낼 수 있기 때문.
2024. 07. 26¶
celery task에 bind를 true로 하면 할 수 있는 것¶
python - What is the meaning of bind = True keyword in celery? - Stack Overflow
bind 써서 할 수 있는 것
- retry 세팅하기
- 커스텀 상태 만들기
celery의 -Ofair 옵션¶
Tasks — Celery 5.5.0b1 documentation (celeryq.dev)
celery version 4.0부터 디폴트 스케쥴링 전략이 -Ofair가 되었다고 한다.
In previous versions, the default prefork pool scheduler was not friendly to long-running tasks, so if you had tasks that ran for minutes/hours, it was advised to enable the [`-Ofair`](https://docs.celeryq.dev/en/latest/reference/cli.html#cmdoption-celery-worker-O) command-line argument to the **celery worker**. However, as of version 4.0, -Ofair is now the default scheduling strategy. See [Prefetch Limits](https://docs.celeryq.dev/en/latest/userguide/optimizing.html#optimizing-prefetch-limit) for more information, and for the best performance route long-running and short-running tasks to dedicated workers ([Automatic routing](https://docs.celeryq.dev/en/latest/userguide/routing.html#routing-automatic)).
2024. 07. 27¶
-
2024. 07. 28¶
C#에서 리스트를 n개 아이템씩 쪼개는 방법¶
c# - Split a List into smaller lists of N size - Stack Overflow
Chunk라는 메소드가 있다. 이를 5543번: 상근날드 (acmicpc.net) 문제를 푸는 데에 다음과 같이 사용할 수 있다.
Console.Write(new int[5].Select(i=>int.Parse(Console.ReadLine())).Chunk(3).Sum(i=>i.Min())-50);
2024. 07. 29¶
Couldn't connect to Docker daemon at http+docker://localhost - is it running?¶
아래의 명령어를 실행하자.
sudo service docker restart
mysql에서 != 기호로 null 체킹이 불가능하다¶
오랜만에 mysql을 써보니 별 걸 다 잊어버린다.
The “!=” operator, also written as “<>”, is a common comparison operator in SQL used to test for inequality between two values. When you use “!=” with NULL, it behaves differently than you might expect. In fact, “!=” NULL doesn’t return the desired result when checking for NULL values.
... it won’t return any rows because NULL values are not directly comparable using the “!=” operator.
AutoCAD에서 임시로 화면에 표시할 도형 그리기¶
Using Transient graphics - AutoCAD DevBlog (typepad.com)
Temporary graphics in AutoCAD - AutoCAD DevBlog (typepad.com)
임시로 표시할 도형이나 텍스트를 만드는 방법. 첫 번째 포스트는 transient graphics 기능을 활용한 것이고, 두 번째 포스트는 AutoCAD에 내장된 low level graphics method를 활용한 것이다.
2024. 07. 30¶
gitk로 모든 브랜치 보기¶
gitk --all
gitk 뒤에 all 옵션을 붙이면 현재 브랜치와 연관된 히스토리 뿐만 아니라 다른 브랜치들까지도 보여준다. 자주 까먹고 다시 찾아보게 되어서 기록해둠.
pip install할때 cache를 사용하지 못하게 막고 싶을때¶
docker build시 특정 레이어 이후로만 캐시 비활성화 하기 | Postlude's IT Blog
ARG DISABLE_CACHE
를 하고 docker 실행할때 저 arg값을 줘서 해당 줄 이후로는 전부 다시 빌드하게 만드는 방법. 이때 DISABLE_CACHE
값에 현재 시간 처럼 계속 변하는 값을 줘야 캐싱된 값을 안 쓴다. 하지만 이건 docker-compose랑 쓸때 저 disable 값에 변동되는 값을 넣을 수 없는 문제가 있어서 적용이 불가능...
아래의 방법을 사용.
docker-compose -f docker-compose-worker.yaml down
docker-compose -f docker-compose-worker.yaml build --no-cache
docker-compose -f docker-compose-worker.yaml up -d
이렇게 하면 캐시 없이 처음부터 docker compose를 빌드하므로 시간이 조금 걸리긴 하는데, 대신 확실하게 패키지 수정된 것을 다시 받아와서 설치한다.
2024. 07. 31¶
캐시 없이 docker-compose를 반복했을때 용량을 다 써버리는 문제 해결¶
docker system prune으로 캐시가 쌓이지 않게 하자.
c# setup project에서 상황에 따라 다른 파일을 추가하도록 하는 방법¶
파일의 속성 중 Condition
이라는 것이 있어서 거기에 $(ConfigurationName) == MyConfigName
같이 조건을 넣어보았다.
ㄴ 이거 작동 안함.
TJStory | 열정 그 이야기.. :: Visual Studio Setup and Deployment / 비쥬얼 스튜디오 셋업 프로젝트 (tistory.com)
여기 내용 참고하면 설치하는 상황에 유저가 무엇을 하는지에 따라 조건 걸어놓는 식으로 쓰는 것이지 setup 파일 만들때 조건이 걸리는 것이 아니다.
visual studio - Setup project: Using dynamic path for adding a file - Stack Overflow
내가 하고 싶은 것과 동일한 질문. 그리고 답이 달려있지 않음.
AutoCAD transient가 생겼다가 바로 사라지는 이슈¶
AddTransient won't draw image AutoCAD 2023 .net c# - Stack Overflow
c# GC랑 transient가 사라지는 것이 연관되어 있을 수도 있다는 답변.