3월부터 새로운 직장을 다니게 되었다.

이전 회사에서 했던 업무가 딥러닝과 데이터 분석에 초점이 맞춰져 있었다면, 이번 회사에서 맡게 된 업무는 내가 그동안 하고 싶었던 Ops 관련 및 백엔드 업무이다. 워낙 새로운 걸 도전하고 배우는 것을 좋아하는 나인지라 흥미를 느끼고 흔쾌히 시작하겠다고 패기 좋게 말했다. 해보지 않았던 업무이기 때문에 조금만 배우면 쉽게 적응하고 따라갈 수 있을거라 생각했지만 생각 외로 고난이 가득한 길이었다. 물론 회사에서도 나를 채용하며 어느정도 배움의 시간이 필요할 거라 생각했겠지만, 이정도로 내가 못 따라올 줄은 예상하지 못 했을 것 같다.

시간은 흐르고 성과물은 없으니 조급해지는 마음은 사람인지라 어쩔 수 없었다. 일등으로 출근해서 막차를 타고 퇴근하는 시간을 매일 보내도 문제는 해결되지 않고 고민의 시간만 길어졌다.

 

평일 스터디를 올스탑하고 업무에 집중했다. 사람도 만나지 않았다. 주말에도 업무를 했다. 부족한 내 실력을 메꾸는 방법은 그 방법뿐이 없다고 생각했다. "가장 빠르게 가는 방법은 가장 정확한 방법으로 가는 것이다." 라는 말을 몸소 실천하고 싶었지만 그럴 수 없는 내 자신에 화가 났다.

헬스장과 회사, 집만 반복하니 잡 생각도 들지 않았다. 꿈 속에서도 회사였다. 업무에만 매진하는 한 달을 보냈다. 어느 주말, 업무를 하려고 노트북을 여는 순간 두통이 몰려오는 걸 느끼며 그제서야 번아웃이 온 걸 알았다. 스트레스를 받으면서도 의도적으로 회피해왔던 것이다. 업무 스트레스를 운동으로 풀었기 때문에 중량은 계속해서 갱신을 했고 나의 운동 수행능력이 증가한줄로만 알았다. 물론 배운건 정말 많았다.

생에 처음으로 만든 백엔드 모듈을 도커와 kubernetes로 서버에 배포하였고, GCP, mysql, 파이썬을 다루는 실력이 확 늘었다. 하지만 여전히 jupyter notebook 위주의 작업 스타일과 객체 지향적이지 않은 코드는 남아 있었고, 다른 base 파일을 import 해오는 것이 익숙하지 않았다. 금세 바꿀 수 없는 문제라는 걸 인지하고 받아들이기로 했다. 몇번이나 rollback을 반복한 뒤에 나의 문제점을 깨달았다. 

 

다행히 사수님이 자신감이 많이 하락하고 의기소침해 있던 나를 북돋아주시고 칭찬과 조언도 많이 해주셨다. 다시 기운을 차리고 매진하고 있다. 팀 워크샵도 다녀왔는데, 업무 생각을 많이 떨쳐버리고 친목을 도모하는 데 집중했다. 요즘 유행하는 말이 중요한건 꺾여도 그냥 하는 마음이라는데, 4월 한달동안은 나도 꺾이지 않으려고 노력해왔던 것 같다. 하지만 계속해서 한 방향만 바라볼수록 부러지기 쉽다는 건 몰랐다. 정신을 차려보니 시간이 지나있어서 어떻게 흘러갔는지도 모르겠다.

지금 이 과정과 이 시간 하나하나가 나에게 굉장히 소중한 시간이란 걸 잘 알고 있다. 작은 것들을 쌓아 내 걸로 만들고 더 큰 성과를 내고 싶은 욕심이 있다. 4월 한달동안 힘들었던만큼 다시 심기일전하여 5월,6월을 넘어 계속해서 롱런하고 싶다.

'Think' 카테고리의 다른 글

2023년 회고  (0) 2024.01.12
2023년 5월 회고  (0) 2023.05.31
2022년 9월 회고  (1) 2022.10.04
2022년 8월 회고  (0) 2022.09.01
2022년 상반기 회고  (0) 2022.08.01

문제

dbeaver에서 한글 깨짐 현상 발생하여 인코딩 문제임을 알아차렸다. 

 

 

해결방법 

home에서 shift + cmd + G 키를 눌러 DBeaver를 검색한다.

 

 

Applications > DBeaver > Contents 디렉터리로 들어가면 아래와 같이 나오고 이 중 Eclipse 폴더로 들어간다.

 

 

dbeaver.ini 파일을 연다. 

 

vscode로 파일을 열면 아래와 같이 적혀있다.

 

마지막줄에 아래와 같이 추가해준다.

-Dfile.encoding=utf8

 

 

정상적으로 한글이 보인다.

 

만약, 이렇게 해도 해결이 되지 않는다면 이는 인코딩 문제가 아닌 것이다. utf-8로 정상적으로 인코딩이 되어있지만, byte로 되어있는 문자열을 string 그대로 출력해줘서 그런 것이다. 이럴 때는 아래와 같은 SQL 문을 통해 변경하여 확인해야 한다.

HEX(column name)

 

 

hex() 는 SQL 내장 함수로, 주어진 문자열의 문자를 16진수로 반환한다. input 문자열을 바이트로 간주하고, 각 바이트를 16진수로 표현한 후 문자열로 반환한다. 

SELECT HEX(name) AS NameValue FROM info;

위의 문법은 infof라는 테이블에서 name이라는 이름을 가진 column의 값을 NameValues 라는 컬럼으로 변경한다.

꾸준히 나를 기록하지 않으면 기간 중 최근의 기억에 치중되는 경향이 있다. 이를 방지하기 위하여 많이 기록하려 노력했는데 그리 쉽지는 않은 습관이다. 10월부터는 조금 더 분주하게 메모해야겠다.

북한산

Work

업무를 위해 공부를 많이 하였다. 특히 이미지 데이터를 다루며 tensor 사이즈나 메모리 이슈를 많이 접하였다. 확실히 이론적으로 접하는 부분과 실무에서 접하는 에러가 다름을 많이 느꼈다. 이론을 익힌 후에는 레퍼런스만 보는 것보다 때로는 부딪혀 보는 것이 성장에 큰 도움이 되는 듯 하다.

Health

8월부터 개인사정으로 힘들었던 몸과 마음을 달래기 위해 9월에는 공사다망한 와중에도 등산을 많이 갔다. 잡념이 많아지는 것을 정리하기 위해 몸을 움직이러 자연으로 여기저기 떠났는데, 덕분에 몸과 마음이 많이 치유되었다. 추석 연휴에는 4번이나 등산을 갔는데, 등산을 자주 가니 퇴근 이후에도 야간 등산을 가는 것이 습관이 되어 체력이 좋아졌다.

혼자 산을 오르며 사색하는 것이 좋아 혼자 가곤 했는데 관악산을 갔다가 길을 잘못 들고 휴대폰이 방전되고, 랜턴 배터리가 나가는 바람에 헤매다가 다행히 다른 등산팀에 합류하여 겨우 하산하였다. 당시 어르신들께 혼쭐이 났는데 혼자도 좋지만 가끔은 동행인과 같이 등산을 하는 것도 좋을 것 같다.

유도를 관둔 김에 풋살을 시작했다. 복싱, 웨이트, 런닝, 수영, 유도 등 개인 플레이만 하던 내가 팀플레이를 잘 할 수 있을까 걱정이 되었는데 멤버들을 잘 만난 덕분에 생각보다 재미있게 즐기고 있다.

식탐이 많았는데, 지금은 식탐도 거의 없고 식사 속도도 많이 느려졌다. 식사를 크게 조절하지 않아도 건강과 더 가까워지는 기분이다.

Experience/Knowledge

특정 시점을 계기로 실력이 upgrade 되는 것을 느끼는 순간이 있는데, 아직은 그 지점에 도달하지 못했다. 다만, 요새 많이 사용하는 '메타인지' 의 중요성을 많이 느낀 한 달이었다. 

1년 반만에 멘토님을 만났다. 원하는 지점에 도달하기 위하여 가는 길 중에 도랑에 빠지기도 하지만, 지나고 보니 실패와 경험 속에서 배우는 수반 지식들이 결국 큰 자양분이 됨을 또다시 일러주셨다. 또한 인간 관계의 중요성과 실행력의 중요성을 또다시 배웠다. 또 peer 간의 커뮤니케이션도 결국 돌고 돌아 나의 성장의 밑바탕이 된다는 점을 깨달았다.

네이버에서 주관한 실리콘밸리의 한국인 컨퍼런스에 참가하였다. 미국 실리콘밸리 기업 문화에 대해 많이 알 수 있었다. 장단점이 있겠지만, 네트워킹과 멘토링 문화는 정말 센세이션이었고 꼭 한 번 경험해보고 싶은 문화이라 언젠가 꼭 경험해보리라 다짐했다. 미국에서 말하는 사회의 필터링 시스템 또한 인상적이었다. 

한국은 소위 말하는 엘리트코스 (강남8학군-명문중학교-특수목적고-아이비리그나 sky,치의대-의전법전 등) 가 있으며 조금이라도 낙오되거나, 혹은 코스에서 이탈하는 경우 낙인이 찍히거나 인정을 해주지 않는 경우가 대다수다. 하지만 미국은 패자부활전 제도가 잘 발달되어 있기 때문에 어떤 사람의 출신이나 과거가 어떻든 결국 돌고 돌아 올라올 사람은 올라온다고 믿고, 그걸 인정해준다는 사실이 너무 좋았다.

내가 이런 문화에 대해 왈가왈부할 실력은 전혀 아니다. 물론 한국도 비전공자 출신 개발자도 많고, 학력 위주의 채용은 사라지는 추세이지만 아직까지는 많이 보수적이고 후려치기가 심한 것 또한 사실이기에 한국도 이러한 사회 분위기가 있다면 조금 더 도전적이고 실행력이 좋은 인재들이 더 많이 생기지 않을까하는 생각이다.

ai interview 스터디를 통해 배우는 점이 굉장히 많다. 한동안 영어스터디를 참가하지 못했는데, 오랜만에 참가했더니 영어가 막힘없이 나와서 신기했다.

개인적으로 30일의 기적 프로젝트를 시작하였다. 다음달 회고에 후기를 쓸 수 있을 것 같은데 나의 꾸준함이 기대된다.

'Think' 카테고리의 다른 글

2023년 5월 회고  (0) 2023.05.31
2023년 4월 회고  (0) 2023.05.09
2022년 8월 회고  (0) 2022.09.01
2022년 상반기 회고  (0) 2022.08.01
2022.1Q 회고  (0) 2022.04.07
실전 시계열 분석을 보며 정리했습니다.

 

[Last updated : 2022-09-14]

정의

시계열 분석은 시간 순서대로 정렬된 데이터에서 의미있는 요약과 통계 정보를 추출하는 것이다. 과거 행동 진단뿐만 아니라 미래 행동 예측에도 사용된다. 

 

1.1 다양한 응용 분야의 시계열 역사

'과거가 미래에 어떤 영향을 주는가?' 와 같은 인과관계를 다루는 질문으로 시계열 분석에 대해 일축할 수 있다.

 

1.1.1 시계열 문제로서의 의학

존 그란트(John Graunt)는 1500년대 초반부터 사망 기록 연구를 시작하여, 특정 연령대에 있는 사람이 다음 생일 전에 사망할 확률을 구했다. 그란트는 처음으로 사람의 건강을 문서에 기록한 통계학자이다. 하지만 당시에는 찬밥 신세를 받았다.

그 이유는 당시 생리학, 해부학이 훨씬 우세하다는 여론이었고 통계적 방법이 임상적 관찰보다 낫다는 근거가 부족했다. 그리하여 시계열 분석이 의학에 도입된 시기는 다른 분야보다 훨씬 늦다. 아주 장기간에 걸쳐 규칙적으로 과학 시설로 관측된 데이터가 있어야 하기 때문이다.


의료 기구

환자에 대한 시계열 분석은 통계적 차원의 연구보다 훨씬 일찍 시작되었다. 1901년 심전도 (ECG) 가 발명되었고, 1924년 뇌전도 (EEG) 가 발명된 덕분에 시계열 분석을 의료 진단에 적용할 수 있었다. 하지만 해당 장비를 통해서는 오랜 시계열 데이터를 생성하지 못하기 때문에, 분석에 한계가 있었다. 다행히 최근 기술의 발달로 다양한 웨어러블 센서 기기가 등장하며 데이터 수집이 예전보다 쉬워졌고, 이로 인해 더 많은 시계열 데이터가 측정되어 의학의 발전에 기여할 수 있었다.

1.1.2 일기예보

고대 시절부터 기상에 대한 관심은 많았으며, 다양한 관측법과 기록을 통해 보관되어왔다. 하지만 과거에는 과학적인 기록법이 없었기 때문에, 1850년대가 되어서야 기상 기록을 위한 시설을 갖출 수 있었다. 이 시설을 기반으로 날씨가 측정되기 시작하였고 요즘날 사용되는 일기예보에 활용되는 의미있는 데이터셋을 생성할 수 있었다. 

 

1.1.3 경제성장 예측

19세기 말~20세기 초의 금융 위기는 불안감을 초래했고, 이러한 불안감은 경제 예측의 필요성을 야기시켰다. 경제를 순환 시스템에 비유할 수 있다는 생각에서 영감을 얻어 많은 경제학자들은 이러한 예측을 통해 경제 추락을 피할 수 있다고 생각하였다.

경제 데이터를 추적하기 위한 다양한 공공기관이 설립되었고, 오늘날 대부분 국가에서는 경제성장, 재앙, 호항과 불황 주기 등을 파악하거나 방지하는 데 유용한 데이터를 제공하고 있다. 예를 들어 오늘날 많이 사용되는 국내 총생산(GDP) 도 경제 지표의 한 분류로 볼 수 있다.

 

주식 시장

증권 거래소의 데이터를 통해 시장 참가자의 수준이 높아지고, 자동화 방식이 늘어나기 시작했다. 수학적인 접근 방식을 통해 이윤 창출을 추구하게 되었고, 최근에는 머신러닝이 주도하고 있다. 현재의 금융시장 분석은 자체적인 시계열 분석 방법을 사용한다.

리처드 데니스는 알고리즘을 통한 시계열 예측을 하였고, '인공지능'에 대한 생각에도 영향을 주었다.

 

1.1.4 천문학

천문학은 물체, 궤도, 측량 그래프 등을 활용하기 때문에 시계열과 큰 관련이 있다고 볼 수 있다. 시간의 흐름에 따라 우주가 변화하는 방식을 이해할 수 있도록 도와주는 데이터를 수집하기 위해 실시간 스트리밍 형태로 관찰을 함으로써, 도움을 받을 수 있었다. 

 

1.2 시계열 분석의 도약

조지 박스는 실제 세상을 묘사할 수 있는 모델을 만든다는 것은 가능성이 희박한 일이라고 주장하였다. 1970년에 등장한 박스-젠킨스 방법은 시계열 분석에 많은 기여를 했다.

당시, 많은 데이터셋을 모으는 건 가능했지만 R, 파이썬, C++ 등의 도구가 없었기 때문에 많은 데이터를 처리하는 것은 어려웠다. 따라서 시계열 분석과 예측은 컴퓨터의 발전과 동행할 수밖에 없었다. 1970년대 말 초기 개인용 컴퓨터, 컴퓨터 언어의 등장으로 인해 시계열 예측은 혁신을 가져왔다.

지난 수십년간의 하드웨어 기술의 발달로 인해 컴퓨터의 연산 능력은 증가하였고, 덕분에 시계열 분석 및 예측 또한 정확도가 올라갔다.

 

1.3 통계적 시계열 분석의 기원

(저자에 따르면) 통계학은 데이터의 질적인 측면에 의존적인 미성숙한 학문이었으나, 시계열 분석은 하나의 학문의 관점으로 볼 수 있다. 시계열 분석은 자기회귀 모델을 실제 데이터에 적용하였으며, 이는 주기성을 가정하지 않은 모델이다. 초기 시계열 분석의 모델은 전통적인 모델에 의존하였으나 현재는 과학의 발전에 따라 초기 문제들을 해결할 수 있으며, 동시에 다양한 비즈니스 문제를 해결할 수 있다.

 

1.4 머신러닝 시계열 분석의 기원

1969년 발표된 The combination of Forecasts 논문은 예측 성능을 향상시키기 위한 방법으로 '최고의 하나'를 고르는 것보다 여러 예측을 결합하는 방법을 제안했다. 이후 ensemble(앙상블) 방법이 널리 사용되었으며, 이는 월등히 뛰어난 모델이나 완벽한 방안보다는 여러 모델의 특성을 잘 조합을 하는 것이 나을 수 있다는 결론을 내렸다.

이러한 접근 방법은 다양한 시나리오에서 사용되기 시작했으며, 아직까지는 전통적인 통계 방법이나 선형적 방법이 시계열 분석을 지배하고 있다. (저자에 따르면) 시계열 분석과 예측은 황금기를 맞이하지 못했고, 앞으로 미래를 위한 도약을 여전히 기다리고 있다.

Work

데이터 분석가와 머신러닝 엔지니어로서 필요한 자질은 어떠한 것들이 있을까? 도메인 지식이 있다는 가정 하에 , 리서치를 하며 데이터에 대한 직관력과 인사이트를 키울 수 있겠지만 도메인 지식이 없을 때는 리서치만으로 해결되지 않는다. 도메인 없이는 컬럼명부터 이해가 가지 않는 경우가 굉장히 많다. 이번 달은 도메인 지식이 없던 데이터를 다루며 직관력과 인사이트를 얻는 방법을 많이 배웠다. 

또, 데이터 파이프라인과 서빙까지의 전반적인 flow 에 대한 학습도 필수적이라는 걸 알았다. 그저 파이프라인 구축에 관심이 있어요~ 라고 말하는 사람이 아니라 직접 구축하고 적재하고 모델까지 서빙할 줄 아는 사람이 되어야 한다.

이미지 데이터를 원천으로 수집하고 가공하고 라벨링하는 과정을 겪으며, 정제 데이터만 다루던 경험으로 느낄 수 없었던 raw data 처리의 중요성을 느꼈다.

Health

몸과 마음이 아팠던 한 달이었다. 근 몇 년간 이렇게까지 마음이 힘들었던 적은 없었는데, 운영하던 개인 사업의 행정적 처리 문제로 나도 모르는 사이에 스트레스를 많이 받았다. 무방비 상태로 받은 스트레스라 더 고통스러웠다. 그 외에도 업무적으로도 스트레스를 꽤 받아왔는지, 스트레스로 인한 급성 췌장염과 위염으로 며칠동안 회사도 못 가고 쉬었다. 혈액검사도 여러번 하고 링겔 맞고 약물 치료를 해도 잘 회복이 되지 않았다. 회사를 쉬는동안 회복에만 전념하니 많이 나아졌지만, 여전히 완전히 이전 몸 상태로 돌아오진 않았다. 

나는 스트레스에 대한 역치가 낮은 편이 아니다. 높은 축에 가깝지만, 한 번 타격을 받은 후에는 회복 탄력성이 낮기 때문에 오랜 시간이 소요된다는 사실을 이번에 깨달았다. 아직도 가끔은 회의 도중, 업무 도중 명치를 부여 잡고 몸을 숙여야지만 통증이 사라지지만 그래도 회복 중인 단계임을 인지하고 있고 조금씩 나아지고 있다. 

아파서 거의 유도를 못 나갔다. 관장님에게도 몸이 아프니 회복하고 가겠다고 연락을 해놨는데, 나도 모르는 사이에 유도 밴드에서 강제탈퇴처리가 되어 있었다. 오히려 잘됐다 싶어 등산이나 근력운동, 수영 등의 운동을 하고 있다. 날이 좋아 등산을 많이 가고 있다. 메인 사진은 8월 말의 인왕산이다.ㅎㅎ


Experience/Knowledge

지식을 쌓는 과정을 시각적으로 표현한다면 어떤 모습일까? 사실 차곡차곡이라기보단 두루뭉술하게, 쌓일듯 말듯하며 쌓이는 모습이 가깝지 않을까 생각이 든다. 모르던 개념, 특히나 추상적인 개념을 알게 된다면 사전적 정의만으로 이해하기는 쉽지 않다. 직접 경험해보거나 깊게 들여다보지 않는다면 금세 잊혀지고 만다. 어떤 주제에 대해 꾸준히 공부를 한다고 해도 지식이 규칙적으로 쌓이는 것이 아니라 미진하게 쌓이다가 한날한시에 미친듯이 쌓이기도 한다. 하지만 그 미친듯이 쌓이는 순간을 경험하게 되면 희열을 느낄 수 있다. 희열 이후에 한 발자국을 더 걸어가면 그 너머에는 더 많은 개념이 기다리고 있다. 마치 변수가 한 개 생기면 경우의 수가 제곱으로 증가하듯이.

한 달동안 알고리즘 공부를 하고 자료구조를 공부하며 느끼고 배운점이 참 많았다. 사고의 확장이라는 면에서 긍정적인 영향을 많이 받았다. 단순히 문제풀이에만 매몰되기보다는 구조에 대해 구상하고 아이디어를 내고 구현하는 과정이 나에겐 하나의 게임이자 재미요소였다. 덕분에 많은 부분을 배울 수 있었다.

마켓컬리 해커톤에 참가하였다. 예선을 통과하고 본선에 진출하였으나, 아쉽게도 결선까지 가지는 못했다. 꼬박 밤을 새고 잠을 쪼개가며 했지만 시간이 부족했다. 아쉬운 점도 많았지만 배우고 성장한 점도 많았던 즐거운 경험이었다.

'Think' 카테고리의 다른 글

2023년 4월 회고  (0) 2023.05.09
2022년 9월 회고  (1) 2022.10.04
2022년 상반기 회고  (0) 2022.08.01
2022.1Q 회고  (0) 2022.04.07
2022년 3월 회고  (0) 2022.03.31

Reference :  CS 공부 비서, 티스토리


Q&A

Q. 컴파일러와 인터프리터의 차이가 무엇인가요?

A. 나의 답변

* 컴파일러는 인풋언어(고급어)를 객체어(기계어)로 변환하고, 하드웨어에 종속적이다. 번역 진행 시 전체 코드를 검사한 뒤에 실행한다.
반면 인터프리터는 line by line으로 번역을 진행하고, 하드웨어에 종속되지 않는 특징이 있다. 


Best Answers

 

★ㅇ*님의 답변
컴파일러와 인터프린터는 사람이 작성한 코드(고급언어)를 컴퓨터가 이해할 수 있는 언어(기계어)로 변환하는 작업을 수행해주는 역할을 한다. 컴파일의 경우 고급언어를 한 번에 번역한다.

인터프린터의 경우 고급언어를 한 줄씩 번역을 진행하기 때문에 컴파일 보다 실행시간이 빠르다는 장점이 있다. 그러나 번역을 할 때 실행파일을 생성하지 않기 때문에 매번 실행할 때마다 같은 번역작업을 반복해서 실행해야 되는 단점이 있고, 이러한 문제 때문에 컴파일러를 사용하는 언어보다 실행속도가 느리다.
그럼에도 불구하고 인터프린터를 사용하는 이유는 모든 플랫폼에 종속되지 않는다는 장점을 갖기 때문에 호환문제에서 자유롭다.


★홍*님의 답변
<컴파일러(compiler)>
전체 파일을 스캔하여 한꺼번에 번역한다.
초기 스캔시간이 오래 걸리지만, 한번 실행 파일이 만들어지고 나면 빠르다.
기계어 번역과정에서 더 많은 메모리를 사용한다.
전체 코드를 스캔하는 과정에서 모든 오류를 한꺼번에 출력해주기 때문에 실행 전에 오류를 알 수 있다.
대표적인 언어로 C, C++, JAVA 등이 있다.

<인터프리터(interpreter)>
프로그램 실행시 한 번에 한 문장씩 번역한다.
한번에 한문장씩 번역후 실행 시키기 때문에 실행 시간이 느리다.
컴파일러와 같은 오브젝트 코드 생성과정이 없기 때문에 메모리 효율이 좋다.
프로그램을 실행시키고 나서 오류를 발견하면 바로 실행을 중지 시킨다. 실행 후에 오류를 알 수 있다.
대표적인 언어로 Python, Ruby, Javascript 등이 있다.




★최*님의 답변
컴파일러는 고급 언어로 작성된 프로그램 전체를 일괄적으로 기계어로 번역하는 도구이다. 컴파일 하는 데 시간이 소모되지만, 실행 시에는 필요한 정보들이 모두 미리 계산되어 있기 때문에 인터프리터 방식에 비해 빠르다는 장점이 있다. C, C++, 포트란, 파스칼 등의 언어가 컴파일러를 사용한다.

인터프리터는 실행문을 한 문장씩 번역하면서 실행하는 구조이다. 그에 따라서 바로 실행이 가능하지만, 전체 실행 시간은 컴파일러에 비해서 더 오래 걸린다. 추가적으로 메모리 사용도 컴파일러에 비해서 비효율적인 면이 있다. BASIC, PHP, 펄, 파이썬 등의 언어가 인터프리터를 사용한다.

이밖에도 자바같은 언어는 컴파일러와 인터프리터의 중간 형태의 언어를 사용한다고 볼 수 있다. 이를 혼합형 방식이라고 하는데, 고급 언어를 컴파일해 중간 언어로 번역하고 인터프리터에 의해 번역을 하면서 실행하는 방식을 의미한다. 자바의 경우 자바 가상 머신이 이해할 수 있는 자바 바이트코드를 생성하고, 자바 가상 머신이 이를 실행하는 식으로 구동된다.




★황*님의 답변
작성한 프로그램을 빌드 혹은 실행하는 방법으로는 컴파일러방식과 인터프리터 방식이 있다. 컴파일러와 인터프리터는 고급언어로 작성된 원시 프로그램을 목적 프로그램으로 번역하는 프로그램이며, 프로그램 번역 방식에 따라 구분된다.

"컴파일러"는 고급 언어(C, C++, JAVA)등으로 작성 된 소스 코드를 컴퓨터가 읽을 수 있는 저급 언어(기계어, 어셈블리어)로 번역해주는 프로그램이다. 컴파일러의 경우 크게 4가지 과정(전처리 - 컴파일 - 어셈블리 - 링킹)을 통해 실행 가능한 산출물로 만들어진다.

1. 전처리 
전처리기를 통해 전처리된 소스 코드로 변환하는 과정이다. 주석 제거, 헤더 파일 복사후 삽입, 매크로 치환 및 적용등을 진행합니다.

2. 컴파일
전처리된 소스 코드를 어셈블리어로 변환한다. 언어의 문법검사 정적(Data,BSS)인 영역들의 메모리 할당을 수행한다.

3. 어셈블리
어셈블리어 파일을 오브젝트 파일로 변환하는 과정이다. 오브젝트 파일은 기계어로 쓰여 있으며 보통의 포맷 종류는 PE(Window), ELF(Linux)가 존재한다.

4. 링킹 과정
컴파일러에 존재하는 링커를 통해 오브젝트 파일들을 묶어 실행 파일로 만드는 과정이다. 이 과정에서 오브젝트 파일들과 프로그램에서 사용하는 라이브러리 파일들을 링크하여 하나의 실행 파일을 만든다. 이러한 과정을 거쳐 우리가 작성한 고급언어들을 실행 가능한 파일로 만드는 것이 컴파일러가 수행하는 역할이다.


"인터프리터"는 고급언어로 작성된 프로그램을 한 줄 단위로 받아들여 번역한 뒤 번역과 동시에 프로그램을 한 줄 단위로 즉시 실행시켜 주는 프로그램이다. 줄 단위로 번역, 실행되기 때문에 시분할 시스템에 유용하며 한단계씩 테스트와 수정을 하며 진행시키는데에 적합하다.

1. 소스 코드를 직접 실행한다.
2. 첫번째 줄을 읽는다.
3. 기계어 명령어로 번역한후 CPU에 바로 돌린다.
4. 프로그램 한 줄을 실행한다.

둘의 차이점은
컴파일러 - 전체 단위로 번역함
인터프리터 - 한 줄 단위로 번역함

컴파일러 - 목적 프로그램을 생성함
인터프리터 - 생성하지 않음

컴파일러 - 실행속도의 경우 한번에 번역해서 실행하기 때문에 빠름
인터프리터 - 한 줄씩 읽어내기 때문에 느림

컴파일러 - 번역속도가 느림
인터프리터 - 번역속도가 빠름





★김*님의 답변
컴파일러는 프로그램 전체를 스캔하여 이를 모두 기계어로 번역한다. 
하지만 전체 실행 시간만 따지고 보면 인터프리터 보다 빠르다. 왜냐하면 컴파일러는 초기 스캔을 마치면 실행파일을 만들어 놓고 다음에 실행할때 이전에 만들어 놓았던 실행파일을 실행하기 때문이다.

인터프리터는 프로그램 실행시 한 번에 한 문장씩 번역한다. 그렇기 때문에 한번에 전체를 스캔하고 실행파일을 만들어서 실행하는 컴파일러보다 실행시간이 더 걸린다. 그럴 수 밖에 없다고 본다. 한 문장 읽고 번역하여 실행시키는 과정을 반복하는게 만들어 놓은 실행파일을 한번 실행시키는 것보다 빠르긴 힘들어 보인다. 하지만 인터프리터는 메모리 효율이 좋다.

 




★권*님의 답변
2가지의 차이를 설명하기 이전에 컴퓨터의 시작의 역사를 조금 되짚어보겠다. 흔히 알려진 컴퓨터 OS의 시작은 유닉스이다. 그리고 유닉스가 유료화가 되면서 오픈소스로 만들어진 가장 잘 알려진 리눅스가 된다.

이러한 리눅스에서는 콘솔 창에서 어떤 명령을 수행할지에 대한 명령어 처리 시스템인 셸이 존재한다. 간단하게는 디렉터리 위치 변경, 파일 목록 출력, 문자열 탐색과 같은 명령어들이 있다. 이러한 명령어 집합을 파일로 만들어서 해당 파일을 실행하면 명령어들을 순차적으로 셸에 실행시켜준다. 이를 셸 프로그래밍이라고도 하고, 이는 인터프린터이다.
프로그램 파일의 명령어를 단순히 순차적으로 실행시켜주는 것이다. 잘 알려진 프로그래밍 언어로는 자바스크립트,파이썬,파워쉘, 등이 있을 것이다.


이에 반에 컴파일러는 인터프리터의 문자열 수준의 명령어가 아닌, 기계어 수준의 명령어 집합으로 만드는 것이다. 여기서 기계어란 컴퓨터가 (CPU) 더하기 연산이나 빼기 연산, 레지스터 복사 같은 명령어들을 얘기한다. 컴파일러로 컴파일 할 경우 기계어이다 보니 인터프린터보다 속도가 훨씬 빠르다는 장점이있다. 이런 컴파일러 언어의 예로는 C언어, C++ 가 대표적이다.

참고로 C#이나 Java의 경우, 인터프린터와 컴파일러의 중간에 있다.
Java를 예로 들면, Java 개발사에는 JVM이라는 프로그램을 만들어서 배포한다. 이 JVM은 인터프린터와 같은 명령어 실행기이다. 그리고 Java를 이용하여 프로그램을 만드는 개발자의 경우 프로그래밍을 하고 코드를 실행 시 컵파일이 된다. 컴파일 시 기계어가 아닌 JVM에서 실행시켜줄 수 있는 바이트 코드가 되어 JVM에서 실행된다. 이는 한 코드로 모든 운영체제에서 실행시키려는 자바의 철학이다.
따라서 java 개발사에서는 JVM를 각 운영체제 별로 만들어야 한다. 그리고 프로그램 개발자의 경우 한 코드로 모든 운영체제에서 돌릴 수 있다. 이러한 Java C#은 굳이 따지자면 컴파일러 언어에 더 가깝다.





★박*님의 답변
1. 컴파일러
: 전체 프로그램을 스캔해 한번에 기계어로 번역한다, 코드 분석에 시간이 많이 걸리는 대신 컴파일 후 실행시간이 빠르다. 컴파일러는 기계어와 코드 사이의 중간 코드를 생성하기 때문에 더 많은 메모리가 필요하다.

2.인터프리터
: 한 번에 하나의 프로그램 명령문을 기계어로 번역한다. 소스 코드를 분석하는데 상대적으로 적은 시간이 걸리지만 코드가 실행되는 시간은 더 오래 걸린다. 중간에 기계어와 코드 사이를 연결하는 코드를 생성하지 않아 메모리를 적게 쓴다.

컴파일러는 C, C++ 등에서 쓰이고, 인터프리너틑 JS, Python등에서 대표적으로 쓰인다.





★(*님의 답변
컴파일러는 소스 코드 n줄을 기계 코드로 한 번에 변환한 후 실행 파일로 만들어 해당 실행 파일만 있으면 실행할 수 있게 하는 것이고 인터프리터는 소스 코드 한 줄 한 줄 실행되는 순간 순간에 기계 코드로 변환하여 바로 실행한다는 것이다.

한 번 컴파일 하여 생성된 실행 파일만 있으면 빨리 실행할 수 있다는 장점이 있지만 컴파일 할 때 시간이 걸린다는 단점이 있고 인터프리터는 컴파일을 하지 않기 때문에 바로 바로 코드의 결과를 확인할 수 있다는 장점이 있지만 한줄을 기계 코드로 변환 후 실행하고 다음 한 줄을 기계 코드로 변환 후 실행하기 때문에 컴파일 후 생성된 파일을 실행하는 것보다는 느리다는 단점이 있다.




★서*님의 답변
컴파일러와 인터프리터는 모두 초기 컴퓨터의 서로 다른 cpu의 서로 다른 어셈블리어를 더 나은 방식으로 통합하기 위해 만들어졌다. 즉 서로 같은 명령을 서로 다른 어셈블리어로 번역해 주기 위해 만들어진 것이다.


<컴파일러(compiler)> 

컴파일러는 프로그램 전체를 스캔하여 이를 모두 기계어로 번역한다. 전체를 스캔하기 때문에 대개 컴파일러는 초기 스캔 시간이 오래 걸린다. 하지만 전체 실행 시간만 따지고 보면 인터프리터 보다 빠르다. 왜냐하면 컴파일러는 초기 스캔을 마치면 실행파일을 만들어 놓고 다음에 실행할때 이전에 만들어 놓았던 실행파일을 실행하기 때문이다. 하지만 단점도 있다. 컴파일러는 고급언어로 작성된 소스를 기계어로 번역하고 이 과정에서 오브젝트 코드(Object Code)라는 파일을 만드는데 이 오브젝트 코드를 묶어서 하나의 실행 파일로 다시 만드는 링킹(Linking) 이라는 작업을 해야한다. 설명만 딱 봐도 뚝딱하고 번역을 하는것 같아 보이진 않는다. 이때문에 컴파일러는 통상적으로 인터프리터 보다 많은 메모리를 사용해야 한다. 또한 컴파일러는 오류 메시지를 생성할때 전체 코드를 검사한 후에 오류 메시지를 생성한다. 그래서 실행 전에 오류를 발견 할 수 있다. 대표적인 언어로 C,C++,JAVA 등이 있다.

<인터프리터(interpreter)>

컴파일러와는 반대로 인터프리터는 프로그램 실행시 한 번에 한 문장씩 번역한다. 그렇기 때문에 한번에 전체를 스캔하고 실행파일을 만들어서 실행하는 컴파일러보다 실행시간이 더 걸린다. 그럴 수 밖에 없다고 본다. 한 문장 읽고 번역하여 실행시키는 과정을 반복하는게 만들어 놓은 실행파일을 한번 실행시키는 것보다 빠르긴 힘들어 보인다. 하지만 인터프리터는 메모리 효율이 좋다. 왜냐하면 컴파일러처럼 목적코드를 만들지도 않고, 링킹 과정도 거치지 않기 때문이다. 이 때문에 인터프리터는 메모리 사용에 컴파일러 보다 더 효율적인 모습을 보인다. 인터프리터는 오류 메시지 생성과정이 컴파일러와 다르다. 인터프리터는 한번에 한문장씩 번역하기 때문에 프로그램을 실행시키고 한 문장씩 번역될때 오류를 만나게 되면 바로 프로그램을 중지한다. 그래서 프로그램을 실행해봐야지만 오류 발견이 가능하다. 대표적인 언어로 Python, Ruby, Javascript 등이 있다.





★?*님의 답변
<컴파일러>
- 프로그램 전체를 스캔하여 이를 모두 기계어로 번역
- 전체를 스캔하기 때문에 초기 스캔 시간이 오래 걸리지만 전체 실행 시간만 따지고 보면 인터프리터보다 빠름
- 프로그램 실행 전에 오류를 알 수 있음
- 대표적인 언어로 C, C++, JAVA 등이 있음

<인터프리터>
- 프로그램 실행 시 한 번에 한 문장씩 번역
- 한번에 전체를 스캔하고 실행 파일을 만들어서 실행하는 컴파일러보다 실행 시간이 더 걸림
- 프로그램 실행 후에 오류를 알 수 있음
- 대표적인 언어로 Python, Ruby, Javascript 등이 있음

많이 늦은 상반기 회고지만, 더 늦기 전에 작성해보려 한다.

 

Work

커리어를 데이터 사이언스 분야로 전환하고 난 후 첫 취업을 하였고, 하루하루 배움의 연속이었다. 부족한 역량을 채우기 위해 추가적인 공부가 필요해서 업무도 공부도 열심히 하였다. 동료 연구원들과 선임, 책임연구원분들의 이야기를 들으며 데이터를 다룰 때 고려해야 하는 부분이 내 생각보다 훨씬 많다는 것도 배웠다. 넘겨 짚지 않아야 하는 건 당연하고, 다양한 경우의 수를 생각하며 플랜을 짤 수 있는 방법을 습득하였다.

리서치를 하며 모델에 대한 지식을 넓혔다. 혼자 paper를 읽으며 공부를 했을 때는 '아 여기서는 이 구조에서 이러한 특징을 살려 이러한 부분을 develop했고, 그래서 이러한 점이 개선되었구나' 이러한 플로우로 이해를 했고, '그래서 이 구조가 이 task에서 backbone으로 많이 사용되는구나' 를 중점적으로 보다보니 구조에 대한 이해도도 전보다 개선되었다. 

OCR 업무를 담당하며 컴퓨터 비전과 NLP 양쪽의 task를 모두 다루었다. 겉으로 보기엔 쉽고 당연해 보였던 것들이 직접 하려니 어려움에 많이 부딪혔다. 하지만 이유를 찾아가는 과정과 develop시키는 과정 속에서 많이 성장하고, 또 데이터의 형태나 layer의 형태, 차원 등에 대해 더 깊게 알 수 있었다. PyTorch를 전보다 능숙하게 다룰 수 있게 되었으며 시간이 될 때 pytorch documentation open source 도 contribution 하고 싶다.

input data와 output data의 특징을 탐색하며 이를 서비스에 어떻게 잘 붙여 확장할지 고민하는 과정도 즐거웠다. 브레인 스토밍은 정말 재미있다.

 

Study

언어 스터디는 꾸준히 하고 있다. 2년째 진행중인 독일어 회화 스터디, 그리고 주1회 전화영어는 감을 잃지 않기 위해 하고 있다. 듀오링고도 시작한지 벌써 1111일이 넘어 곧 1200일을 향해 가고 있다. 하루 10분씩의 습관이 쌓여 지금의 독일어 실력을 만들었다니 감회가 새롭다.

운영체제, sql, ELK 스터디 등을 마쳤다. ElasticSearch, Logstash, Kibana 를 실무에선 다룰 기회가 적어 스터디에 참여했는데 확실히 큰 도움이 되었다. 운영체제는 운영체제의 바이블인 공룡책으로 1회 스터디한 후, 2회부터는 반효경 교수님의 k-mooc 강좌를 듣고 있는데 책을 읽었던 내용을 비디오로 다시 복습하니 확실히 좋았다. Linux 로 서버에 접속할 때 으레 다들 그렇게 하니까 했던 행동들, 혹은 코딩을 할 때 당연히 그래야 한다고 알고 있었던 개념들을 논리적으로 알게 되니 시야가 달라졌다. 이유를 알기 전과 후가 이렇게 다른건가.

SQL은 프로젝트 때 잠깐 쓴 이후로 실무에서 쓸 일이 많이 없어 자신감이 없었다. sqld 자격증을 따기 위해 공부했던 내용과 겹치지만, 목적이 달라 그런지 데이터베이스 개론과 함께 공부하니 생각보다 쉽게 배울 수 있었다. 이제는 sql을 전보다 좀 더 자신감있게 다룰 수 있을 것 같다.

머신러닝 스터디와 논문스터디, 추천시스템 스터디는 계속 진행중이다. 이 세 개의 스터디는 속도보다는 방향을 우선적으로 잡고 꾸준히 천천히 하고 있는데 그래서 그런지는 몰라도 얻어가는 게 많은 느낌이다. 한 논문을 2-3주 동안 잡고 있기도 했는데, 그동안 해온 공부방법이 너무 속도에만 치중하여 본질을 잊고 잘못해 온 방법이 아니었을까 하는 생각이 많이 들었다.

요즘 관심사는 파이프라인과 클라우드인데, 확실히 operation 쪽을 넘어가니 뿌옇던 시야가 확 트여 지평선이 보이지 않을 정도로 넓게 펼쳐진 것 같다. 무궁무진한 클라우드 세계에서 잘 살아남기를 목표로,적어도 실종되지만은 않기를 바라며 오늘도 aws 공부를 한다. ㅎㅎ

Health

다리를 다친 이후 2달 가까이 꼼짝 않고 안정을 취해야 했다. 이후 건강이 급속도로 나빠진 것을 느끼고 운동을 시작하였다. 요새는 유도를 하고 있는데, 처음에 낙법만 배워서 답답했지만 이제는 굳히기와 대련, 익히기도 하며 조금씩 재미를 느끼고 있다. 주말에는 자유수영을 하고 있는데 수영에는 유도와는 또 다른 매력이 있어 수영을 절대 관둘 순 없을 것 같다. 다가오는 8월에는 한강을 수영으로 건너는 대회를 나가기로 해서 한강에서 수영하는 것도 도전해봤다. 색다른 경험이었다.

공부만 하고 자극적인 음식을 먹다보니 몸이 묵직해진 게 느껴져 건강한 음식 위주로 먹기 시작하였다. 운동도 빼놓지 않으려고 한다. 올 초보다 근 10키로 가까이 살이 빠졌다. 가뿐해진 몸 덕분인지 이제는 운동을 하지 않으면 답답하다.

출근 전 아침에 유도를 하려다 의도치 않게 미라클 모닝을 시작했다. 생각보다 너무 잘 맞아서 아주 잘 지키고 있다. 보통 11-12시에 자고 5-6시쯤 일어나는데, 몸이 적응을 잘 해줘서 나 자신에게 너무 고맙다. 미라클 모닝을 시작하며 아침에 일기를 쓰는 습관도 생겼는데, 항상 쓰지는 않는다. 가끔이지만 텍스트로 내 마음을 기록하고 표출하는 것이 나 자신을 더 잘 알게 하는 느낌이다.

 

Plans

플랜이랄 것도 없지만 사실 하반기는 상반기보다 더 잘하고 싶은 욕심은 없다. 느슨하게 가되, 지금 내가 하고 있는 것들의 KPT를 꾸준히 되뇌이며 스스로 인지하는 것이 중요한 시기라고 생각한다. 욕심을 부린다고 바로 잘 할 수 있는 것도 아니고, 그럴 역량도 없다. 물론 Try하는 것은 좋지만 Keep 과 Problem이 우선되어야 하지 않을까? Problem을 고치려고 노력하고, Keep Going 하며 하루하루를 채워가는 것이 이미 하나의 Try라고 생각하고 있다.

20대 중반부터 느껴왔지만, 특히 요즘은 인간관계에 있어 어린 시절의 유치한 이기심과 질투가 얼마나 해로웠는지 다시금 느낀다. 누군가에겐 (어린 시절의 나에겐) 체리피킹을 잘 하는 것이 능력일 수 있겠지만 이제 나에겐 체리피킹보다는 나누는 것이 더 중요하다. 절대로 나 혼자 성장할 수 없다. 내가 성장할 수 있었던 이유는 내가 잘해서가 아니라 좋은 사람들을 만나 주변의 도움을 잘 얻고 운이 좋았기 때문이다. 성장하고 싶지만 주변 환경이 맘에 들지 않는다면, 주변 환경이 아니라 나 자신부터 바뀌어야 한다. 내 인생은 내 책임이라는 것을 명심하자!

하반기에는 리프레쉬할 겸 해외로 여행을 다녀오려 한다. 리프레쉬보단 배움이 더 많을 것 같은 여행이라 설렌다.

한 가지 아쉬운 점은 독서량이 많이 줄었다는 점이다. 적어도 2주에 1권은 읽었는데, 요새는 개발책 위주로 많이 봐서 그런지 1달에 1권을 읽을까말까 하는 듯 하다. 물론 정량적인 것이 중요하진 않지만 input이 적어지는 느낌은 지울 수 없다. 이런 시기도 있겠거니 하며 하반기엔 상반기보다 더 열심히 활자를 탐색해보려 한다.

이룬 것이 없어 보이지만 하루하루가 모이고 쌓이면 생각보다 큰 결과를 나타낸다는 것을 이번 회고를 적으며 또 느겼다. 이미 알고 있던 것이지만 몸소 체험할 때마다 색다른 기분이 든다. 5개월 뒤의 나는 과연 어떤 모습일지 기대되는 8월의 첫째 날이다. 

 

 

'Think' 카테고리의 다른 글

2022년 9월 회고  (1) 2022.10.04
2022년 8월 회고  (0) 2022.09.01
2022.1Q 회고  (0) 2022.04.07
2022년 3월 회고  (0) 2022.03.31
2022년 2월 회고  (0) 2022.02.28

[last updated Aug 05, 2022]

reference book : 구글 브레인 팀에게 배우는 딥러닝 with TensorFlow.js

 


서문

그동안 대부분의 딥러닝 프레임워크(Tensorflow 등)들은 파이썬으로 쓰여있어서, 파이썬이 익숙치 않은 사람들이 프레임워크를 다루는 것에 어려움이 있었다. 구글 브레인 팀은 자바스크립트와 Tensorflow 를 연결하여 자바스크립트 개발자들도 머신 러닝 모델을 구축하고 배포할 수 있도록 하며, 새로운 종류의 on-device 컴퓨팅을 가능하게 만들었다.

Tensorflow.js는 자바스크립트를 통해 신경망을 다루며 다양한 데이터 형태의 인풋이 가능하도록 하며 사전학습모델(pre-trained model)을 활용한 학습, fine-tuning, 더 나아가 추론(inference) 등이 가능케 하는 API를 제공한다. 

이 책은 Tensorflow.js 의 기능 및 기본적인 머신러닝/딥러닝 이론을 제공하며, <케라스 창시자에게 배우는 딥러닝> 책을 토대로 작성된 책이다. 딥러닝은 수학적 지식을 많이 알아야한다는 조건때문에 허들이 높게 느껴졌던 분들에게 좋은 책이 될 것 같다. 신경망 학습을 통해 활용하거나 확장할 수 있는 서비스가 굉장히 많기 때문에 많은 입문자 혹은 웹 개발자들이 읽기에 적합한 책이다.

책 자체가 프론트엔드 개발이나 Node.js 기반 백엔드 개발 경험을 가진 자바스크립트 실무 경험자를 대상으로 하여 쓰여졌기 때문에 자바스크립트를 경험해 본 사람이라면 이 책을 통해 누구나 쉽게 신경망을 다룰 수 있을 것이다.


환경설정

1) 책을 읽고 실습을 시작하기에 앞서, 도서의 부록 569페이지를 참고하여 실습 환경설정을 해야 한다. 책에 있는 예제를 실행하기 위해서는 node.js 와 npm을 설치해야 한다.

2) Node.js에서 Tensorflow.js GPU 가속 버전을 사용하기 위해서는 CUDA와 CuDNN을 설치해야 하며, CUDA를 지원하는 NVIDIA GPU가 장착되어야 한다. 1이 진행되었다는 가정하에 하기 진행사항을 서술한다.

<리눅스에서 tfs-node-gpu 설치하기>

  1. 리눅스에서 CUDA 툴킷을 설치한 후, sudo 명령으로 파일을 실행한다. 만약 이미 설치된 NVIDIA 드라이버의 버전이 오래됐거나 드라이브가 미설치되었다면 설치 과정에서 NVIDIA 드라이버를 설치 혹은 업데이트 해야한다. 이럴 경우에는 셸 전용 모드로 진입하여 설치하고 시스템을 리부팅해야 한다.
  2. 만약 위 단계가 마무리 되었다면 nvidia-smi 명령이 정상적으로 실행이 되고 GPU의 상태를 확인할 수 있다. 이후 환경 변수에 CUDA 라이브러리 디렉토리를 추가해주면 된다.
  3. 그 다음 CuDNN을 설치해야 하는데, CuDNN은 CUDA를 기반으로 구축한 심층 신경망 연산을 가속하기 위한 NVIDIA 라이브러리이다. 이는 실행 가능한 설치 파일이 아니라 동적 라이브러리 파일과 C/C++ 헤더를 포함하고 있는 압축파일이므로 적절한 폴더에 압축을 풀어 복사해야 한다. 아래 명령어를 통해 진행이 가능하다.
tar xzvf cudnn-10.0-linux-x64-v7.6.4.38.tgz
cp cuda/lib64/* /usr/local/cuda/lib64
cp cuda/include/* /usr/local/cuda/include

   4. 설치가 완료되었다면 node에서 tfjs-node-gpu를 import하여 확인할 수 있다.

npm i @tensorflow/tfjs @tensorflow/tfjs-node-gpu
node

   5. Node.js 명령줄 인터페이스에서 아래와 같이 입력하면 정상 설치가 완료되었을 때 GPU를 찾았다는 메시지와 tfjs-node-gpu를 사용할 준비가 되었다는 로그를 확인할 수 있다.

const tf = require('@tensorflow/tfjs');
require(@tensorflow/tfjs-node-gpu');

  6. 로그가 확인된다면 준비가 다 된것이고 package.json에 사용할 라이브러리 버전을 추가한다. 이후 main.js에서 필요한 라이브러리를 임포트하면 정말 끝이다.


<윈도우에서 tfs-node-gpu 설치하기>

  1. 설치 전 현재 윈도 버전이 CUDA 툴킷 시스템 요구 사항에 맞는지 확인해야 한다. 일부 버전과 32bit 는 지원하지 않는다.
  2. CUDA 툴킷 설치에 필요한 비주얼 스튜디오를 설치한다. (이미 설치되어있다면 패스해도 무방하다.)
  3. CUDA 툴킷을 설치한 후, CuDNN을 설치하는데 이 두 버전이 맞는 버전인지 확인한다.
  4. CuDNN은 zip파일이기 때문에 CUDA 툴킷이 설치된 디렉터리를 찾고 압축 해제한 CuDNN 파일을 동일 이름의 하위 폴더에 복사한다. 이 과정에서 관리자 권한이 필요할 수 있다.
  5. CUDA 툴킷과 CuDNN을 설치한 후 pc를 재부팅한다.
  6. window-build-tools npm 패키지를 설치하고, npm으로 tfjs와 tfjs-node-gpu 패키지를 설치한다.
npm install --add-python-to-path='true' --global windows-build-tools
npm install @tensorflow/tfjs @tensorflow/tfjs-node-gpu

 7. 설치를 확인하기 위해 node 명령줄에서 아래 코드를 실행하고 에러 없이 실행되는지, 로그가 잘 출력되는지 확인한다. 

const tf = require('@tensorflow/tfjs');
require('@tensorflow/tfjs-node-gpu');

본문

전부 적기엔 방대하여 이 책의 주요 포인트와 인상적인 부분만 추려 기록한다.

" 왜 자바스크립트와 머신 러닝을 합쳐야 하나요? "

  • 머신 러닝은 일반적으로 주로 백엔드에 사용되는 언어로 수행되어 웹 브라우저가 아닌 서버나 워크스테이션에서 실행된다. 심층 신경망 모델의 훈련을 위해서는 GPU와 멀티코어가 필요하며, 훈련 데이터는 백엔드에서 입력하는 것이 가장 편리하다. ex) native 파일
  • 머신 러닝이 훈련된 후 배포되지 않는다면 컴퓨터 자원 낭비에 불과하다. 많은 모바일 앱은 웹 뷰로도 전환되는데 그렇기 때문에 웹 브라우저가 딥러닝 모델을 배포하기 위한 합리적인 선택인 것이다.
  • 웹 서비스를 설계하고 확장할 때는 서버 비용이 가장 큰 모델이다. 딥러닝 모델을 위한 GPU를 따로 구축하며 트래픽이 늘어나고 클라우드 비용이 높아지는데, 모델을 클라이언트 측에 배포함으로써 문제를 해결할 수 있다. 모델을 클라이언트 측에 다운로딩하는 오버헤드는 브라우저 캐싱과 로컬 스토리지 기능으로 완화할 수 있다.

그 외에 추론 속도 증대, 데이터 프라이버시, WebGL 가속, 즉각적인 사용 등 자바스크립트를 활용한 다양한 이점이 있다.


후기

파이썬으로만 데이터를 다뤄보고, 자바스크립트는 웹 페이지를 구현하는 데에만 사용해온 나에게 자바스크립트를 활용한 딥러닝이라는 건 상상할 수 없는 조합이었다. 물론 이 책을 보기 전까지는 그랬다.... 두 언어 모두 스크립트 언어라는 공통점을 제외하고는 js로 사용하는 것에 대한 이점을 느낄 수 없었다. 하지만 막상 책을 보고 실습을 진행해보니 사용하는 언어만 바뀌었을 뿐 오히려 자바스크립트라는 언어의 특성을 잘 살려 쉽게 구성된 것 같아 재미있었고 굉장히 신선했다.

그도 그럴것이 목차의 구성을 보면 기본적인 머신러닝, 딥러닝 방법론적인 개념에 대한 설명부터 선형회귀,신경망에 대한 설명도 너무 친절하게 되어 있다. 실습을 통해 실제 딥러닝 workflow를 경험하며 예측모델을 만들어보고, 더 나아가 LSTM, GAN 등을 활용한 딥러닝과 강화학습까지 진행할 수 있다. 

일반적인 딥러닝 책이라면 이 단계까지 진행했겠지만, 모델 테스트 및 최적화, 배포까지 하는 과정까지 소개를 하며 구축부터 배포까지 end-to-end 과정을 친절하게 설명하고 있다. 또한 중간중간 연습문제도 제공하며, 독자가 딥러닝에 대한 지식을 탄탄하게 쌓을 수 있도록 잘 설계된 책이다.  

주변에 데이터를 다루거나 딥러닝을 배우고 싶어하는 웹 개발자분들이 많은데 꼭 추천하고 싶은 책이다. 구글 브레인팀 최고!

Reference :  CS 공부 비서, midas님의 velog


Q&A

Q.  트랜잭션의 각 격리 수준에 대해서 설명하고, 각 수준에서 일어날 수 있는 문제에 대해 설명해주세요

A. 나의 답변

* 트랜잭션은 데이터베이스의 논리적 수행 단위라고 할 수 있는데, 가지고 있는 여러가지 특징 중 격리성에 대한 특징이 있다.
격리성이란 트랜잭션들이 동시에 실행될 때 서로 영향을 미치지 않도록 격리하는 성질을 의미한다.

* 격리 수준은 4가지로 나눌 수 있는데, 하위 단계로 갈수록 격리 수준이 높아지지만 동시처리의 성능은 떨어진다.
1) Read Uncommitted
2) Read Committed
3) Repeatable Read
4) Serializable 


Best Answers

★김*님의 답변
격리성 관련 문제점을 해결하기 위해서 ANSI 표준에서 트랜잭션의 격리성과 동시 처리 성능 사이에 Trade-off 를 두고 4단계 격리수준을 나눴다.

0 - 한 트랜잭션의 변경된 내용을 commit이나 rollback과 상관 없이 다른 트랜잭션에서 읽을 수 있다
문제점 : 더티 리드(Dirty Read) 발생 가능성 존재한다, 데이터 정합성에 문제가 많다

1 - commit이 완료된 데이터만 조회 가능하다
문제점 : Non-repeatable Read 발생 가능성 존재한다, 잠금이 발생하므로 속도나 성능에 있어서 느릴 수 있다, 트랜잭션 간 고립성을 완전히 보장하지 못한다

2 - 트랜잭션이 시작되기 전에 커밋된 내용에 관해서만 조회할 수 있다
문제점 : 다른 사용자는 트랜잭션 영역에 해당되는 데이터에 대한 수정이 불가능하다, 잠금이 적용되는 범위가 넓어져 성능과 속도가 느려진다

3 - 한 트랜잭션을 다른 트랜잭션으로부터 완전히 분리한다
문제점 : 동시처리 능력이 다른 격리수준보다 떨어지며, 성능저하 발생한다


★김*님의 답변
트랜잭션 격리 수준이란 여러 트랜잭션 동시 처리시, 서로 얼마나 고립되었는지를 나타낸 것으로, 한 트랜잭션이 다른 트랜잭션에 변경한 데이터를 볼 수 있도록 허용할 것인지 결정하는 것이다. ACID와 같은 특성으로 트랜잭션이 독립적인 수행을 하도록 Locking을 통해 다른 트랜잭션 관여 여부를 막는데, 효율적인 Locking을 위해 격리수준을 나눈다.

격리 수준 (Isolatio) 종류
레벨 0. Read Uncommitted
- Select 문장 수행 중 해당 데이터에 Shared Lock이 걸리지 않음
- 일관성 유지 불가
- 문제점 : Dirty Read
- user1이 data A 를 B로 변경하는 도중 user2가 data를 B로 읽게되는 현상 (커밋 X)

레벨 1. Read Committed
- Select 문장 수행 중 해당 데이터에 Shared Lock이 걸림
- 트랜잭션 수행 중 다른 트랜잭션이 접근할 수 없어 대기
- 커밋된 트랜잭션만 조회 가능
- Non-Repeatable Read 발생
- A 트랜잭션에서 1번 데이터 조회 : 1
- B 트랜잭션에서 1번 데이터를 2로 바꾸고 커밋
- A 트랜잭션에서 1번 데이터 조회 : 2

레벨 2. Repeatable Read
- 트랜잭션 완료 전까지 SELECT 내의 모든 데이터에 Shared Lock
- 트랜잭션이 범위 내에 조회한 데이터 내용이 항상 동일함을 보장

레벨 3. Serializable
- 트랜잭션 완료 전까지 SELECT 내의 모든 데이터에 Shared Lock
- 완벽한 읽기 일관성 모드 제공



★권*님의 답변
트랜잭션의 각 격리 수준에 대해 얘기하기 이전에 몇 가지 개념을 정리하려 한다. 트랜잭션이란 데이터의 수정/읽기하는 명령을 의미한다.
커밋은 데이터의 영구적인 저장을 의미한다. 
DB의 각 격리수준이 나오는 이유는 DB가 값을 수정하고, 다른 트렌젝션이 값을 읽고 롤백할 경우 데이터의 일관성을 잃는 문제가 있다. 이런 문제들을 갖고 어떤 방법론을 쓸 건지 나눈 것이다.
예를들면 데이터를 수정할 때 데이터를 수정 전의 값 기준으로 한다. 데이터를 수정 후의 기준으로 한다. 데이터를 커밋하기 이전의 기준으로 한다. 이후로 한다. 와 같이 나눠진다.

자세히 살펴보면 다음과 같은 방법이 있다.

READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
SERIALIZABLE

READ UNCOMMITTED
커밋하지 않아도 수정한 결과를 계산 값으로 쓴다. 이때 위에 말한 것처럼 롤백을 사용할 경우 데이터의 일관성을 잃는다.


READ COMMITTED
커밋한 결과만으로 값을 쓴다. 그렇다면 데이터의 일관성이 유지되지만 또 다른 문제점이 존재한다. DB가 멀티스레드로 트렌젝션을 동시에 처리할 때이다. 이럴 경우 동기화가 되지않아서 어떤 것은 수정되기 이전 값을 쓰고 이후에 커밋되어 수정된 값을 쓰고 같은 문제가 발생한다.


REPEATABLE READ
트랜잭션이 시작되면 각 트랜잭션이 발생한 시점의 데이터들을 저장한다. 그리고 연산 시 발생한 시점의 데이터만 사용한다. 발생하는 문제로데이터 업데이트할 경우 나중의 트랜잭션만 수행되고, 처음에 시작된 트랜잭션은 무시된다. 또 각 시점별 데이터를 저장하므로 용량 문제가 발생할 수 있다.


SERIALIZABLE
읽기와 수정 모두 동기화를 시켜서 엄격하게 관리한다. 이렇게 할 경우 위의 모든 문제를 해결할 수 있지만 한 작업이 길게 이어지는데 데이터를 오랫동안 사용할 경우 계산낭비가 발생한다.


★.*님의 답변
# 트랜잭션 격리수준(isolation level)이란
- 특정 트랜잭션이 다른 트랜잭션에 변경한 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것

## 격리수준
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE

### READ UNCOMMITTED
- 어떤 트랜잭션의 변경내용이 COMMIT이나 ROLLBACK과 상관없이 다른 트랜잭션에서 보여진다.
- 데이터 정합성에 문제가 많아, 격리수준으로 인정하지 않음

### READ COMMITTED
- 어떤 트랜잭션의 변경 내용이 COMMIT 되어야만 다른 트랜잭션에서 조회할 수 있다.

### REPETABLE READ
- 트랜잭션이 시작되기 전에 커밋된 내용에 대해서만 조회할 수 있는 격리수준

### REPEATABLE READ
- UPDATE 부정합: 변경을 수행할 로우에 대해 잠금이 필요하다.
- Phantom READ: 한 트랜잭션 내에서 같은 쿼리를 두 번 실행했는데, 첫 번째 쿼리에서 없던 유령(Phantom) 레코드가 두 번째 쿼리에서 나타나는 현상을 말한다.

### SERIALIZABLE
- 가장 단순하고 가장 엄격한 격리수준이다.

 



★황*님의 답변
트랜잭션은 데이터의 무모순성을 보장하기 위한 기능입니다. 트랜잭션은 논리적인 작업 셋 자체가 100% 적용되거나(COMMIT) 또는 아무것도 적용되지 않아야 함(ROLLBACK)을 보장해주는 것입니다.
트랜잭션의 격리 수준이란 동시에 여러 트랜잭션이 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것입니다.

격리 수준은 다음과 같이 4가지로 정의할 수 있습니다.
READ UNCOMMITTED(커밋되지 않은 읽기)
READ COMMITTED(커밋된 읽기)
REPEATABLE READ(반복 가능한 읽기)
SERIALIZABLE(직렬화 가능)

1. READ UNCOMMITED
각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관 없이 다른 트랜잭션에서 값을 읽을 수 있습니다.

따라서 트랜잭션 작업이 완료되지 않았는데도 다른 트랜잭션에서 볼 수 있는 DIRTY READ현상이 발생합니다.
ex: A트랜잭션에서 값을 바꿨으나 아직 커밋되지 않은 상태에서 B트랜잭션이 해당 바뀐 값을 확인할 수 있는 문제가 발생합니다.

2. READ COMMITTED
실제 테이블 값이 아닌 Undo(잘못되었을 경우 데이터가 변경되기 전의 데이터 보관하는 곳) 영역에 백업된 레코드에서 값을 가져옵니다.

하나의 트랜잭션에서 같은 쿼리를 두 번 실행하였을 때 두 실행 조회 값이 달라질 수 있습니다.

정합성 문제가 해결된 것 같지만 부정합 문제가 발생할 수 있습니다.
ex:)A트랜잭션이 작동 도중 B트랜잭션이 해당 값을 조회 한 결과 "P"라는 결과가 나옴. 그 후 A트랜잭션이 커밋이 되면 B트랜잭션에서 조회한 결과 커밋으로 바뀐 결과가 나타남

하나의 트랜잭션 내에서 똑같은 SELECT를 수행했을 경우 항상 같은 결과를 반환해야 하는 정합성 문제에 어긋납니다.

3. REPETABLE READ
트랜잭션이 시작되기 전 커밋된 내용에 대해서만 조회할 수 있는 격리수준입니다.(트랜잭션마다 트랜잭션 ID를 부여하여 트랜잭션 ID보다 작은 트랜잭션 번호에서 변경된 것만 읽습니다.)

부정합이 발생하지 않습니다.

그러나, PHANTOM READ(한 트랜잭션 안에서 일정범위의 레코드를 두번 이상 읽을 때, 첫 번째 쿼리에서 없던 유령 레코드가 두번째 쿼리에서 나타나는 현상)은 여전히 발생합니다.

고립화 수준을 높여 LOCK을 통해 다른 트랜잭션 시점에 다른 데이터가 추가되는 것을 막을 수 있습니다. 그러나 동시성이 저하됩니다.
(오라클은 Lock을 전혀 사용하지 않은 상태서 서로 다른 쿼리를 SCN 확인 과정을 통해 하나의 시점에 존재했던 대상으로만 집계를 수행하는 방법을 사용합니다. 동시성 저하를 하지 않으면서 일관성 유지)


4. SERIALIZABLE
새로운 트랜잭션이 읽은 데이터를 다른 트랜잭션이 갱신하거나 삭제하지 못하게 하고 중간에 새로운 레코드를 삽입 하는것을 막아줍니다.

이 Level에서는 Insert까지 막아줍니다. 다른 트랜잭션에서 이 레코드 변경을 하지 못하게 되기 때문에 동시처리 능력이 떨어지고, 성능 저하, 속도 저하 등이 발생하게 됩니다.



★정*님의 답변
트랜잭션이란, DB에 이루어지는 작업을 의미합니다. 몇 개의 작업이 한 단위를 이룰 수 있고, 이 작업들의 격리 정도를 트랜잭션의 각 격리 수준이라고 합니다.

트랜잭션의 격리 수준은 아래와 같이 4개의 단계가 있습니다.
1. Read Uncommitted
2. Read Commmitted
3. Repeatable Read
4. Serializable

1. Read Uncommitted
커밋되지 않은 트랜잭션까지 읽을 수 있는 격리 수준입니다. 사실상 격리의 개념이 존재하지 않는다고 볼 수 있습니다.


2. Read Committed
커밋된 트랜잭션을 읽을 수 있습니다. 일부 DB에서는 기본적으로 read committed가 기본 격리 단계로 사용됩니다. 데이터를 수정할 때는 수정이 완료될 때까지 lock이 적용되며, 데이터를 읽을 때는 lock이 해제됩니다. 따라서 데이터를 읽는 도중에 데이터가 변경될 수 있는 위험성이 존재합니다.


3. Repeatable Read
데이터가 수정될 때, 조회될 때 모두 lock을 겁니다. 일부 RDBMS의 기본 격리 수준으로 사용되고 있습니다. Phantom read라는 문제점이 발생할 수 있는데, 반복 조회 시 결과 집합이 달라지는 현상을 phantom read라고 합니다.


4. Serializable
가장 엄격한 단계의 격리 수준으로, 완벽한 격리 수준을 나타냅니다. 데이터를 읽거나 쓸 때, 완료될 때까지 lock을 걸게 됩니다. 하지만 이로 인하여 동시성 처리 성능이 떨어지는 문제점이 존재합니다.


★겨*님의 답변
트랜잭션의 격리 수준은 네개로 나눌 수 있다.
1. READ UNCOMMITTED
2. READ COMMITED
3. REPEATABLE READ
4. SERIALIZABLE


아래로 내려갈수록 트랜잭션 간의 고립 정도가 높아지며 성능이 떨어진다. READ UNCOMMITTED 격리수준에서는 어떤 트랜잭션의 변경내용이 Commit 이나 Rollback 과 상관없이 다른 트랜잭션에서 보여진다. 여기선 한 데이터의 값을 변경 후 커밋을 하지 않았는데 다른 트랜잭션에서 해당 데이터를 조회했을 때 변경된 값이 조회되는 더티리드 현상이 발생할 수있다.

READ COMMITTED는 어떤 트랜잭션의 변경 내용이 COMMIT 되어야만 다른 트랜잭션에서 조회할 수 있는데 이는 현재 오라클 DBMS에서 기본으로사용하고 있다.
해당 격리 수준에서는 하나의 트랜잭션 내에서 똑같은 Select 명령을 수행했을 경우 항상 같은 결과를 반환해야 한다는 Repeatable Read 정합성에 문제가 나타날 수 있다. 이를 Non-Repeatable Read 부정합 문제라고 한다.

REPEATABLE READ는 트랜잭션이 시작되기 전에 커밋된 내용에 대해서만 조회할 수 있는 격리 수준이다. MySQL DBMS에서 기본으로 사용하고 있는데, 이는 자신의 트랜잭션 번호보다 낮은 트랜잭션 번호에서 변경된(커밋된) 데이터만 보게 된다. 해당 격리 수준에서는 Update 부정합과 Phantom Read 라는 문제가 발생할 수 있다.

SERIALIZABLE은 가장 단순하고 엄격한 겨리수준이다. 해당 격리 수준에서는 읽기 작업에도 공유 잠금을 설정하게 되고, 다른 트랜잭션에서 해당 레코드를 변경할 수 없다. 이러한 특성 때문에 동시처리 능력이 다른 격리수준보다 떨어지고 성능저하가 발생하게된다.


★서*님의 답변
트랜잭션의 격리 수준이란 동시에 여러 트랜잭션이 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것으로 네가지로 정의됩니다.


1. READ UNCOMMITTED(커밋되지 않는 읽기)
2. READ COMMITED(커밋된 읽기)
3. REPEATABLE READ (반복 가능한 읽기)
4. SERIALIZABLE(직렬화 가능)


순서대로 1의 수준이 가장 낮고, 4인 직렬화 가능 단계의 수준이 가장 높습니다. 

READ UNCOMMITTED 격리 수준에서는 위 그림처럼 각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관 없이 다른 트랜잭션에서 보여지게 됩니다. 하지만 이러한 수준은 트랜잭션에서 처리한 작업이 완료되지 않았음에도 불구하고 다른 트랜잭션에서 볼 수 있게 되는 현상을 야기하고, 이를 더티 리드(Dirty Read) 라고 합니다.

READ COMMITTED 격리 수준은 오라클 DBMS에서 기본적으로 사용되고 있으며 온라인 서비스에서 가장 많이 선택되는 격리 수준입니다. 이 레벨에서는 위 READ UNCOMMITTED 수준에서 발생할 수 있는 더티 리드(Dirty Read)와 같은 현상은 발생하지 않습니다. 어떠한 트랜잭션에서 데이터를 변경하더라도 COMMIT이 완료된 데이터만 다른 트랜잭션에서 조회할 수 있기 때문입니다. 하만 READ COMMITTED 격리 수준에서도 "NON-REPEATABLE READ"라는 부정합 문제가 존재합니다. 즉, 하나의 트랜잭션내에서 동일한 SELECT 쿼리를 실행했을 때 항상 같은 결과를 보장해야 한다는 "REPEATABLE READ" 정합성에 어긋나게 됩니다.

따라서 세번 째 수준인 REPEATABLE READ는 MySQL의 InnoDB 스토리지 엔진에서 기본적으로 사용되는 격리 수준입니다. 이 격리 수준에서는 READ COMMITTED 격리 수준에서 발생하는 "NON-REPEATABLE READ" 부정합이 발생하지 않습니다. 하지만 이러한 격리수준에서도 다른 트랜잭션에서 수행한 변경 작업에 의해 레코드가 보였다가 안보였다가 하는 현상인 PHANTOM READ(PHANTOM ROW)이 발생할 수 있습니다. 

이때문에 네번째 격리수준인 SERIALIZABLE로 설정되면 읽기 작업도 공유 잠금(읽기 잠금)을 획득해야 하며, 동시에 다른 트랜잭션은 그러한 레코드를 변경할 수 없습니다. 즉, 한 트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 절대 접근할 수 없습니다. 이는 팬텀리드 현상을 해결합니다.



★김*님의 답변
격리 수준은 READ UNCOMMITTED(커밋되지 않은 읽기), READ COMMITTED(커밋된 읽기), REPEATABLE READ(반복 가능한 읽기), SERIALIZABLE(직렬화 가능) 으로 정의할 수 있습니다. 순서대로 READ UNCOMMITTED의 격리 수준이 가장 낮고 SERIALIZABLE의 격리 수준이 가장 높습니다.

READ UNCOMMITTED 격리 수준에서는 각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관 없이 다른 트랜잭션에서 보여지게 됩니다. 이를 Dirty Read라고 합니다. READ COMMITTED 격리 수준에서는 어떤 트랜잭션에서 변경한 내용이 커밋되기 전까지는 다른 트랜잭션에서 변경 내역을 조회할 수 없습니다.


REPEATABLE READ는 UNDO 영역에 백업된 이전 데이터를 통해 동일한 트랜잭션 내에서는 동일한 결과를 보여줄 수 있도록 보장합니다. 이에 어긋나는 현상을 NON-REPEATABLE READ라고 합니다. 트랜잭션의 격리 수준이 SERIALIZABLE로 설정되면 한 트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 절대 접근할 수 없습니다.

PHANTOM READ는 한 트랜잭션내에서 동일한 쿼리를 두 번 수행했는데, 첫 번째 쿼리에서 존재하지 않던 유령(Phantom) 레코드가 두 번째 쿼리에서 나타나는 현상입니다. 이는 READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ에서 나타날 수 있습니다.


★용*님의 답변
트랜잭션을 T라고 하고 T1의 단위중 갱신구문이 있을때,


READ UNCOMMITTED는
변경된 레코드를 커밋과 롤백 여부에 상관없이 T2에서 조회할 수 있습니다.
이는 해당 격리수준이 언두로그를 활용하지 않고, 디스크에 바로 반영하기 때문입니다.

READ COMMITTED는
변경된 레코드를 커밋되기 전까지 T2에서 조회할 수 없습니다.
이는 해당 격리수준이 언두로그를 활용해 갱신이전 레코드를 유지하기 때문입니다.

REPEATABLE READ는
트랜잭션마다 ID를 부여하여 현 ID보다 작은 ID에서 갱신한 레코드의 갱신 전 레코드를 조회할 수 있게 합니다.

SERIALIZABLE은
동시에 레코드를 조회함은 가능하지만, 갱신은 불가능하며
T1이 조회하면서 T2가 갱신하는 상황도 불가합니다.

다음은, 문제를 나열하고 어떤 수준에 일어나는지 기술하겠습니다.
DIRTY READ는
T2가 T1의 롤백 이전에 레코드를 조회하는 경우에
재개된 T1의 트랜잭션이 커밋되어 T2의 조회가 온전한 조회일수도
커밋되지 않아 온전한 조회가 아닐 수도 있는 현상입니다.
READ UNCOMMITTED에만 발생합니다.

NON-REPETABLE READ는
T2가 여러번 조회하는 사이 T1이 갱신이후 커밋됬다면 T2의 마지막 조회가 일관되지 않은 현상입니다.
T1의 커밋이전까지는 T2가 언두로그를 바라보지만,
T1의 커밋이후 T2가 디스크를 바라보게 되기때문입니다.
READ UNCOMMITTED와 READ COMMITTED에서 발생합니다.
REPEATABLE READ가 극복할 수 있었던 이유는
현 ID보다 작은 ID에서 갱신한 레코드의 갱신전 레코드는 언두로그에 남아있기 때문입니다.

PHANTOM READ는
T2가 여러번 조회하는 사이 T1이 갱신을 했다면
레코드가 변하지는 않지만 추가되거나 삭제될 수 있는 현상입니다.
SERIALIZABLE을 제외한 모든 격리수준에서 발생합니다.
단, InnoDB엔진의 default 수준인 REPEATABLE READ에는 발생하지 않는데,
Gap lock을 사용해 레코드의 일정 구간 자체에 락이 걸려 T1의 갱신 행위가 이뤄지지 않기 때문입니다.

카카오톡 플러스 친구에 좋은 채널이 있어 추가하였다. 하루에 한 개씩 CS 공부를 할 수 있도록 질문을 보내주고 , 답변자에 한하여 그 날이 마무리될때쯤 베스트 답변을 취합하여 다시 알려주는 좋은 채널이라 덕분에 나도 틈날때마다 개념을 정리하려 한다.

Reference : CS 공부 비서, 동기와 비동기의 개념, 동기와 비동기의 개념과 차이


Q&A

Q.  동기(Synchronous)와 비동기(Asynchronous), 블로킹(Blocking)과 논-블로킹(Non-blocking)에 대해 설명해주세요

A. 나의 답변

* 동기는 요청을 보내는 동시에 결과값을 받을 수 있도록 동시에 일어나는 것에 초점을 맞춘 방식이다. 비동기는 반대로 요청과 결과가 동시에 일어나지 않는다.

* 블로킹은 원래는 스포츠(농구)용어인데 수비수가 공격수로부터 방어하는 것을 의미한다. 컴퓨터용어로 사용하게 되며 비슷한 듯 다른 의미로 변경되었다. 블로킹은 호출함수가 호출당한 함수에게 제어에 대한 권한을 넘기는 것이다. 호출당한 함수의 작업이 끝나야 돌려받을 수 있기 때문에 호출함수는 그동안은 아무것도 할 수 없다. 논블로킹은 호출함수가 호출당한 함수를 호출은 하지만, 제어 권한을 넘겼다가 바로 돌려받기 때문에 호출함수는 다른 작업을 할 수 있다.

 

 


Best Answers


★ㅇ*님의 답변
동기식 - submit
: 리로드 방식. 로딩을 계속 하는 것.
동기는 요청과 결과가 동시에 일어난다는 약속인데, 요청을 하면 시간이 얼마나 걸리던지 요청한 자리에서 결과가 주어져야 합니다. = 그 동안 다른 처리를 할 수 없음.

비동기 - ajax
: 로딩을 하지 않는 상태로 데이터만 이동
화면은 고정적으로 있고 데이터만 이동하며, 호출한 화면으로 다시 돌아감.
비동기는 동시에 일어나지 않는다는 의미로 요청한 결과가 반환되지 않은 상태에서도 다른 작업을 처리할 수 있습니다.

비동기식은 동기식보다 설계가 더 복잡하지만 자원을 효율적으로 사용할 수 있다는 장점을 가지고 있습니다.

——

블로킹과 논블로킹의 차이는 처리되어야 하는 작업이 전체적인 작업의 흐름을 막느냐 안막느냐의 관점의 차이로 즉, 제어권이 누구에게 있느냐로 판단합니다.

블로킹은 호출한 함수에게 제어권을 넘겨주어 해당 함수의 작업이 끝나 다시 제어권을 돌려주기 전까지 실행을 멈춥니다.

논블로킹은 함수를 호출해도 제어권은 그대로 유지한 상태로 계속 실행할 수 있습니다.


★한*님의 답변
동기 (Synchronous)   

- 요청과 결과가 동시에 일어남
- 요청을 했을 경우 시간이 얼마나 걸리던지에 상관없이 요청한 자리에서 바로 결과값을 받아야 함
- 설계가 매우 간단하고 직관적임
- 결과가 주어질 때까지 아무것도 못하고 대기하면서 결과를 기다려야 함

비동기(Asynchronous) 
- 요청과 결과가 동시에 일어나지 않음
- 요청했을 경우에 지금 바로 혹은 당장 응답받지 않아도 됨 
- 동기에 비해 설계가 복잡함
- 결과가 주어지는데 시간이 걸리더라도 기다리는 시간동안 다른작업을 진행할 수 있으므로 자원을 효율적으로 사용

제어권   
- 함수를 실행시킬 수 있는 권리 

결과값 
- 함수의 리턴 값

블로킹(blocking)
- 요청자(부모함수) 는 요청한 작업이 끝날 때까지 다른 작업을 하지 않고 기다림
- 다른 함수를 호출할 때, 제어권도 함께 넘겨주며 그 작업이 끝난 후에 돌려받기 때문 (제어권이 없는상태)
- 요청받은 함수는 모든 실행을 마치고 최종 결과값을 돌려줌

논블로킹(non-blocking) 
- 요청자(부모함수) 는 요청한 작업이 수행되는 동안 다른작업을 진행할 수 있음
- 다른함수를 호출할 때, 제어권을 넘겨주지만 바로 돌려 받음 
- 제어권을 바로 돌려받기 때문에 다른 작업을 진행할 수 있음


★민*님의 답변
블로킹 Blocking
A 함수가 B 함수를 호출 할 때, B 함수가 자신의 작업이 종료되기 전까지 A 함수에게 제어권을 돌려주지 않는 것

논블로킹 Non-blocking
A 함수가 B 함수를 호출 할 때, B 함수가 제어권을 바로 A 함수에게 넘겨주면서, A 함수가 다른 일을 할 수 있도록 하는 것.

동기 Synchronous
A 함수가 B 함수를 호출 할 때, B 함수의 결과를 A 함수가 처리하는 것.

비동기 Asynchronous
A 함수가 B 함수를 호출 할 때, B 함수의 결과를 B 함수가 처리하는 것. (callback)


★박*님의 답변
동기: 요청-응답이 하나로 묶여서 기다리는 방식, 가령 A라는 작업과 A에 대한 A’ 라는 응답이 있고, B,C,D가 같은 형태로 있다면 갹각의 응답 결과 뒤에 다음 작업들을 요청한다.
비동기: 요청을 응답을 기다리지 않고 실행한다. 요청들은 응답이 오면 별도의 방식으로 순서와 상관없이 처리되어 반환된다. 응답 결과를 확인하는 방식은 비동기를 처리하는 부분을 구현하는 것에 따라 다르다.

블로킹: 특정 작업 동안 프로세스 자원을 점유하며 다른 작업을 하지 못하게 막는다. 가령 파일입출력 같은 작업동안 별도의 커맨드를 수행하지 못하게 한다거나 하는 부분이 이에 해당한다.
논블로킹: 특정 요청이 프로세스 자원을 다른 커맨드에서 활용하는 것을 막지 않는다. 프로세스/스레드 어느쪽 자원이든 커맨드가 실행되고 해당 작업이 종료되지 않아도 다른 작업들을 실행할 수 있게 한다.


★조*님의 답변
[동기 비동기]
- 작업 수행 순서가 직렬로 이어지냐(동기), 병렬로 동시에 진행되냐(비동기)에 대한 문제
동기 : 작업을 순차적으로 진행, 한 작업이 끝날 때까지 다음 작업은 대기하고 있다가 실행된다. 혹은 기존 작업에서 계속 다른 작업의 실행이 끝났는지를 확인하며 체크해야함
비동기 : 스레드 다수개를 이용해 작업을 동시에 병렬로 작업 후, 한 작업이 끝나면 callback 을 받아서 해당 작업을 요청했던 스레드를 호출하는 식으로 동작함.

[블로킹/논블로킹]
- 작업 중간중간에 쉴 때 계속 본인이 점유하고 있을지(블로킹), 혹은 다른 작업에게 주도권을 넘겨줄지(논블로킹)에 대한 문제
블로킹 : 본인의 작업이 끝날 때까지 다른 작업들은 모두 대기함(말 그대로 block, 막고 서있는 느낌). 가령 스레드 A가 일을 하다가 B를 호출했다면, B의 작업이 끝날 때까지 계속 대기하거나 B의 작업 종료를 본인이 함
논블로킹 : 본인의 작업이 끝나지 않았더라도, 다른 작업을 수행해야하거나 작업이 종료되어 콜백이 들어오면 해당 작업이 진행됨. 가령 스레드 A가 일을 하다가 B를 호출했다면, A는 일을 하다가 유휴 상태가 되면 B에게 주도권을 넘겨줄 것임.

★노*님의 답변
### 블로킹(Blocking)

A함수가 B함수를 호출하면 A함수의 제어권을 B함수에 넘긴다.
B에게 제어권이 넘어가면 A는 함수 실행을 멈춘다.
B의 실행이 끝나면 제어권을 A에게 돌려준다.

### 논-블로킹(Non-blocking)

A함수가 B함수를 호출해도 제어권을 A가 가지고있다.
A함수는 B함수를 호출한 이후에도 A함수의 코드를 계속 실행한다.

### 동기(Synchronous)

요청과 응답이 동시에 일어남.
요청이 들어오면 결과가 주어지기까지 다른 요청을 받을 수 없음.

### 비동기(Asynchronous)

요청과 응답이 동시에 일어나지 않음.


★이*님의 답변
동기는 어떤 함수를 호출했을 때 호출된 함수가 완료상태를 전달하기 전까지는 호출한 함수는 다른 작업을 수행할수 없다. 즉, 2개의 함수가 시간을 맞춰 수행하는것.

비동기는 호출된 함수가 콜백함수를 반환하여 자신의 일이 완료가 되지 않아도 호출한 함수가 다른일을 수행할 수 있으며 호출된 함수가 결과를 반환하면 호출한 함수는 해당 결과값을 가지고 관련된 작업을 수행한다. 즉, 2개의 함수가 시간에 맞춰 수행하지 않고 서로의 작업을 수행하는것이다.

블로킹은 호출된 함수가 완료상태가 될때까지 제어권을 호출한 함수에게 넘겨주지 않는것이다.

논블로킹은 호출된 함수가 완료상태가 되지 않아도 제어권을 호출한 함수에게 넘겨주어 다른 작업을 할 수 있게 하는것이다.

동기,비동기와 블로킹,논블로킹의 차이점은 전자는 호출되는 함수의 완료여부를 누가 신경쓰는지에 초점을 맞추고 후자는 호출된 함수가 리턴을 바로하는지 아닌지에 초점을 맞추고 있다.


★정*님의 답변
1. 동기/비동기 -> 응답을 받는 순서
2. 블로킹/논블로킹 -> 응답을 받는 타이밍

1.1 동기
한 번에 하나씩 작업하는 것. 작업 순서가 보장된다.
CPU가 점유되지만 실행되고있지않은 블로킹(waiting time)이 생길 수 있다.

1.2 비동기
여러 작업을 동시에! 작업순서보장x
목적: 동기 작업중 cpu속도차로 생기는 블로킹영역의 효율적 사용
:o:독립적 작업
:x:상호의존적작업, 대규모연산 요구되는 작업


2.1 블로킹
작업 완료 후 응답결과를 받는다.
작업완료 전까지 cpu는 점유되지만 실행되지않는다.
해당 쓰레드는 Waiting Queue에 들어감.
비동기모델이라면, 블로킹영역에 수행할 다른 작업을 명시적으로 지정해줘야함.

2.2 논블로킹
응답결과를 기다리지않고 cpu가 다음작업을 계속한다.


:question:더 공부할 점)
- I/O 작업이란?
- kernel이란?
- user space란?
- 쓰레드란?? 멀티쓰레드?
- 웨이팅 큐??


★민*님의 답변

### 동기와 비동기
동기 : 메인업무가 서브업무 작업 완료 후의 결과값을 기다린다.
비동기 : 메인업무는 서브업무의 작업 완료를 신경쓰지 않는다.

### 블로킹과 논블로킹
블로킹은 서브업무에 제어권을 넘기기 때문에 메인업무는 잠시 실행을 멈추고 서브업무 종료 후 실행된다.
논블로킹은 메인업무가 여전히 제어권을 가지고 있기 때문에 서브업무 실행 후에도 메인업무가 계속 실행된다.


### 조합
동기 & 블로킹 : 메인업무가 서브업무 결과값이 필요해서 서브업무 종료 시까지 실행을 멈춘다.
동기 & 논블로킹 : 메인업무가 서브업무의 결과값을 지속적으로 확인하며 실행을 계속한다.
비동기 & 블로킹 : 메인업무가 서브업무의 결과와 상관없는데도 서브업무 종료 시까지 실행을 멈춘다.(거의 없음)
비동기 & 논블로킹 : 메인업무가 서브업무 응답을 기다리지 않고 실행을 계속한다. 서브업무는 업무 종료시 메인업무로 콜백된다.

★염*님의 답변
- 동기 작업이란, 한번에 하나씩 수행되는 것을 의미합니다.
즉, 해당 작업이 끝나기 전까지 현재 진행중인 작업 외의 다른 작업을 수행할 수 없습니다.
ex) HTTP 요청을 하면 무조건 응답을 받음. 동기적이라고 할 수 있다.

- 비동기 작업이란, 한 번에 하나 이상이 수행될 수 있음을 의미합니다
즉, 현재 작업을 진행중이더라도 다른 작업을 수행할 수 있습니다. 또한 작업의 결과를 바로 원하지 않습니다.
ex) 이메일을 보내는 작업은 상대방이 바로 답장하기를 원해 보내는 작업이 아님

- 블로킹은 자신이 Waiting(Blocking) 된 것을 의미합니다.
쓰레드가 블로킹 된다는 것은 CPU 가 점유되어 실행되지 못함을 의미합니다.
요청한 작업이 모두 완료되어 응답과 결과를 반환 받습니다. 그동안 CPU 를 점유합니다.

- 논블로킹은 Wait 하지 않고 그냥 수행합니다.
자신이 호출되었을때, 제어권을 바로 자신을 호출한 쪽으로 넘기며
자신을 호출한 쪽에서 다른 작업을 할 수 있도록 하는것을 의미합니다.
자신은 그대로 작업을 이어나갑니다. 쓰레드가 Waiting 하지 않으므로 CPU 제어는 그대로입니다.

 

위의 답변만 잘 읽어도 개념 정리가 잘 될 것 같다!

+ Recent posts