study 973

2023-03-27 월요일

경기가 안좋아지면서, chatgpt라는게 나오면서 업계 분위기가 확확 변하는것 같다. 2년 전 코로나때만해도 개발자의 인기가 끝도 모르고 올라갔는데, chatgpt가 나오면서 개발자들 일자리 줄어드는거 아니냐, 경기가 안좋아지면서 들리는 다른 회사들의 연봉 상승률도 낮고, 이제는 누군가에게 개발자 하라고 추천하기도 그렇다. 작년까지만 해도 나름 기술적으로 알아낸거.. 그런 글을 종종 쓰다가 요즘은 일기형식의 이런 글만 쓰는데 바빠서인것도 있지만 근본적으로 마인드가 바뀐것 같다. 이전 직장에서 이전 팀에서의 역할과 지금 회사에서 지금 역할이 좀 달라져서 그런것 같은데.. 이전 팀에서 한 일을 요약하자면 '시키는대로 여러 일을 하는 개발만 하는 잡부'였다. 다른 팀과의 일정조율, 의사결정 등을 팀장님이 거의..

2022-12-16 금요일

곧 배포일정이 다가오느라 최근 한달간 매우 바빴다. 딱히 이런생각을 안하고 있었는데 전 회사에서는 회사에서 주목하지 않는 프로젝트를 하는 팀에 있었다. 장점이라면 큰 실수를 할 거리가 없다는것과 주목하지 않으니 압박이 딱히 없다는것.? 단점은 주목하는 팀이 성과를 당연히 많이 가져가고 내가 있던 팀의 경우는 별로 못 가져간다. 는 것이 있다.(물론 연봉상승이나 인센과도 관련이 있었다.) 그런데 현회사에서는 실단위(조직단위)내에서도 많이 주목하는 프로젝트를 하고 있는데 연말에 우리 프로젝트가 나름 지목되어서 상도 받고 성과가 눈에 보이니 전회사랑 느낌이 상당히 다르다. 둘다 겪어보니 오히려 이런 주목받는 프로젝트를 하는게 내 성향상 확실히 더 맞는것 같다. 좀 빡세더라도 결과물이 눈에 보이니 뭔가 더 불태..

2022-10-13 목요일

너무 바쁘다. 우연히 두개의 일을 맡게되었는데 하나를 메인으로, 하나를 서브로 했었는데 서브 일이 전사목표가 되면서 갑자기 중요도가 메인보다 높아졌다. 엄청 바빠졌고 리소스 배분을 7:3정도로 문서상에서는 했는데.. 7:3은 정말 문서상이고 10:10인것 같다 ㅋㅋ 예전처럼 기술공부를 한다고 해도 뭔가를 적을 시간이 없다. 뭔가를 적을 시간이 있으면 하나라도 더 개발하거나 문서 읽기에 바쁘다. 그래도 예전보다 지금이 더 소비자와 맞닿은 면이 더 넓은 작업을 하다보니 확실히 더 재미있고, 팀원들이 똑똑한데 열정까지 많아서 배우는게 정말 진짜로 많다. 주위에 똑똑한 사람들이 정말 많다. 사실 협업하거나 대화하면서 느낀건데 와 저분에게서는 배울게 정말 많을것같다, 나랑 비슷한연차인것같은데 느껴지는 포스가 뭐이..

2022-06-30 목요일

우형에 입사하고 거의 한달이 되간다. 전직장인 쿠팡과 비교해서 우형은 비슷하면서 정말 다른 회사라는걸 느낀다. 일단 비슷하게 느껴지는건 개발환경이나 개발문화같은거다. 어떤 프로젝트를 하는데 기술이나 언어적인 제약이 딱히 없이 그때그때 팀에서 모여서 정하고 등 개발적인 부분에 대해서는 쿠팡과 비교해서 아직까지는 겉만 핥았지만 비슷한 느낌인것 같다. 정말 180도 다르다고 느낀건 문화다. 우형에 와서 느낀거지만 쿠팡이 좀 폐쇄적, 개인적(우리가 생각하는 일반적인 회사) 이라면 우형은 정말 개방적, 외향적이고 직원을 위한다는 느낌이 든다. 내가 신기하게 느꼈거나, 직원을 위한다는 느낌이 들었던 케이스, 자랑, 좋은점 등을 적어본다. 1. 근무시간이 매년 줄어듦.(작년 35시간 이번년 32시간 비포괄 재작년은 ..

데이터 엔지니어 경력 5년 이직준비 후기

자소서 : http://qkqhxla1.tistory.com/797 면접 후기 : http://qkqhxla1.tistory.com/799 내가 한 공부들과 방법 : http://qkqhxla1.tistory.com/802 취업을 위한 알고리즘 공부법 : http://qkqhxla1.tistory.com/990 데이터 엔지니어 경력 5년 이직준비 후기 : https://qkqhxla1.tistory.com/1193 오랫만에 글을 쓴다. 최근 두달동안 글이 없었는데 모든걸 이직준비에 올인하느라 글이 없었다. 제목에 적었듯이 나는 데이터 엔지니어 직군인데, 데이터만 다루는 직군은 예전부터 있었지만 데이터 엔지니어라는 명칭으로 it회사들의 채용공고에 박힐정도로 정립된지는 3~4년 정도 된것 같다. 그래서 현재..

private/memo 2022.04.27

leetcode 1995, 2078(two pointer), 744(이분 탐색)

1995 https://leetcode.com/problems/count-special-quadruplets/ easy문제인데 O(n^2)의 시간복잡도로 풀려고 생각해보자. a+b+c=d가 나와야 하는데 c를 넘기면 a+b=d-c로 만들수 있다. 그리고 요 두파트를 각각 계산하면 된다. https://leetcode.com/problems/count-special-quadruplets/discuss/1446988/JavaC%2B%2BPython3-Real-O(n2)-solution class Solution: def countQuadruplets(self, nums: List[int]) -> int: # a + b = d - c d = {} ret = 0 n = len(nums) for i in rang..

leetcode 1763(브루트포스), 1099(two pointer), 395(구현), 1071(구현)

1763 https://leetcode.com/problems/longest-nice-substring/ easy 로 분류되었는데 medium 하위정도 되는것같다. O(n^2)으로 모든 경우를 탐색한다. 길게 좌우에서 조여오면서 탐색한다. cur_s는 l과 r이 움직임에 따라 만들어지는 부분적인 문자열이고, cur_s내의 모든 문자가 대문자와 소문자가 cur_s내에 존재해야 하면서 이게 이전 길이보다 더 길면 바꿔준다. class Solution: def longestNiceSubstring(self, s: str) -> str: len_s = len(s) l = 0 ret = '' while l < len_s: r = len_s - 1 while l < r: cur_s = s[l:r+1] if all(..

leetcode 974(prefix sum), 1375(구현;), 93(백트래킹), 616(merge interval)

974 https://leetcode.com/problems/subarray-sums-divisible-by-k/ subarray의 합이 k로 나눠지는 subarray를 구해야하는데 인덱스와 상관없이 구하는게 아니라 근처의 값들로만 구성해야 해서 백트래킹같은게 아니다. 앞에서부터 prefix sum을 계산해주며 prefix sum이 k로 나눠지면 그 값이 존재하는만큼 더해준다. 그리고 뒤에서도 사용하기 위해 그 값이 나온만큼 증가시켜준다. class Solution: def subarraysDivByK(self, nums: List[int], k: int) -> int: ret = 0 d = {0: 1} prefix_sum = 0 for i in range(len(nums)): prefix_sum += ..

leetcode 2024(sliding window), 424(sliding window), 498(대각 행렬), 99(s트리)

2024 https://leetcode.com/problems/maximize-the-confusion-of-an-exam/ 바로 앞글의 1004번 문제랑 똑같다. 근데 이번엔 T나 F의 최대값으로 만들어야 한다. 그러면 간단하게는 T일경우의 최댓값과 F일경우의 최댓값을 구해서 그중에 최댓값을 리턴하면 된다. class Solution: def maxConsecutiveAnswers(self, ans: str, k: int) -> int: #ans = 'TFFT' #k = 1 l,r = 0,0 d = {'T':0, 'F':0} ret = 0 while r k and d['F'] > k: # l과 r사이, 즉 ..

pyspark read mongodb, mysql

이전에 이거 관련해서 글을 썼었는데.. 너무 뒤죽박죽한 글 구성 + 잘 모르는데 여기저기서 이상하게 갖다붙힘 + 버전이 낮아짐에 따라 쓸모 없어진 글이 되버려서 이전 글은 삭제하고 다시 좀 다듬어서 정리합니다. 현재 쓰고있는 spark 3 버전 초반 기준입니다. 1. mongodb 공식 api : https://docs.mongodb.com/spark-connector/current/python-api/ 몽고디비에서 데이터를 읽는 예시를 예로 듦. https://docs.mongodb.com/spark-connector/current/python/read-from-mongodb/ 공식 홈페이지에 코드 예제가 있는데.. pipeline = "{'$match': {'type': 'apple'}}" df = ..

data engineering 2021.12.28

leetcode 935(dp), 503(monotonic stack), 1004(sliding window), 340(sliding window)

935 https://leetcode.com/problems/knight-dialer/ 미리 다음에 갈수 있는 길들을 저장해놓는다. 그리고 n번만큼 반복해주면서 메모이제이션으로 한번 했던 계산은 하지 않도록 조절한다. class Solution: def knightDialer(self, n: int) -> int: #n=3131 d = {-1: range(10), 0: [4,6], 1: [6,8], 2: [7,9], 3: [4,8], 4: [0,3,9], 5: [], 6: [0,1,7], 7: [2,6], 8: [1,3], 9: [2,4]} cache = {} def dp(n, path): if n == 0: return 1 key = (n, path) if key in cache: return cach..

leetcode 1405(그리디+heap), 143(linked list), 370(prefix sum), 739(stack, heap)

1405 https://leetcode.com/problems/longest-happy-string/ 단순히 dfs로 짜면 시간초과가 나왔다. 더 효율적으로 생각해보다가 가장 긴 길이를 만들어내려면 현재 존재하는 a,b,c중에서 가장 많이 존재하는 단어를 먼저 사용하는 전략으로 결과값을 만들어야 한다. 단어와 단어 카운트를 기반으로 힙을 만들어준 후 남아있는 단어중 갯수가 가장 많이 남아있는것부터 빼서 계산하는식으로 처리한다. from heapq import * class Solution: def longestDiverseString(self, a: int, b: int, c: int) -> str: s = '' while a > 0 or b > 0 or c > 0: heap = [] if a > 0 a..

leetcode 39(backtracking), 1353(그리디), 128(two pointer), 368(lis)

39 https://leetcode.com/problems/combination-sum/ 별다른 설명이 필요 없다. 백트래킹 연습용으로 좋은 문제다. class Solution: def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: #candidates = [1,2] #target = 4 ret = [] def get_comb(candidates, cand, target): if target == 0: ret.append(cand) return for i in range(len(candidates)): if target-candidates[i] >=0: get_comb(candidates[i:], cand + [c..

leetcode 1209(stack), 1048(dp), 1854(그리디, 범위내 최대값)

1209 https://leetcode.com/problems/remove-all-adjacent-duplicates-in-string-ii/ 딱봐도 스택문제다. 새 문자가 들어올때마다 새 문자와, 새 문자가 존재하는 갯수를 넣어두고, 동일한 문자가 들어오면 카운트를 증가시켜준다. 이후 마지막 문자가 k보다 큰 경우 연산을 해준다. class Solution: def removeDuplicates(self, s: str, k: int) -> str: #s = "deeedbbcccbdaa" #k = 3 ret = '' stack = [] for i in range(len(s)): if stack and s[i] == stack[-1][0]: # 이미 들어왔던 문자의 경우 카운트를 늘려준다. stack[-1..

leetcode 244(two pointer), 91(dp), 909(bfs), 16(two pointer)

244 https://leetcode.com/problems/shortest-word-distance-ii/ 모든 word의 인덱스를 저장해놓는다. 그리고 구해야 하는 두 점에 대해서 투 포인터로 가장 근접해 있는 점 끼리의 최소값을 업데이트해준다. class WordDistance: def __init__(self, wd: List[str]): self.d = {} for i, w in enumerate(wd): self.d[w] = self.d.get(w, []) + [i] #print(self.d) def shortest(self, w1: str, w2: str) -> int: ret = 9999999999 i,j = 0,0 d1,d2 = self.d[w1],self.d[w2] while i < l..

leetcode 227(basic calculator), 1197(bfs, dp등), 1010(2sum 다른버전), 526(dp)

227 https://leetcode.com/problems/basic-calculator-ii/ 이전 부호의 상태값을 저장해놨다가 그걸 기반으로 푼다. 이런 계산기반의 문제는 보통 부호를 한번 저장해놓고 다음단계에 가져와서 쓰는식으로 하는것 같다. 하드문제인 https://leetcode.com/problems/basic-calculator/ 와 비교해보면서 익히자. class Solution: def calculate(self, s: str) -> int: num = 0 stack = [] sign = '+' i = 0 while i < len(s): #print(s[i],stack) if s[i].isdigit(): num = num * 10 + int(s[i]) if s[i] in '+-*/' o..

leetcode p1762(구현), 2079(꽃에 물주기,시뮬레이션), p1676(LCA), 394(stack, regex, 구현)

1762 https://leetcode.com/problems/buildings-with-an-ocean-view/ 왼쪽에서부터 검사하면 오른쪽에 높은 벽이 나타났을때 다시 왼쪽의 케이스를 체크해야한다. 그런데 오른쪽에서부터 왼쪽으로 가면서 하면 다시 오른쪽의 케이스를 체크할 필요가 없다. 오른쪽에서 왼쪽으로 가면서, 최대값을 유지해주고 현재까지의 최대 높이보다 높아지는 왼쪽 높이가 나오면 그 인덱스를 저장해두면 된다. class Solution: def findBuildings(self, h: List[int]) -> List[int]: cur_max = 0 ret = [] for i in range(len(h)-1, -1, -1): if h[i] > cur_max: ret.append(i) cur_m..

leetcode 986(구현, two pointer), 1043(dp), 1329(대각 정렬행렬)

986 https://leetcode.com/problems/interval-list-intersections/ 왠지 그리디 문제같이 생긴 list intersection문제이다. 무식하게 풀면 안되고 규칙을 찾은 뒤에 구현하면 된다. 투 포인터를 쓰기는 하는데 그냥 구현하면 된다.. 두개의 리스트가 있을때 겹치는 경우는 first_start List[List[int]]: diagonal_dict = {} for i in range(len(mat)): for j in range(len(mat[0])): if i-j not in diagonal_dict: diagonal_dict[i-j] = [] diagonal_dict[i-j].append(mat[i][j]) #for k,v in diagonal_dic..

leetcode 1026(트리), 1525(two pointer, hashmap), 1884(dp, 계란층문제)

1026 https://leetcode.com/problems/maximum-difference-between-node-and-ancestor/ 어떤 트리에서 자손 관계에서 절대값의 차가 최대가 되어야 한다. 방법론을 생각해보면 현재 노드 아래 자식들중에서의 최대값과 최소값을 알고 있어야 한다. 그래야 abs(현재노드- 자식 최대값), abs(현재노드- 자식 최소값)의 최대값을 구할수있기 때문이다. class Solution: def maxAncestorDiff(self, root: Optional[TreeNode]) -> int: self.ret = 0 def inorder(node): if not node: return 9999999999, -9999999999 l_min, l_max = inorde..

카테고리 없음 2021.11.27

leetcode 2023, 979(트리), 1310(prefix xor)

2023 https://leetcode.com/problems/number-of-pairs-of-strings-with-concatenation-equal-to-target/ 요건 제한조건이 너무 단순해서 그냥 마음가는대로 이중 반복문으로 풀수도있지만 그랬다가는 알고리즘 공부하는 의미가 없다. nums리스트에서 두개만 앞값 + 뒷값으로 문자열을 연결했을때 target이 나오면 된다. prefix, suffix 딕셔너리를 만들어서 풀수 있는데, prefix 딕셔너리에는 앞에서 얼마만큼 만들었는지를 저장하고, suffix 딕셔너리에는 뒤에서 얼마만큼 만들었는지를 저장해둔다. nums = ["123","4","12","34"], target = "1234" 인 경우를 예로 보면 target 1234에 대해서 ..

prometheus + grafana getting started(k8s node monitoring)

모니터링을 위해 설치했던 prometheus와 grafana를 가볍게 재정리합니다. 관리하는 k8s의 노드 리소스 모니터링을 진작 만들었어야 했는데 다른거 하느라 못하다가 시간이 남아서 이번에 추가했다. 모니터링은 prometheus + grafana로 하기로 했다. 1. Prometheus 먼저 prometheus의 아키텍쳐에 대해 알아보자면 https://blog.outsider.ne.kr/1254 요 글이 파악하기에 가장 설명이 잘되어있었다. https://prometheus.io/docs/introduction/overview/ prometheus는 크게 Exporter, Push gateway, Server, Alert manager로 나눌수 있다. - Exporter는 모니터링 대상의 메트릭 ..

data engineering 2021.11.08

mysql simple dump process

1. 걸릴 시간을 대략적으로 체크해보기 위해 테이블의 크기를 확인한다. 참조 : https://stackoverflow.com/questions/9620198/how-to-get-the-sizes-of-the-tables-of-a-mysql-database 아래 쿼리를 돌려본다. 테이블의 크기가 어느정도 큰 경우로 생각해서 gb단위로 출력해본다. mysql> select table_name, round(((data_length + index_length) / 1024 / 1024 / 1024), 2) `size (gb)` \ -> from information_schema.TABLES WHERE TABLE_SCHEMA = "{내 디비}"; +-----------------------------------..

data engineering 2021.11.04

customizing spark helm chart

이번에 쓸 글은 spark자체를 커스터마이징 한다기보다 삽질과, bitnami spark helm chart를 구성하는 것들을 살펴보는데 중점을 둔 글입니다. 전에 쓴글 중에 https://qkqhxla1.tistory.com/1164?category=698045 에서 스파크에서도 airflow와 python 세팅이 동일해야 하는 이유를 적었었다.(spark의 python udf 사용 불가능) 최근에 회사에서 이슈가 있어서 k8s 서버를 통째로 옮겨가야 할 일이 생겼다. 랜쳐도 새로 설치했고, 내부의 App들을 옮기는 중인데 spark를 옮기던 도중 지금이 spark에 airflow와 같은 python 버전을 적용해야 할 적기라고 생각해서 세팅한다. 우선 내부의 파이썬 버전을 바꾸기 위해서는 기본적으로 ..

data engineering 2021.10.25

redash, +kibana와 비교

최근에 새로 들어오신 분에게서 redash라는걸 알게되었다. redash는 kibana나 grafana처럼 데이터 시각화 툴이다. 나는 주로 키바나를 사용하는데, 키바나보다 사용법은 훨씬 직관적이고 쉬웠다. 다만 구조가 다르고, 장단점이 확연히 존재하였다. redash를 가볍게 사용하고 느낀점을 정리한다. 일단 redash tutorial링크 : https://redash.io/help/user-guide/getting-started 키바나의 시각화 과정을 가볍게 그리면 아래와 같다. 가볍게 이런식이다. DB에서 파이썬이나 자바로 내가 원하는 형태로 데이터를 가공해서 es에 저장할수 있고, 이 1차적으로 가공된 데이터를 기반으로 2차적으로 가공을 해서 키바나에서 시각화를 할 수 있다. redash의 동작..

data engineering 2021.10.16

pyspark when does python used in spark 'worker'

apache spark를 쓰는데 리모트 환경에서 submit하는 환경이면 주의해야할게 상당히 많았다. 예로 1. spark submit하는곳과 spark server의 버전이 같아야 한다. 메이저 버전이 같으면 호환되는 경우도 있는데 호환 안되는 경우도 많다.. 2. spark submit을 리모트 서버의 도커에서 하는 경우 네트워크를 호스트와 동일하게 해주거나, 도커의 포트 설정을 추가로 해줘야 한다. 이전글 : https://qkqhxla1.tistory.com/1138 등이 있었다. 위의 방법들이 그닥 선호되는 방법은 아니어서 최근에는 일반적인 방법으로 사용해보려고 airflow를 세팅해서 그 안에 스파크를 submit용으로 설치해서 리모트 스파크 서버에 호출해서 쓰는 방법으로 사용하고 있다. 그리..

data engineering 2021.10.14

about self signed certificate(ssc), apply my ssc to rke

인증서에 대해 아는 지식이 거의 없어서.. 이번에 self signed certificate를 만들면서 알게된 내용을 정리함. 여기저기 찾아보고 정리하긴 했는데 확실하지 않은 정보가 좀 있어서 틀린부분 있으면 지적해주시면 정말 감사하겠음.. 읽을거리(개념정리용) : https://m.blog.naver.com/alice_k106/221468341565 대부분의 내용 참조함.(실습용) : https://www.lesstif.com/system-admin/openssl-root-ca-ssl-6979614.html 추가 읽을 거리(영어 버전) : https://phoenixnap.com/kb/openssl-tutorial-ssl-certificates-private-keys-csrs 일단은 개념정리를 먼저 하..

data engineering 2021.10.09

leetcode 160(linked list), 2006(caching), 1850(permutation, 구현)

160 https://leetcode.com/problems/intersection-of-two-linked-lists/ easy난이도인데 맨 아래의 제한조건이 O(n) 시간복잡도, O(1) 공간복잡도이다. 이거 생각하면서 풀려면 어렵다. 예제들을 살펴보면 교차로부터는 값이 전부 동일한걸 알수있다. input a,b중에 길이가 긴 링크드 리스트를 짧은 링스크 리스트랑 길이를 맞춰줄만큼 앞으로 전진해서 탐색을 시작한다. 둘다 똑같이 한칸씩 전진하면서, 값이 같으면 그걸 리턴해주고, 같은 값이 없으면 아무것도 리턴해주지 않으면 된다. class Solution(object): def getIntersectionNode(self, headA, headB): len_a, len_b = 0, 0 t_headA, ..

pyspark Cannot cast DOCUMENT into a NullType 관련.

pyspark로 몽고에서 컬렉션을 읽어와 잡을 돌리고 있다. 몽고에서 컬렉션을 읽어와서 title이라는 필드에서 \t,\r,\n을 제거하고 이후의 프로세싱을 하기 위한 작업이다. ....... df = self.spark.read.format("com.mongodb.spark.sql.DefaultSource") \ .option("spark.mongodb.input.partitioner", "MongoSamplePartitioner") \ .option("spark.mongodb.input.partitionerOptions.partitionKey", "_id") \ .option("spark.mongodb.input.partitionerOptions.partitionSizeMB", 128) \ .opti..

data engineering 2021.09.20

airflow Kubernetes Executor, how helm values.yaml works

바로 이전글(https://qkqhxla1.tistory.com/1159) 에서는 kubernetes에서 helm을 사용해 airflow를 구성하는데 초점을 두었었다. 그런데 내가 kubernetes와 helm에 익숙하지 않아서 가장 쉽고 익숙한 airflow를 CeleryExecutor로 구성했었다. airflow-worker에 spark를 통째로 올려놓고, docker-in-docker로 docker를 마운트해놓은다음 대부분의 배치 잡은 DockerOperator로 실행하고, spark잡을 실행할 때는 airflow-worker내에 설치된 스파크를 직접 호출해서 사용한다. 간단한 구성도이다. CeleryExecutor이 기본 설정으로 되어있기도 하고 구성도 쉬워서 이렇게 만들었었는데, 구성하고 이것저..

data engineering 2021.09.05